Validate email addresses (syntax, MX, disposable, typo)
validate_emailsScreen signup and lead lists for email deliverability risk: checks syntax, DNS/MX, disposable domains, role accounts, typos, and SPF/DMARC, with valid/risky/invalid verdicts.
Instructions
WHAT: Validate email addresses for deliverability risk: RFC-style syntax, domain existence and MX records (DNS-over-HTTPS), null MX, disposable/temporary inbox domains, role accounts (info@, sales@), free webmail providers, common domain typos with a "did you mean" suggestion, and optional SPF/DMARC presence and policy. WHEN TO USE: cleaning signup or lead lists, checking an address before sending, flagging throwaway or typo signups. WHEN NOT TO USE: for a quick offline format check or parsing "Name " strings use check_email_syntax (free). Does NOT send email or do SMTP mailbox probing, so it cannot confirm that a specific mailbox exists. BEHAVIOR: runs the Fairquery Apify Actor fairquery/email-validator-mx-disposable via the Apify API (DNS lookups via Cloudflare DoH). Requires APIFY_TOKEN. Duplicates (case-insensitive) are skipped. Typical run 3-30 s. COST: paid (billed to your Apify account, pay-per-event): $0.00005 per run + $0.00079 per email row with a verdict; error rows are free. 100 emails ~ $0.08. RETURNS: one email row per unique address; verdict follows reasons[]: INVALID_SYNTAX, DOMAIN_NOT_FOUND, NULL_MX, NO_MAIL_SERVER -> invalid; DISPOSABLE_DOMAIN, ROLE_ACCOUNT, FREE_PROVIDER (per allow* flags), POSSIBLE_TYPO, IMPLICIT_MX_ONLY -> risky; DNS_NOT_CHECKED -> unknown. Error rows are free and never sit next to an email row for the same address: INPUT_EMPTY (nothing to check), MAX_EMAILS_EXCEEDED (once, for the overflow), DNS_LOOKUP_FAILED (one per address whose domain lookup failed, instead of its email row; retryable=true for transient DNS errors, so resend only those addresses). PARAMETERS: emails: entries are split on commas, semicolons and newlines, trimmed, reduced from "Name " to addr, and case-insensitive duplicates are skipped before checking, so a pasted list in one element works and you pay once per unique address; maxEmails caps that unique count (extras get one free MAX_EMAILS_EXCEEDED row), which makes it your spend cap. checkDns=false skips all DNS lookups: domain_exists / has_mx stay null and an address that is otherwise clean gets verdict "unknown" (DNS_NOT_CHECKED) instead of "valid" - it is still billed. checkSpfDmarc only adds has_spf / has_dmarc / dmarc_policy and never changes the verdict; it is ignored when checkDns=false. The three allow* flags only decide whether a condition downgrades an otherwise valid address to "risky": the reason code (ROLE_ACCOUNT, DISPOSABLE_DOMAIN, FREE_PROVIDER) is listed in reasons[] either way, and no flag can rescue an "invalid" address (bad syntax, DOMAIN_NOT_FOUND, NULL_MX, NO_MAIL_SERVER). POSSIBLE_TYPO and IMPLICIT_MX_ONLY are always "risky". Presets: B2B lead list = allowFreeProviders false + allowRoleAccounts false; consumer signups = defaults. EXAMPLE: {"emails":["someone@gamil.com"]} -> verdict "risky", reasons ["POSSIBLE_TYPO"], did_you_mean "someone@gmail.com".
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| emails | Yes | Required. 1-10000 email addresses to validate. Entries may also be comma/semicolon/newline-separated lists or "Name <addr>" forms. Example: ["john.doe@gmail.com","someone@gamil.com"] | |
| checkDns | No | Optional boolean, default true. true looks up MX/A records (DNS-over-HTTPS) to confirm the domain can receive mail; false = syntax/list checks only, clean addresses then get verdict "unknown". Example: false | |
| maxEmails | No | Optional integer 1-100000, default 10000. Safety/spend cap on unique emails per run; addresses beyond it are skipped with one free MAX_EMAILS_EXCEEDED error row. Example: 500 | |
| checkSpfDmarc | No | Optional boolean, default true. true adds has_spf, has_dmarc and dmarc_policy (none|quarantine|reject) per domain; never changes the verdict; needs checkDns=true | |
| allowDisposable | No | Optional boolean, default false = disposable/temporary-inbox domains (mailinator.com, ...) get "risky"; true stops penalising them (DISPOSABLE_DOMAIN still reported) | |
| allowRoleAccounts | No | Optional boolean, default true. false downgrades role mailboxes (info@, sales@, support@, ...; +tags ignored) from "valid" to "risky"; ROLE_ACCOUNT is reported in reasons either way | |
| allowFreeProviders | No | Optional boolean, default true. false downgrades free webmail (gmail.com, outlook.com, yahoo.com, ...) to "risky" - recommended for B2B lead lists |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| count | Yes | Number of rows returned | |
| items | Yes | Result rows; each has a "type" field (data rows or machine-readable "error" rows) |