Reason codes
Reason codes
The fixed list of reasons we return with each check. You can write your rules against these codes.
Every reason code
This list is fixed, so you can write rules against it. The plan column shows the lowest plan on which each code counts.
| Code | Plan | Meaning |
|---|---|---|
invalid_syntax | Free | Not a valid email address. Blocks. |
disposable_domain | Free | The domain is on our burner list. Blocks. |
stale_list_domain | Free | The domain is only on an old open list of burner domains that stopped updating in 2023. Many of these domains belong to real businesses now. 40 points, a weak signal: a challenge on its own at the default cutoffs, and never a block on its own. With two earlier signups of the same inbox, a datacenter IP or a hijacked network, it reaches a block at the default cutoffs. If the domain has no mail server, or its mail goes to a burner mail server, no_mx or burner_mx blocks as usual. |
burner_mx | Free | The domain's mail goes to a burner mail server. That server handles mail for three or more known burner domains and no domain on our list of real providers. This catches new burner domains too. Blocks. |
no_mx | Free | The domain cannot receive mail: a null MX record, or no MX record and no A/AAAA record to fall back to. Blocks. A DNS failure or timeout does not count. |
free_subdomain_mail | Free | An address at a subdomain of a dynamic DNS or free subdomain service we list, such as duckdns.org or ddns.net. So alex@myhome.duckdns.org counts and alex@duckdns.org doesn't. 45 points, a challenge at the default cutoffs. If the name can't receive mail, no_mx blocks the signup, so test with a registered name. |
repeat_inbox | Free | The same inbox signed up before on your account, in any of your apps, in the last 7 days. Each earlier signup counts once: another spelling of the inbox (dots or a +tag), or the same address on another app. The same address checked again on the same app is the same signup and adds nothing. With an attempt_id, each attempt_id is one signup. Test calls and signups that failed later count too. 25 points for one earlier signup, 40 for two, 55 for three and 70 for four, which is a block at the default cutoffs. Five or more add 75. |
relay_service | Free | A forwarding service such as SimpleLogin or Hide My Email. 10 points, a weak signal that never blocks alone. From the Starter plan, an alias on a commercial VPN IP with no other signal adds no points, because the two count as one privacy signal. With any other signal, it adds its 10. |
role_account | Free | admin@, info@, support@ and similar. 10 points, a weak signal that never blocks alone. |
plus_alias | Free | The provider treats this spelling as another name for one mailbox, such as Gmail dots or a +tag, so we count it with that mailbox's other spellings. Information only, 0 points. |
young_domain | Free | The email's own domain was registered fewer than 30 days ago. Information only, 0 points, so the result stays the same with or without it. We look up the registration date in the background after a signup arrives, so the first signup from a new domain usually comes without this code. We skip free mail providers, burner domains, and registries whose terms rule out storing the date, such as .uk, .de and .xyz. |
datacenter_ip | Starter | The IP belongs to a hosting or cloud network. A challenge at the default cutoffs. If you lower the block score to 40 or below, it blocks on its own. |
vpn_ip | Starter | The IP is a known commercial VPN exit. Never blocks alone. |
tor_exit | Starter | The IP is a Tor exit node. A challenge at the default cutoffs, never a block alone. |
privacy_relay | Starter | iCloud Private Relay or similar. Information only, because many real people use it. |
ai_agent | Starter | The IP is in a range that an AI agent's operator publishes, such as OpenAI's ranges for ChatGPT. A person who asks an agent to sign them up has a real inbox. So this is information only, 0 points, and datacenter_ip does not count on these addresses. The email, repeat and burst reasons still apply. To challenge agent signups, set this check to Always challenge on the Rules tab. If you set datacenter_ip to Always challenge or Always block, that setting still applies here. |
hijacked_network | Starter | The IP is in an address range on a public list of networks that were hijacked or leased by spam and cybercrime operations. We update the list once a day. 65 points, which is a challenge on its own at the default cutoffs. Together with a role address, a repeat signup or another email signal of 5 points or more, it is a block. Other network reasons and burst_ codes do not add to it toward a block. If you lower the block score to 65 or below, it blocks on its own. |
residential_proxy | Pro | Coming on the Pro plan. Until then this code never appears. |
burst_subnet | Pro | Earlier signups from the same /24 (/48 for IPv6) in the last hour: by default 5 on this app or 10 across your apps. A retried signup counts once. 25 points at the threshold, 40 at twice it, 60 at five times. Like every burst_ code, it can raise a signup to challenge but never to block, because a school or office network can burst too. |
burst_asn | Pro | Earlier signups from the same hosting or VPN network (ASN) in the last hour, across all its subnets: by default 10 on this app or 20 across your apps. Home and mobile networks are not counted. The same points as burst_subnet. Never a block, even together with datacenter_ip, since an office proxy in the cloud is both. |
burst_inbox | Pro | Different spellings of the same inbox (Gmail dots and +tags) on this app in the last 24 hours: by default 2 earlier spellings. The same points as burst_subnet. It overlaps with repeat_inbox, which counts repeats across all your apps, so only the stronger of the two counts. Never a block. |
burst_pattern | Pro | Addresses at the same domain built from the same name and a number of 3 or more digits (jsmith4821@, jsmith9930@) in the last hour: by default 4 earlier on this app or 8 across your apps. Birth years and 1-2 digit numbers do not count, in any script. The same points as burst_subnet. Never a block, since popular names with numbers match by chance. |
burst_domain | Pro | Earlier signups at the same company or custom email domain in the last hour: by default 5 on this app or 10 across your apps. It catches a farmer's own domain that sends every address to one inbox. Mail providers such as Gmail and Outlook, relay services and the domains on our allowlist never count. Domains ending in certain academic suffixes, such as .edu and .ac.uk, don't count either. A person signing up again counts once. 40 points at the threshold, so the 6th signup in an hour is a challenge on its own, and 60 at five times it. Never a block, since colleagues at one company can sign up together. |
confirm_from_datacenter | Free | Second look: the person confirmed their email from a hosting or cloud network, pressing a button or typing a code. 40 points. On a signup challenged by other signals it is a block at the default cutoffs. burst_ points and checks you set to Always challenge don't count toward that block. It adds nothing when the signup came from the same network, such as an office behind one cloud proxy. |
confirm_ua_headless | Free | Second look: a script or headless browser pressed the confirm button or sent the code. 40 points. On a signup challenged by other signals it is a block at the default cutoffs. burst_ points and checks you set to Always challenge don't count toward that block. |
confirm_from_vpn | Free | Second look: the person confirmed from a known commercial VPN exit. 30 points, never a block on its own. |
confirm_from_tor | Free | Second look: the person confirmed from a Tor exit node. 50 points, never a block on its own. |
confirm_network_change | Free | Second look: the confirmation came from another /24 and another network (ASN) than the signup. People sign up on a laptop and confirm on a phone, so it is 10 points and never a block on its own. |
confirm_scanner | Free | Second look: a mail scanner from a Microsoft or Google network opened the confirmation link. We answer allow and keep nothing from it, so the person's own confirmation still gets the second look. 0 points. |
override_allow | Free | Matched one of your allow overrides. Always allows. |
override_block | Free | Matched one of your block overrides. Always blocks. |
Points and cutoffs
Each reason adds points to the score. Network reasons (datacenter, VPN, Tor, privacy relay, hijacked network, residential proxy) describe the same IP, so only the strongest of them counts.
On the Starter plan and up, an email alias on a commercial VPN with no other signal adds only the VPN's points. With any other signal, the alias adds its own 10 points.
By default, a score of 40 marks the signup challenge and 70 marks it block. You can change both cutoffs per app, which changes what the other reasons lead to. A score made only of weak signals (VPN, Tor, privacy relay, role account, relay service, a domain only on an old burner list) can reach challenge but never block.
Some reasons set the result on their own: an override, an invalid address, a known burner domain, a burner mail server, or a domain that cannot receive mail.
Velocity reasons
The velocity reasons (the burst_ codes) each count earlier signups in a fixed window, on the app and across all your apps. You can change the thresholds per app in the dashboard's Velocity section (0 turns one off, otherwise the lowest is 2).
Velocity points count in the score and can raise a signup to challenge but never to block. A block needs the other reasons to reach your block score on their own. Classmates on the same network, colleagues behind an office proxy and people with popular names all produce velocity patterns.