Bulk Email Verifier (syntax, MX, disposable, catch-all, SMTP) avatar

Bulk Email Verifier (syntax, MX, disposable, catch-all, SMTP)

Pricing

from $0.30 / 1,000 results

Go to Apify Store
Bulk Email Verifier (syntax, MX, disposable, catch-all, SMTP)

Bulk Email Verifier (syntax, MX, disposable, catch-all, SMTP)

Verify email lists in bulk: RFC syntax, typo suggestions, MX records, disposable and free provider detection, role accounts, catch-all detection and SMTP mailbox check without sending mail.

Pricing

from $0.30 / 1,000 results

Rating

0.0

(0)

Developer

Rod Services

Rod Services

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

Share

What does Bulk Email Verifier do?

Bulk Email Verifier checks email lists in bulk and tells you which addresses are valid, invalid, risky or unknown. It runs RFC syntax validation, typo suggestions (gmial.com to gmail.com), domain and MX record lookups, disposable email detection, free provider and role account flags. With your own SOCKS5 proxy it also runs a catch-all check and an SMTP mailbox check that talks to the mail server without sending any email.

What valid means. Without the SMTP check, valid means the address is well formed and its domain can receive mail (verificationLevel: "dns"). The mailbox itself is not confirmed. Only rows with verificationLevel: "smtp" were confirmed by the recipient mail server. SMTP needs your own SOCKS5 proxy, because Apify blocks port 25.

Paste addresses or give a CSV URL, click Start, and download clean results as JSON, CSV or Excel. As an Apify Actor you also get an API, scheduling, webhooks, integrations with Make, Zapier and Google Sheets, and run monitoring.

Why use Bulk Email Verifier?

  • Protect sender reputation. Remove hard bounces before a campaign. High bounce rates get domains blocked.
  • Clean signup forms and CRMs. Catch typos like john@gmail.con and throwaway inboxes from Mailinator or 10MinuteMail.
  • Keep B2B lists useful. Flag role accounts such as info@ or sales@ that rarely reach a decision maker.
  • Cheap and fast. 1,000 addresses finish in about 4 seconds in DNS mode. Domains are looked up once and cached.
  • No lock-in. Plain dataset output, API access, no monthly plan.

How to verify an email list

  1. Open the Input tab.
  2. Paste addresses into Email addresses, or put a CSV or text file link into CSV or text file URL.
  3. Leave SMTP mailbox check off unless you have a SOCKS5 proxy. See below.
  4. Click Start. The prefilled 5 address example finishes in a few seconds.
  5. Open the Output tab. Filter by status or download the dataset.

Input

All fields are in the Input tab. JSON example:

{
"emails": ["info@apify.com", "example.user@gmial.com", "test@mailinator.com"],
"emailsFileUrl": "https://example.com/contacts.csv",
"smtpCheck": false,
"socksProxyUrl": "socks5://user:pass@proxy.example.com:1080",
"heloHost": "verify.yourdomain.com",
"fromAddress": "bounce@yourdomain.com",
"checkCatchAll": true,
"timeoutSecs": 10,
"maxConcurrency": 10,
"maxConnectionsPerMx": 2,
"greylistRetrySecs": 60
}
FieldMeaning
emailsAddresses to verify. Blocks separated by new lines, commas or semicolons also work.
emailsFileUrlCSV or text file. Every cell with an @ is used, so headers and other columns are ignored. Max 50 MB.
smtpCheckTurn on the SMTP mailbox and catch-all check. Needs socksProxyUrl on Apify.
socksProxyUrlYour SOCKS5 proxy that can reach port 25. Stored encrypted.
heloHost, fromAddressIdentity used in EHLO and MAIL FROM. Use a domain you control.
checkCatchAllOne extra RCPT per domain with a random address.
greylistRetrySecsWait time before one retry after 4xx answers. 0 disables it.
timeoutSecsTimeout per DNS query and per SMTP step.
maxConcurrencyDomains processed in parallel.
maxConnectionsPerMxParallel SMTP sessions to one mail server.

Duplicates are verified and billed once. Addresses count as duplicates after trimming, removing mailto: or Name <...> wrappers and lowercasing, so INFO@Example.com and info@example.com are one result. Plus tags are kept: jane+news@gmail.com and jane@gmail.com are two results.

Output

One item per unique address. You can download the dataset in various formats such as JSON, HTML, CSV, or Excel.

{
"email": "example.user@gmial.com",
"normalized": "example.user@gmial.com",
"domain": "gmial.com",
"status": "risky",
"reason": "possible_typo",
"verificationLevel": "dns",
"isSyntaxValid": true,
"hasMx": false,
"mxHosts": ["gmial.com"],
"isDisposable": true,
"isFreeProvider": false,
"isRole": false,
"isCatchAll": null,
"smtpChecked": false,
"smtpCode": null,
"smtpMessage": null,
"didYouMean": "example.user@gmail.com",
"checkedAt": "2026-09-27T10:32:25.005Z"
}

A run summary with counts per status and per verification level is saved as SUMMARY in the key-value store. It also shows smtpMode: off, socks, direct or unavailable.

Data fields

FieldDescription
emailAddress as given
normalizedTrimmed, lowercased, punycode domain
statusvalid, invalid, risky or unknown
reasonWhy. See the table below
verificationLeveldns: domain accepts mail, mailbox not confirmed. smtp: mail server answered for this mailbox. syntax: rejected before any lookup
isSyntaxValidPasses RFC 5321/5322 addr-spec rules
hasMxDomain has MX records
mxHostsMail hosts by priority. Domain itself when only an A record exists
isDisposableDomain is on the disposable list
isFreeProviderGmail, Yahoo, Outlook, GMX and about 110 more
isRoleinfo@, admin@, support@, noreply@ and similar
isCatchAllServer accepts any address. null when not tested
smtpCheckedMail server gave a definitive answer for this mailbox
smtpCode, smtpMessageRaw RCPT TO reply
didYouMeanSuggested fix for a likely domain typo
checkedAtISO timestamp

Status and reason

StatusReasonsWhat to do
validmailbox_exists: mailbox confirmed by SMTP, verificationLevel smtpSafe to keep
validmx_found, a_record_only: domain accepts mail, mailbox not checked, verificationLevel dnsKeep, but expect some bounces
invalidinvalid_syntax, domain_not_found, null_mx, no_mail_server, mailbox_not_foundRemove
riskydisposable, catch_all, possible_typo, mailbox_fullReview or remove
unknowndns_error, smtp_blocked, greylisted, smtp_temporary_error, smtp_unreachable, smtp_errorRetry later

Without the SMTP check, valid means syntax, domain and mail server are fine and the domain is not disposable. The mailbox itself is not confirmed, so an address like nobody-12345@gmail.com is still valid at DNS level. Filter on verificationLevel = smtp when you need confirmed mailboxes. a_record_only means the domain has no MX record and mail would go to its A record, per RFC 5321. Many such domains do not accept mail in practice.

How much does email verification cost?

Pay per event, no subscription:

  • $0.30 per 1,000 addresses for syntax, DNS, MX, disposable, role and typo checks.
  • +$0.40 per 1,000 only for addresses where the SMTP check got a definitive answer. That is $0.70 per 1,000 in total.
  • A small start fee of $0.0005 per run, per GB of memory. The default 256 MB run pays it once.

Blocked, greylisted or unreachable SMTP answers are not charged as SMTP checks. The Apify free plan monthly credit covers tens of thousands of DNS level checks. Set Maximum cost per run in run options to cap spend. The Actor stops when it is reached. Addresses past the cap are not written and not charged.

SMTP mailbox check and port 25

The mailbox check needs outbound TCP port 25. Apify blocks port 25, like most cloud providers. The Apify Proxy does not tunnel it either. So on Apify the SMTP step needs your own SOCKS5 proxy:

  1. Rent a small VPS where port 25 is open. Many hosts open it on request.
  2. Set reverse DNS of its IP to a hostname you own, e.g. verify.yourdomain.com.
  3. Run a SOCKS5 server such as Dante with username and password.
  4. Fill socksProxyUrl, heloHost and fromAddress, then turn on smtpCheck.

The Actor tests port 25 before it starts. If it fails, you get a warning, the run continues at DNS level, and no SMTP events are charged. The run summary shows smtpMode.

The SMTP step sends only EHLO, MAIL FROM, RCPT TO and QUIT. It never sends DATA, so no email is delivered.

Tips and advanced options

  • Rate limits. Keep maxConnectionsPerMx at 1 or 2. Domains on Google Workspace or Microsoft 365 share MX hosts, and the limit applies per host.
  • Greylisting. Some servers answer 450 or 451 on first contact. The Actor waits greylistRetrySecs and retries once with the same probe addresses.
  • Big providers. Yahoo and some Microsoft servers accept every RCPT or block probes. Expect catch_all or smtp_blocked there.
  • Speed. DNS mode uses at least 20 parallel domains. 256 MB memory is enough for lists of 100,000+ addresses.

Acceptable use

  • Only verify lists you have a lawful basis to process, for example your own customers or signups under GDPR or similar law. You are the data controller for the addresses you upload.
  • No spam. Do not use this Actor to build or clean lists for unsolicited email, or to guess addresses for harvesting.
  • Respect mail server limits. Do not raise concurrency to hammer servers.
  • The Actor stores results only in your own Apify storage. Delete datasets you no longer need.

FAQ and support

Is the result 100% accurate? No verifier is. Catch-all servers, greylisting and anti-probe policies limit what SMTP can prove. risky and unknown exist for that reason.

Where does the disposable list come from? A pinned snapshot of disposable-email-domains, CC0 licensed, 9,185 domains, commit 0655284. Details in data/disposable-source.json.

Does it send emails? No. There is no DATA command.

What happens if my input is invalid? The run still ends SUCCEEDED and you pay only the small start fee. No address is charged and the dataset stays empty. The run status message explains the problem and the fix, and the same help record is saved in the key-value store under INPUT_ERROR:

{
"error": true,
"errorCode": "EMPTY_INPUT",
"message": "No email addresses in input.",
"howToFix": "Add addresses to \"emails\" ..."
}

Codes: EMPTY_INPUT (no addresses), NO_EMAILS_FOUND (the file has no address), FILE_UNREADABLE (emailsFileUrl cannot be downloaded) and INVALID_INPUT (a wrong socksProxyUrl). Addresses with bad syntax are not an input error: they are verified and returned with status invalid.

Found a bug or need a feature? Open the Issues tab. Custom verification pipelines are available on request.