Bulk Email Verifier — MX, Disposable & Score Check ($0.50/1k) avatar

Bulk Email Verifier — MX, Disposable & Score Check ($0.50/1k)

Pricing

from $0.50 / 1,000 email-verifieds

Go to Apify Store
Bulk Email Verifier — MX, Disposable & Score Check ($0.50/1k)

Bulk Email Verifier — MX, Disposable & Score Check ($0.50/1k)

Bulk email verifier: status, 0-100 score and reason per address from MX, SPF/DMARC, disposable, role and typo checks. $0.50 per 1,000.

Pricing

from $0.50 / 1,000 email-verifieds

Rating

0.0

(0)

Developer

Mohammed Samaan

Mohammed Samaan

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

12 days ago

Last modified

Share

Bulk Email Verifier

Paste a list, chain a dataset, or point at a CSV URL — get back every address with a status, a 0–100 score, and the exact reason, so you can delete the bounces before they wreck your sender reputation.

Who it's for

  • Cold-email agencies and SDR teams cleaning a list before a send
  • Anyone chaining this after a scraper (ours or another) to grade the emails it found before they hit an outreach tool
  • Newsletter and e-commerce lists that need a periodic bounce-risk cleanup

What you get

FieldWhat it is
emailNormalized address
statusvalid / invalid / catch_all / unknown / disposable / risky
score0–100 deliverability confidence
reason / reason_detailMachine-readable code + a plain-English sentence
syntax_validPassed the offline format check
mx_found / mx_hostDomain has a mail destination, and which one
smtp_checkedWhether the mailbox-level check actually ran
smtp_validMail server's verdict on the mailbox, null if not checked
is_disposable / is_role / is_free_providerThrowaway / generic inbox / consumer provider
has_tag / base_email+tag detection and the de-dupe base address
typo_suggestionSuggested fix for a likely-mistyped domain, or null
domain_has_spf / domain_has_dmarcWhether the domain publishes those records
checked_at / duration_msTimestamp and how long the check took

A SUMMARY record with the run's tally is written to the key-value store.

Example output

One real row from a run of this actor (a throwaway address, so the checks stop at the disposable-domain step and no MX or SMTP lookup is made):

{
"email": "throwaway@mailinator.com",
"status": "disposable",
"score": 5,
"reason": "disposable_domain",
"reason_detail": "Throwaway/temporary mailbox provider — will not stay reachable.",
"syntax_valid": true,
"domain": "mailinator.com",
"mx_found": false,
"mx_host": null,
"smtp_checked": false,
"smtp_valid": null,
"is_catch_all": false,
"is_disposable": true,
"is_role": false,
"is_free_provider": false,
"has_tag": false,
"base_email": "throwaway@mailinator.com",
"typo_suggestion": null,
"domain_has_spf": false,
"domain_has_dmarc": false,
"checked_at": "2026-09-28T16:04:31.928Z",
"duration_ms": 0
}

status is one of valid, invalid, catch_all, risky, disposable or unknown; reason is the machine-readable cause.

Input

{
"emails": ["info@apify.com", "someone@gmial.com", "throwaway@mailinator.com"],
"treatRoleAsRisky": true,
"concurrency": 20
}

Instead of (or alongside) emails, you can chain another actor's dataset with inputDatasetId + emailField, or point csvUrl at a CSV file (Google Sheets and Dropbox share links are converted to direct downloads automatically). All three sources merge and de-duplicate in one run.

Verification depth

Every address always gets: syntax check, typo suggestion, plus-tag detection, disposable/role/free-provider lookup, MX lookup, and SPF/DMARC presence check — all free, offline or DNS-only.

SMTP mailbox check is available when a relay is configured. Apify's cloud blocks outbound port 25, so the mailbox-level RCPT TO probe runs through a small relay you point the actor at (relayUrl + relayToken, or the EMAIL_RELAY_URL / EMAIL_RELAY_TOKEN environment variables). A relay is also what lets the actor detect catch-all domains, by probing a random address on the domain first. Without a relay, the run does not fail — it logs a warning, sets smtp_checked: false on every row, and grades from syntax, lists, MX and domain health instead. The relay is open source and ships in this repo under email-relay/.

Pricing

$0.50 per 1,000 emails verified. Addresses that fail the free, offline syntax check are not charged by default (skipInvalidSyntax). Duplicates are removed before verification, so you pay for unique addresses only.

How it compares

No browser, no per-second compute — verification is DNS lookups and (when a relay is configured) short SMTP conversations that stop before DATA, so nothing is ever sent. That keeps this fast and cheap to run against large lists compared to a verifier built around a heavier scraping stack.

Use with n8n / Make / Zapier

Add an Apify integration node, run this actor with your list or dataset ID as input, then read the finished dataset back into your workflow to filter out anything that isn't valid before it reaches your send step.

Errors and limits

How the actor behaves when things go wrong (read from its code):

  • No input. If emails, inputDatasetId and csvUrl produce no addresses, the run logs a warning, saves {"total": 0, "note": "no input emails"} to the SUMMARY key-value record and finishes successfully with an empty dataset. Nothing is charged.
  • Unreadable dataset or CSV. A failed inputDatasetId read or csvUrl download (for example HTTP 403 or 404) logs a warning and that source is skipped; the other sources still run. If the CSV has no detectable email column, it logs a warning and returns nothing from that file. Set emailColumn to the exact header name.
  • Bad syntax. An address that fails the offline syntax check gets status: "invalid", reason: "bad_syntax", and is not charged while skipInvalidSyntax is on (the default). Turn it off and those rows are charged.
  • No mail server. If neither an MX record nor an A record is found within timeoutSecs, the row is invalid / no_mx_record. A DNS timeout and a genuinely missing record are not told apart, so a slow or failing resolver can produce this result for a working domain.
  • No SMTP relay (the default). Apify's cloud blocks outbound port 25, so without a relay every row has smtp_checked: false and mailbox-level results are unknown (mx_only_no_smtp). Catch-all domains are not flagged in this mode. If a configured relay turns out to be unreachable, the run switches to the same MX-only behaviour for all remaining rows and logs one warning.
  • Greylisting. When a relay is used and the mail server defers the check (4xx), the actor retries up to maxRetries times (default 2, max 5) with a growing delay. If it is still deferred the row is unknown / greylisted.
  • Internal error on one address. The row comes back as unknown / verifier_error and the run continues. Because it is a delivered row, it is charged like any other.
  • Charging. One email-verified event per row delivered, except syntax failures (see above). Disposable and no-MX rows are charged. If your max-charge limit is reached the run stops early and keeps what it has.
  • Limits. Duplicates are removed first (case-insensitive). maxEmails defaults to 50,000; addresses beyond it are skipped with a warning. concurrency is clamped to 1 to 50 (default 20) and timeoutSecs to 2 to 60 (default 10). With a relay, at most 3 probes run at once against any single mail server.

FAQ

Why is an address unknown? Either the mail server greylisted the probe and it didn't clear after retries, the server refuses probes from unknown IPs, or no relay was configured for mailbox-level checking. unknown means the check didn't reach a verdict — it isn't a soft "invalid".

Does it detect catch-all domains? Only when a relay is configured — that's what lets the actor probe a random address on the domain to test whether it accepts mail for anything. Without a relay, catch-all domains are not flagged; they come back MX-only.

Do you send email to the addresses? No. The SMTP conversation, when it runs, stops at RCPT TO and never reaches DATA.

Can I re-run it later? Yes — mailboxes go stale. Re-verifying a list every few months is normal practice.

What does the score mean? A 0–100 deliverability confidence built from whichever checks actually ran, adjusted for role/free-provider/typo/plus-tag flags — not a claimed accuracy percentage, since accuracy depends on the mix of domains in your list.

Use it from an AI agent (MCP)

Add this Actor to any MCP client (Claude, Cursor, VS Code) with one URL:

https://mcp.apify.com?tools=leadharbor/bulk-email-verifier

Or call it through the Apify API with an input like this:

{
"emails": [
"info@apify.com",
"someone@gmial.com",
"throwaway@mailinator.com"
],
"checkSmtp": false
}

Returns one row per email: status (valid/invalid/disposable/risky/unknown), 0-100 score and the reason. Results land in the run's default dataset (JSON, CSV or Excel). No login or API key is needed for the sites it reads, and pay-per-event pricing works with Apify's x402 agent payments.

API usage

Run it from your own code with an Apify API token. The input below is this actor's prefilled example.

curl (runs the actor and returns the dataset items):

curl -X POST "https://api.apify.com/v2/acts/leadharbor~bulk-email-verifier/run-sync-get-dataset-items" \
-H "Authorization: Bearer $APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"emails": [
"info@apify.com",
"someone@gmial.com",
"throwaway@mailinator.com",
"nobody@thisdomaindoesnotexist1234567.com"
]
}'

Python (pip install apify-client):

from apify_client import ApifyClient
client = ApifyClient("<APIFY_TOKEN>")
run = client.actor("leadharbor/bulk-email-verifier").call(run_input={
"emails": [
"info@apify.com",
"someone@gmial.com",
"throwaway@mailinator.com",
"nobody@thisdomaindoesnotexist1234567.com"
]
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item)

Changelog

28 Sep 2026 — Buyer max-charge cap now stops the run; MCP agent section. Plus 5 public example tasks with their own pages.

More from leadharbor


Using this actor? A quick review helps other buyers find it: bulk-email-verifier

Find us on RapidAPI