Atlorium

Половина регистраций — не люди. Как отсечь ботов и одноразовые ящики на входе в воронку

Боты не воруют деньги напрямую — они выжигают бесплатные лимиты, ломают воронку и портят метрики, по которым вы принимаете решения. Собираем светофор проверок на форме регистрации.

10 минут чтения продакт-менеджер · growth · антифрод · разработчик

Понедельник, планёрка. За выходные в продукт пришло 812 новых регистраций — против обычных двухсот. Маркетинг ничего не запускал, трафик органический, все радуются ровно до того момента, пока кто-то не открывает список аккаунтов.

Дальше картина знакомая. Шестьсот с лишним ящиков на четырёх доменах, о которых никто в компании раньше не слышал. Все аккаунты активировали бесплатный триал, каждый выел свою квоту, половина — за первые двадцать минут. Никто не оплатил. И теперь конверсия «регистрация → оплата» за месяц показывает 1,4% вместо привычных 3,8%, а продакт уже поставил в спринт переделку онбординга, потому что «воронка просела».

Онбординг тут ни при чём. Просела не воронка, а данные, по которым о ней судят. Это и есть главная цена фейковых регистраций: деньги они воруют редко, а вот решения ломают регулярно.

Где именно течёт

Фейковая регистрация — это не обязательно злой умысел. Их четыре разновидности, и мотивы у них разные: автоматизированный абуз бесплатного тарифа, ручные «ещё один аккаунт, чтобы добить лимит», аккаунты под накрутку рефералов и просто человек, который не хочет давать вам свою настоящую почту. Первые три надо отсекать, четвёртого — не обидеть.

Бесплатный тариф кормит чужой продукт

Что происходит
За ночь заведено 300 аккаунтов. Ящики разные, домен один и тот же, живёт он ровно десять минут и никакой почты не хранит.
Во что обходится
Каждый аккаунт съел квоту триала: вычисления, письма, место в базе. Триста аккаунтов по 12 ₽ себестоимости — 3 600 ₽ за одну ночь и ноль выручки.
Чем закрывается
Проверка почты возвращает статус do_not_mail с уточнением disposable ещё до того, как аккаунт создан. Один запрос в момент нажатия кнопки.

Регистрации из дата-центра в четыре утра

Что происходит
Двести аккаунтов из одной автономной системы. Города разные, ASN один, тип сети — hosting. Живой человек с ноутбука так не выглядит.
Во что обходится
Скрипт крутит бесплатные лимиты API, а вы платите за исходящий трафик и за место. Плюс подпорченная репутация домена, если на такие аккаунты уходят письма.
Чем закрывается
Расширенный профиль IP отдаёт признаки анонимизации: VPN, прокси, Tor, relay, резидентный прокси, хостинг — и отметку о публичных жалобах на адрес.

Воронка врёт, и команда чинит не то

Что происходит
Конверсия в оплату упала вдвое. Продакт ставит в спринт редизайн онбординга, аналитик неделю ищет проблему в шагах регистрации.
Во что обходится
Неделя работы двух человек и решение, принятое по загрязнённым данным. Знаменатель воронки раздут, числитель не изменился.
Чем закрывается
Помеченные на входе фейки не попадают в отчёт как регистрации. Метрика возвращается к реальной, и чинить становится нечего.

Сколько это стоит и когда проверка окупается

Считать надо не «сколько украли», а «сколько стоит обслуживать регистрацию, которая никогда не превратится в клиента». Формула короткая, но допущения в ней придётся взять свои — чужие цифры тут бесполезны.

Обозначим: N — регистраций в месяц, p — доля фейков среди них, L — себестоимость одного фейкового аккаунта (compute + письма + хранение + доля поддержки), C — цена проверок на одну регистрацию. Проверки окупаются, пока C < L × p. Всё, что сверх этого, — уже про качество метрик, а не про прямые деньги.

Параметр Пример (подставьте свои) Откуда взять
N — регистраций в месяц 5 000 Аналитика, шаг «аккаунт создан»
p — доля фейков 0,4 Ручная разметка выборки за месяц: кто хоть раз вернулся на второй день
L — себестоимость фейка 12 ₽ Инфраструктурный счёт ÷ число активных триалов
Потери в месяц (N × p × L) 24 000 ₽ Столько уходит на аккаунты, которые не станут клиентами
Бюджет на проверки (L × p) до 4,8 ₽ на регистрацию Верхняя граница, при которой проверка ещё в плюсе

Три проверки на регистрацию стоят доли копейки за запрос (актуальные цифры — на странице тарифов, они меняются, а статья остаётся). До потолка в 4,8 ₽ там далеко — то есть вопрос «окупится ли» на объёмах от нескольких сотен регистраций в месяц просто не стоит. Стоит другой вопрос: как не выкинуть вместе с ботами живых людей. Ему и посвящена вся оставшаяся статья.

Светофор на форме регистрации

Проверок три, они независимы, и порядок у них не случайный: сначала то, что отсекает больше всего и стоит дешевле всего.

Красный сигнал почты: ящика нет или писать на него нельзя

Сервис «Проверка почты» отвечает на вопрос «дойдёт ли письмо», а не «читает ли его человек». Он возвращает один из семи статусов, и для формы регистрации важны не все.

status Что это значит Что делать на регистрации
Valid Ящик есть, домен принимает почту Пропустить
Invalid Ящика не существует или домен почту не принимает Не создавать аккаунт: письмо с подтверждением отскочит в любом случае
DoNotMail + subStatus: disposable Одноразовый ящик на десять минут Сильнейший сигнал абуза. Тяжёлый вес в скоринге или прямой отказ
DoNotMail + subStatus: role_based Ролевой адрес отдела: info, sales, support В B2C — подозрительно. В B2B — норма, вес нулевой
SpamTrap / Abuse Спам-ловушка или адрес с историей жалоб Отказ. Письмо на такой адрес портит репутацию домена
CatchAll Домен отвечает «валидно» на любой ящик — проверить конкретный снаружи нельзя Неопределённость, а не вина. Небольшой вес, дальше решают другие сигналы
Unknown Сервер домена не ответил, применил greylisting или анти-спам Считать сигнал отсутствующим. Такой запрос не тарифицируется

Кроме статуса в карточке есть domainAgeDays — возраст домена. Домен, которому три недели, для корпоративной почты выглядит странно. И didYouMean: если человек написал «gmial.com», ему можно показать подсказку прямо в форме вместо отказа. Это не антифрод, это вежливость, но она поднимает конверсию у живых.

Жёлтый сигнал IP: адрес прячется

Расширенный режим «Профиля IP» (extended=true) добавляет к геолокации секцию privacy — ровно те признаки, ради которых его и зовут: isVpn, isProxy, isTor, isRelay, isHosting и isResidentialProxy. Плюс serviceName, если сервис анонимизации удалось опознать, и секция abuseReports с флагом flagged — есть ли на адрес публичные жалобы.

Отдельно стоит asn.type и flags.isHosting. Регистрация из дата-центра — это не «человек за VPN», это чаще всего вообще не человек: браузер живого пользователя не запускают в облаке ради того, чтобы завести аккаунт в вашем SaaS.

Зелёный сигнал телефона: номер вообще существует

Если на регистрации собирается номер, его стоит разобрать до того, как на него уйдёт SMS. Сервис «Валидация телефона» работает офлайн, по справочнику мировой нумерации, и отвечает на вопрос «может ли такой номер существовать и как он правильно записывается». Поле isValid означает, что номер попадает в реально выделенный в его стране диапазон. «8 (999) 000-00-00» проходит любую регулярку и не проходит эту проверку.

Что ещё полезно из ответа: numberType (номер VoIP на регистрации в B2C-продукте — слабый, но заметный сигнал), countryCode (страна номера, которую можно сопоставить со страной IP) и e164 — канонический вид, в котором номер надо хранить, чтобы потом не ловить дубли «+79161234567» и «8 916 123 45 67».

Скоринг: сумма сигналов и три исхода

Одиночный сигнал не работает. Забаните всех с VPN — потеряете корпоративных клиентов. Забаните все ролевые адреса — потеряете B2B, где на демо приходит именно sales-ящик. Забаните всех с бесплатной почты — потеряете вообще всех.

Работает сумма. Каждому признаку — вес, веса складываются, дальше два порога и три исхода.

Сигнал (поле ответа) Вес Почему столько
Почта: status = Invalid жёсткий отказ Это не подозрение, а факт: ящика нет, подтверждение не дойдёт
Почта: status = SpamTrap или Abuse жёсткий отказ Письмо на такой адрес ударит по репутации домена
Почта: subStatus = disposable +40 Одноразовый ящик заводят ради одноразового аккаунта
IP: privacy.isTor +35 Редкий канал и очень частый у автоматизации
IP: privacy.isResidentialProxy +30 Единственная причина покупать такой прокси — выглядеть домашним пользователем
IP: flags.isHosting или asn.type = hosting +25 Из дата-центра руками не регистрируются
IP: abuseReports.flagged +20 На адрес уже публично жаловались
IP: privacy.isVpn или privacy.isProxy +10 Массовое явление у живых людей. Сам по себе не значит ничего
Телефон: isValid = false +30 Номер введён «лишь бы прошло»
Телефон: numberType = Voip +10 Дешёвый одноразовый номер. Но у части людей это рабочий номер
Телефон: страна номера ≠ страна IP +5 Слабый сигнал: командировки, релокация, роуминг
Почта: domainAgeDays < 90 +10 Домен моложе трёх месяцев под корпоративную почту — редкость
Почта: status = CatchAll +5 Неопределённость, а не вина: так настроены многие корпоративные домены
Почта: subStatus = role_based +10 в B2C / 0 в B2B Единственный вес, который зависит от вашего рынка

Пороги в первой версии я бы взял такие: меньше 30 — пропустить, 30–59 — потребовать подтверждение (код из письма, SMS, капча, ручная модерация — что дешевле), 60 и выше — отклонить с возможностью написать в поддержку. Эти числа не истина, а точка старта: они соответствуют логике «одного сильного сигнала мало, двух — достаточно для вопроса, трёх — для отказа».

Настраивать их надо на своих данных, и вот единственный способ, который работает. Возьмите месяц исторических регистраций, посчитайте по ним скоринг задним числом (данные уже есть в логах: почта, IP, номер) и разметьте по факту: кто вернулся на второй день, кто оплатил, кто выжег лимит и исчез. Дальше смотрите не на общее число пойманных, а на две цифры: сколько платящих клиентов попало бы под отказ и сколько ботов прошло бы мимо. Первая стоит вам выручки, вторая — 12 ₽ по формуле выше. Двигать порог отказа вверх почти всегда выгоднее, чем вниз: ложный отказ платящему клиенту дороже пропущенного бота на два порядка.

Код: три запроса и одна функция

Все примеры ниже работают с публичным демо-ключом ak_sandbox_demo_mockdata_v1 — копируйте и запускайте, регистрация не нужна. На демо-ключе API отдаёт моки: правдоподобные, но сгенерированные данные. Они детерминированы — один и тот же запрос всегда даёт один и тот же ответ, поэтому на них удобно писать тесты. Настоящие данные приходят только с личным ключом.

Проверка почты: что приходит на одноразовый ящик

curl -H "Authorization: Bearer ak_sandbox_demo_mockdata_v1" \
     "https://atlorium.com/api/emailvalidation?email=test@disposable.example.com"
        

import requests

BASE = "https://atlorium.com"
HEADERS = {"Authorization": "Bearer ak_sandbox_demo_mockdata_v1"}


def check_email(email: str) -> dict:
    resp = requests.get(
        f"{BASE}/api/emailvalidation",
        params={"email": email},
        headers=HEADERS,
        timeout=10,
    )
    resp.raise_for_status()
    return resp.json()


card = check_email("test@disposable.example.com")

# status: Valid | Invalid | CatchAll | Unknown | SpamTrap | Abuse | DoNotMail
if card["status"] in ("Invalid", "SpamTrap", "Abuse"):
    raise ValueError("Аккаунт не создаём: письмо с подтверждением не дойдёт")

if card["subStatus"] == "disposable":
    print("Одноразовый ящик — вес 40 в скоринг")
        

using System.Net.Http.Json;

var http = new HttpClient { BaseAddress = new Uri("https://atlorium.com") };
http.DefaultRequestHeaders.Add("Authorization", "Bearer ak_sandbox_demo_mockdata_v1");

// Адрес обязательно кодируем: символ «плюс» и кириллица в query ломают запрос.
var email = Uri.EscapeDataString("test@disposable.example.com");
var card = await http.GetFromJsonAsync<JsonElement>($"/api/emailvalidation?email={email}");

var status = card.GetProperty("status").GetString();
var subStatus = card.TryGetProperty("subStatus", out var s) ? s.GetString() : null;

// Invalid, SpamTrap и Abuse — жёсткий отказ: это не подозрение, а факт.
var hardFail = status is "Invalid" or "SpamTrap" or "Abuse";
var disposable = subStatus == "disposable";
        

{
  "email": "test@disposable.example.com",
  "status": "DoNotMail",
  "statusRaw": "do_not_mail",
  "subStatus": "disposable",
  "account": "test",
  "domain": "disposable.example.com",
  "freeEmail": false,
  "catchAllDomain": false,
  "didYouMean": null,
  "domainAgeDays": 3821,
  "smtpProvider": "zoho",
  "mxFound": true,
  "mxRecord": "mx1.disposable.example.com",
  "activeInDays": null,
  "activeFirstSeen": null,
  "processedAtUtc": "2026-07-14T09:12:44Z",
  "elapsedMs": 486,
  "deliverable": false
}
        

Тот же вызов на шести языках (Python, TypeScript, Go, Java, C#, PHP) — в репозитории email-verification-api-client. Примеры запускаются сразу: ключ в них уже стоит демонстрационный.

Поле deliverable — это true ровно для Valid и ни для чего больше: если нужен один булев ответ «можно писать», берите его. А statusRaw хранит статус ровно в том виде, в каком его вернул источник (do_not_mail): пригодится, если источник когда-нибудь заведёт новое значение, о котором наш enum ещё не знает.

В песочнице у проверки почты есть удобная деталь: домены-сценарии. Обратитесь к disposable.example.com, role.example.com, invalid.example.com, catchall.example.com — и получите нужную ветку ответа, не дожидаясь, пока она встретится в бою. Автотесты для правил скоринга пишутся прямо по ним.

Профиль IP и разбор номера

# Расширенный профиль IP — признаки анонимизации и жалобы
curl -H "Authorization: Bearer ak_sandbox_demo_mockdata_v1" \
     "https://atlorium.com/api/ipinfo/45.83.91.14?extended=true"

# Разбор номера. Знак «+» в URL кодируется как %2B
curl -H "Authorization: Bearer ak_sandbox_demo_mockdata_v1" \
     "https://atlorium.com/api/phone/%2B79161234567"
        

const HEADERS = { Authorization: "Bearer ak_sandbox_demo_mockdata_v1" };

async function ipProfile(ip) {
  const r = await fetch(
    `https://atlorium.com/api/ipinfo/${ip}?extended=true`,
    { headers: HEADERS }
  );
  return r.json();
}

async function phoneCard(number) {
  // encodeURIComponent превратит «+» в %2B — без этого «плюс» дойдёт как пробел.
  const r = await fetch(
    `https://atlorium.com/api/phone/${encodeURIComponent(number)}`,
    { headers: HEADERS }
  );
  return r.json();
}

const ip = await ipProfile("45.83.91.14");
const phone = await phoneCard("+79161234567");

// privacy приходит ТОЛЬКО в расширенном режиме — в базовом секции просто нет.
const hidden = ip.privacy?.isTor || ip.privacy?.isResidentialProxy;
const fromDataCenter = ip.flags?.isHosting === true;
const badNumber = phone.number.isValid === false;
        

# GET /api/ipinfo/45.83.91.14?extended=true
{
  "ip": "45.83.91.14",
  "tier": "Extended",
  "isBogon": false,
  "hostname": "node-14.example-hosting.net",
  "geo": {
    "city": "Frankfurt am Main",
    "country": "DE",
    "countryCode": "DE",
    "timezone": "Europe/Berlin",
    "accuracyRadiusKm": 50
  },
  "asn": {
    "asn": "AS200000",
    "name": "Example Hosting",
    "domain": "example-hosting.net",
    "route": "45.83.91.0/24",
    "type": "hosting"
  },
  "flags": {
    "isAnonymous": true,
    "isAnycast": false,
    "isHosting": true,
    "isMobile": false,
    "isSatellite": false
  },
  "privacy": {
    "isVpn": true,
    "isProxy": false,
    "isTor": false,
    "isRelay": false,
    "isHosting": true,
    "isResidentialProxy": false,
    "serviceName": "DemoVPN"
  },
  "hostedDomains": { "total": 137 },
  "abuseReports": {
    "flagged": true,
    "detailsUrl": "https://www.abuseipdb.com/check/45.83.91.14"
  }
}

# GET /api/phone/%2B79161234567
{
  "input": "+79161234567",
  "number": {
    "isValid": true,
    "isPossible": true,
    "e164": "+79161234567",
    "international": "+7 916 123-45-67",
    "national": "8 (916) 123-45-67",
    "rfc3966": "tel:+7-916-123-45-67",
    "countryCallingCode": 7,
    "countryCode": "RU",
    "country": "Россия",
    "numberType": "Mobile",
    "originalCarrier": "МТС",
    "location": null,
    "timeZones": ["Europe/Moscow"]
  },
  "elapsedMs": 3
}
        

Тот же вызов на шести языках (Python, TypeScript, Go, Java, C#, PHP) — в репозитории ip-geolocation-api-client. Примеры запускаются сразу: ключ в них уже стоит демонстрационный.

Две оговорки по этому ответу. Секция privacy приходит только при extended=true — в базовом режиме её просто нет, и код должен это переживать. А карточка номера в песочнице всегда валидна: разбор офлайновый, ветвиться моку негде, и вариант isValid: false вы увидите только с личным ключом на реально кривом номере.

Скоринг: складываем сигналы и принимаем решение

# Прогон правил по сценарным доменам песочницы: каждый даёт свою ветку ответа
for d in disposable role invalid catchall; do
  curl -s -H "Authorization: Bearer ak_sandbox_demo_mockdata_v1" \
       "https://atlorium.com/api/emailvalidation?email=test@$d.example.com" \
    | jq -r '"\(.domain)\t\(.status)\t\(.subStatus)"'
done
        

HARD_FAIL_STATUSES = ("Invalid", "SpamTrap", "Abuse")

# B2B-продукт: ролевой адрес sales@ — обычный клиент, а не бот. В B2C поставьте 10.
ROLE_BASED_WEIGHT = 0


def score(email_card: dict, ip_card: dict, phone_card: dict | None) -> int:
    """Сумма весов. Чем больше — тем меньше похоже на живого человека."""
    points = 0

    if email_card["status"] in HARD_FAIL_STATUSES:
        return 100  # факт, а не подозрение: подтверждение не дойдёт

    sub = email_card.get("subStatus")
    if sub == "disposable":
        points += 40
    if sub == "role_based":
        points += ROLE_BASED_WEIGHT
    if email_card["status"] == "CatchAll":
        points += 5

    age = email_card.get("domainAgeDays")
    if age is not None and age < 90:
        points += 10

    # Расширенный режим: секции privacy в базовом ответе нет вовсе.
    privacy = ip_card.get("privacy") or {}
    flags = ip_card.get("flags") or {}
    if privacy.get("isTor"):
        points += 35
    if privacy.get("isResidentialProxy"):
        points += 30
    if flags.get("isHosting"):
        points += 25
    if (ip_card.get("abuseReports") or {}).get("flagged"):
        points += 20
    if privacy.get("isVpn") or privacy.get("isProxy"):
        points += 10  # живых людей за VPN больше, чем ботов

    if phone_card:
        number = phone_card["number"]
        if not number["isValid"]:
            points += 30
        if number["numberType"] == "Voip":
            points += 10
        ip_country = (ip_card.get("geo") or {}).get("countryCode")
        if ip_country and number.get("countryCode") != ip_country:
            points += 5

    return points


def decide(points: int) -> str:
    if points >= 60:
        return "reject"     # с возможностью написать в поддержку
    if points >= 30:
        return "challenge"  # код из письма, SMS или капча
    return "allow"
        

// Веса вынесены в конфиг, а не зашиты в код: пороги придётся двигать
// по факту, и делать это перевыкаткой сервиса — плохая идея.
public sealed record SignupSignals(
    string EmailStatus,
    string? EmailSubStatus,
    int? DomainAgeDays,
    bool IsTor,
    bool IsResidentialProxy,
    bool IsHosting,
    bool IsFlagged,
    bool IsVpnOrProxy,
    bool? PhoneIsValid,
    string? PhoneType);

public static int Score(SignupSignals s)
{
    if (s.EmailStatus is "Invalid" or "SpamTrap" or "Abuse")
        return 100;

    var points = 0;

    if (s.EmailSubStatus == "disposable") points += 40;
    if (s.EmailStatus == "CatchAll") points += 5;
    if (s.DomainAgeDays is < 90) points += 10;

    if (s.IsTor) points += 35;
    if (s.IsResidentialProxy) points += 30;
    if (s.IsHosting) points += 25;
    if (s.IsFlagged) points += 20;
    if (s.IsVpnOrProxy) points += 10;

    if (s.PhoneIsValid == false) points += 30;
    if (s.PhoneType == "Voip") points += 10;

    return points;
}

public static string Decide(int points) => points switch
{
    >= 60 => "reject",
    >= 30 => "challenge",
    _ => "allow",
};
        

Тот же вызов на шести языках (Python, TypeScript, Go, Java, C#, PHP) — в репозитории email-verification-api-client. Примеры запускаются сразу: ключ в них уже стоит демонстрационный.

Порядок вызовов имеет значение для счёта. Почту проверяйте первой — она отсекает больше всего и делает остальные запросы ненужными. Профиль IP запрашивайте только для тех, кто прошёл почту. Номер — вообще на втором шаге регистрации, когда человек уже показал, что он не скрипт. Считать все три сигнала для каждого визита формы не нужно.

Чего эти проверки не умеют

Раздел, ради которого стоит читать любую статью про антифрод. Вот что три сервиса выше не делают, и никакие настройки этого не изменят.

Проверка почты не отправляет письмо и не проверяет, читает ли человек ящик. Она отвечает на вопрос доставляемости: существует ли ящик, принимает ли домен почту, не одноразовый ли он, не ловушка ли. Подтверждение по коду из письма решает другую задачу и проверкой не заменяется — они дополняют друг друга.

Статус CatchAll — это честное «не знаю». Домен настроен принимать почту на любой адрес, и существование конкретного ящика снаружи проверить нельзя ни нам, ни кому-либо ещё. Так живут многие корпоративные домены. Штрафовать за это тяжёлым весом — прямой способ отсечь B2B-клиентов.

Данные об IP обезличены: это сведения о сети и адресе — владелец диапазона, автономная система, признаки анонимизации, публичные жалобы. Кто именно сидел за этим адресом, сервис не сообщает: таких данных у него нет. Геолокация IP вообще приблизительна — в ответе есть поле accuracyRadiusKm, и оно нередко исчисляется десятками километров. Строить на нём правила уровня «пользователь не из Москвы — отказ» не стоит.

И главное ограничение, общее для всех трёх. Мотивированный злоумышленник обходит любой из этих сигналов: покупает почту на настоящем домене, берёт резидентный прокси, который выглядит домашним, и настоящую SIM-карту. Задача проверок — не остановить целевую атаку, а сделать массовую автоматизацию невыгодной. Тысяча аккаунтов через одноразовые ящики и дата-центр стоит ноль. Тысяча аккаунтов с настоящими SIM-картами и резидентными прокси стоит денег — и обычно это уже дороже того, что можно выжать из вашего бесплатного тарифа.

Частые вопросы

Частые вопросы

Как определить одноразовую почту при регистрации?

Проверка почты возвращает статус DoNotMail с уточнением subStatus = disposable. Это значит, что домен относится к сервисам временной почты, которая живёт минуты. Держать собственный список таких доменов бессмысленно: они появляются быстрее, чем список обновляется.

Можно ли блокировать всех, кто регистрируется через VPN?

Нет. Через корпоративный VPN работает половина сотрудников компаний с удалёнкой, и среди них ваши платящие клиенты. Признак isVpn стоит использовать как один из слагаемых скоринга с небольшим весом, а решение принимать по сумме сигналов. Гораздо весомее признаки isTor, isResidentialProxy и регистрация из дата-центра.

Проверка почты отправляет письмо на адрес?

Нет. Сервис проверяет доставляемость: есть ли у домена MX-запись, принимает ли сервер почту, существует ли ящик, не одноразовый ли домен и не спам-ловушка ли адрес. Письмо при этом не отправляется. Подтверждение по коду из письма — отдельный шаг, который проверку не заменяет и не заменяется ею.

Можно ли по номеру телефона понять, что он активен и кому принадлежит?

Нет, и такой возможности у сервиса нет в принципе. Разбор номера выполняется офлайн по справочнику мировой нумерации: он показывает, что номер записан правильно и попадает в реально выделенный диапазон. Есть ли за номером живой абонент и кто он — сведения из сети оператора, мы их не получаем и не отдаём.

Сколько запросов нужно на одну регистрацию?

От одного до трёх. Почту проверяют всегда, профиль IP — только для тех, кто прошёл проверку почты, номер — на втором шаге регистрации, если он вообще собирается. Оплата идёт по факту запроса, без подписки, а статус Unknown у почты и ошибка 503 не тарифицируются вовсе.

Что делать с адресом на catch-all домене?

Считать неопределённостью, а не признаком фрода. Домен принимает почту на любой адрес, поэтому существование конкретного ящика проверить снаружи невозможно ни одним способом. Так настроены многие корпоративные домены, поэтому вес в скоринге должен быть минимальным, а решение — приниматься по другим сигналам.

Сервисы из этой статьи

Проверка почты

Проверка доставляемости адреса: существует ли ящик, MX, catch-all, одноразовый ящик, спам-ловушка, подсказка по опечатке

Расширенный профиль IP

Всё из базового плюс владелец сети (ASN/организация), VPN/прокси/Tor, контакт для жалоб и отметка о жалобах

Валидация телефона

Разбор номера офлайн: валидность, формат E.164, страна, тип номера, оператор диапазона, регион, часовые пояса. Активность номера в сети не проверяется

Попробовать прямо сейчас — без регистрации

Демо-ключ ak_sandbox_demo_mockdata_v1 — публичный и общий для всех. С ним API отвечает моками: данные правдоподобные, но сгенерированные, и они не меняются от запроса к запросу — на них удобно писать тесты. Настоящие данные приходят с личным ключом.

curl -H "Authorization: Bearer ak_sandbox_demo_mockdata_v1" \
     https://atlorium.com/openapi/email_ru.json
Полезно? Перешлите коллеге: Telegram VK

Восстанавливаем соединение…

Похоже, связь с сервером ненадолго прервалась. Переподключаемся автоматически — пожалуйста, подождите несколько секунд.

Не удалось переподключиться

Проверьте интернет-соединение. Можно повторить попытку или обновить страницу.

Сессия устарела

Соединение восстановлено, но сессию нужно перезагрузить. Обновите страницу, чтобы продолжить.