Email List Cleaner & Validator (Syntax, MX, Disposable)
Pricing
from $0.56 / 1,000 email checkeds
Email List Cleaner & Validator (Syntax, MX, Disposable)
Clean and validate email lists in bulk: syntax, MX records, disposable domains, role addresses, typo fixes and duplicates. No SMTP probing, privacy-friendly.
Pricing
from $0.56 / 1,000 email checkeds
Rating
0.0
(0)
Developer
James Brown
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
Email Validator & List Cleaner (MX, Disposable, Typos)
This email validator and list cleaner checks an email list before you send to it. For every address you get syntax validation, a DNS MX check (with the RFC 5321 A-record fallback), disposable-domain detection, role-address detection (info@, sales@, admin@, enquiries@, kontakt@…), domain typo suggestions (gmial.com → gmail.com), duplicate flags and a plain verdict: deliverable-likely, risky or invalid with the reasons. A ready-made clean CSV of the addresses worth keeping is saved next to the results.
No SMTP probing, no mailbox verification. The actor never connects to a mail server and never sends a message, so it cannot get your IP blocklisted, trigger greylisting or tip anyone off that an address is being tested. The only network traffic about your addresses is DNS lookups of their domains (the part after the @). The part before the @ never leaves the run. That makes it fast, cheap and privacy-friendly: $0.80 per 1,000 addresses.
What the email validator can and cannot tell you
| This actor | |
|---|---|
| Is the address well-formed? | Yes |
| Does the domain exist and can it receive mail (MX, or A/AAAA fallback, null-MX)? | Yes |
| Is the domain a known disposable / throwaway service? | Yes (bundled list, CC0) |
| Is it a shared role mailbox (info@, sales@…)? | Yes |
| Did the user mistype a popular domain (gmial.com)? | Yes, with a suggested fix |
| Does this particular mailbox exist? | No (that needs SMTP probing, which this actor deliberately does not do) |
| Is the domain a catch-all? | No |
A deliverable-likely verdict means "well-formed, the domain accepts mail, and nothing suspicious was found". It is not a guarantee the mailbox exists. Use it to remove the obviously dead, mistyped and throwaway addresses before a send, not as proof of delivery.
What the email list cleaner returns per address
| Field | Meaning |
|---|---|
row | 1-based position among non-blank inputs |
original | The input, trimmed |
normalized | Trimmed, domain lowercased (IDN domains in punycode), Name <addr> and mailto: unwrapped. null if the syntax is invalid |
syntaxValid | RFC 5321/5322 dot-atom syntax check (quoted local parts and IP-literal domains are rejected) |
domain | Lowercase domain |
hasMx | true if the domain has MX records, or none but an A/AAAA record (implicit MX per RFC 5321 §5.1; see mxSource); false if it cannot receive mail; null if the lookup failed |
mxSource | mx, a-fallback or null |
dnsStatus | ok, nxdomain, null-mx (RFC 7505: domain refuses mail), no-records, or error (timeout / SERVFAIL after one retry) |
isDisposable | Domain, or a parent domain, is on the disposable list |
isRoleAddress | Local part is a role mailbox (info, sales, admin, no-reply, enquiries, bookings, accounts, reception, kontakt, ventas, accueil…; dots, hyphens, underscores and +tags ignored) |
typoSuggestion | Likelier domain, e.g. gmail.com for gmial.com |
suggestedEmail | The address with the domain fixed |
duplicateOf, duplicateOfRow | Set on repeats (compared case-insensitively on the normalized address; inputs that are not valid addresses are compared by their trimmed text); duplicateOfRow is the first occurrence |
recoveredAfterRestart | Only present (true) on a row pushed again after a restart; it was not charged a second time |
verdict | deliverable-likely, risky, invalid (null on duplicates, whose first occurrence carries the verdict) |
reasons | Why: see below |
Verdict rules. invalid: bad syntax (syntax:…), domain-not-found, null-mx, no-mail-records. Otherwise risky if any of disposable-domain, role-address, possible-typo, no-mx-a-record-fallback (the domain has a web server record but no MX), dns-unavailable (the lookup failed, so the domain is unknown), internationalised-local-part (valid, but many systems cannot handle it). Otherwise deliverable-likely.
Input
| Field | Description |
|---|---|
emails | List of addresses |
text | Blob: one per line, or separated by commas / semicolons / tabs. Name <a@b.com> and mailto: forms are understood |
csvUrl + csvColumn | Public CSV URL, read as a stream (up to 200 MB). Column by header name or 1-based index; auto-detects headers containing "mail" |
csvHeader | auto / yes / no: whether the first CSV row is a header |
includeRiskyInCleanCsv | Also put risky addresses in the clean CSV. Default off |
Run it with no input and you get an 11-row sample.
Example input
{"emails": ["jane.doe@gmail.com", "Jane.Doe@GMAIL.com", "sam@hotmial.co.uk", "info@gmail.com", "promo@mailinator.com", "user@@broken"]}
Example output (one record shown)
{"row": 3,"original": "sam@hotmial.co.uk","normalized": "sam@hotmial.co.uk","syntaxValid": true,"domain": "hotmial.co.uk","hasMx": true,"mxSource": "mx","dnsStatus": "ok","isDisposable": false,"isRoleAddress": false,"typoSuggestion": "hotmail.co.uk","suggestedEmail": "sam@hotmail.co.uk","duplicateOf": null,"duplicateOfRow": null,"verdict": "risky","reasons": ["possible-typo"]}
Clean-CSV export
When the run ends, two files are saved in the run's key-value store:
clean-emails.csv: oneemailcolumn with the first occurrence of everydeliverable-likelyaddress (plusriskyones if you switched that on). Invalid addresses are never in it. Addresses starting with=,+,-or@are left out (spreadsheet formula risk) and listed in the review file instead.review-emails.csv: everyriskyandinvalidaddress with its reasons andsuggestedEmail, for fixing by hand. Text beginning with= + - @is prefixed with'so spreadsheets do not execute it.
Both are built from the run's dataset when the run finishes, so they are complete even after a restart.
Pricing (pay per event)
| Event | Price | When it is charged |
|---|---|---|
| Actor start | $0.005 | Once per run |
| Email checked | $0.0008 | Per unique address checked (duplicates, blank rows and failed DNS lookups are free) |
| Addresses | Approximate cost |
|---|---|
| 1,000 | $0.805 |
| 10,000 | $8.005 |
| 100,000 | $80.005 |
- Actor start: $0.005 per run (Apify's
apify-actor-startevent). Maximum run memory is capped at 1,024 MB so the start event is never multiplied. - Email checked: $0.0008 per address (
email-checkedevent), charged after the result is saved to the dataset. Syntax-invalid addresses are charged too (first occurrence only): they are a completed check with aninvalidverdict. - Free: duplicates (including repeated invalid inputs such as
N/A), blank rows, and addresses whose DNS lookup failed with a timeout/SERVFAIL (dnsStatus: "error"; those are returned asrisky/dns-unavailable; re-run them later).
Example: 50,000 unique addresses = $40.00 + $0.005. If you set a maximum cost per run, the actor stops cleanly when it is reached.
Performance
Addresses are processed in batches of 500, with up to 50 DNS lookups in flight and one lookup per distinct domain per run (cached). Measured locally (Windows dev machine, Python 3.11, real DNS from a home connection, local file storage, no pricing configured): 403 addresses over 10 domains took about 7 seconds; 5,000 addresses over about 300 distinct domains took about 70 seconds with a peak of about 84 MB resident memory (much of that time is local per-item dataset writes, as with the other actors in this portfolio). Lists with many distinct domains are limited by DNS latency, not CPU; memory is dominated by the interpreter and the bundled disposable list (about 10,000 domains), and the duplicate index holds one short entry per distinct address. These figures were measured locally, not on the Apify platform.
Restarts
Progress is saved to the key-value store (PROGRESS, counters only, never addresses), so a restart or migration continues without re-pushing or re-charging addresses already delivered, and without repeating their DNS lookups. Results are never lost and never double-charged: the few addresses that were in flight when the run was interrupted are pushed again, without a charge, and carry recoveredAfterRestart: true. In rare cases that means a result row appears twice in the dataset (the first copy has no flag); the two CSV exports are built with each row number once, so they contain no repeats.
Data sources, licences and compliance
- Disposable domains: disposable-email-domains
disposable_email_blocklist.conf, CC0 1.0 Universal (public-domain dedication; verified 2026-10-21 against the repository'sLICENSE.txt). Bundled unmodified indata/disposable_domains.txt(upstream commit and licence copy indata/SOURCE.mdanddata/LICENSE-disposable-email-domains.txt). The list is as of the actor's build and is refreshed by releasing a new version. It also contains some typo-squatting domains (e.g.gmial.com), which therefore get bothdisposable-domainandpossible-typo. - Role-address and typo lists: written for this actor (no third-party data).
- Dependencies: dnspython (ISC licence), httpx (BSD-3-Clause), the Apify SDK (Apache-2.0). No GPL/AGPL code.
- ToS / robots.txt: nothing is scraped. DNS is queried through the platform's resolver. The only HTTP access is when you supply a
csvUrl: the actor then fetches that file, identifies itself with a User-Agent, honours the host'srobots.txt(RFC 9309; it refuses if disallowed, and also ifrobots.txtcannot be fetched or returns 5xx/429), re-checks every redirect target, blocks private/internal addresses, and spaces requests about 1 second apart. This cannot be switched off. - Credentials in URLs (
user:pass@host) are not sent: the actor never makes authenticated requests, so use a URL that needs no login. - What is stored: the results go to the run's default dataset and the two CSV files plus
PROGRESSto the run's default key-value store, with standard Apify storage retention for your account/plan. You control and can delete them. The actor keeps nothing outside your run. Addresses are never written to the run log; error messages contain neither addresses nor full URLs. Apart from the domain DNS lookups described above, the addresses are not sent anywhere. - Personal data: email addresses are personal data. You are responsible for having a lawful basis (e.g. UK GDPR / PECR) for processing and mailing the addresses you submit.
Limitations
- No mailbox-level verification. Cannot detect non-existent mailboxes on a working domain, full inboxes or catch-all servers.
- Disposable detection is list-based and only as current as the bundled list; new throwaway domains will be missed. The list can also contain domains you consider legitimate.
- Typo suggestions are advisory: exact for a curated set of common mistakes, plus a conservative one-edit fuzzy match against about 50 popular providers. A real but unusual domain one letter away from a big provider can be flagged.
- Role detection is a word list; unusual role names are not recognised, and a few personal addresses may share a role word.
- Duplicates compare the full normalized address case-insensitively; Gmail dots and
+tagsare not collapsed. - DNS answers reflect the moment of the run, as seen from the platform's resolver. A
dns-unavailablerow means "unknown": re-run it. - Quoted local parts (
"a b"@x.com), comments and IP-literal domains are treated as invalid. - CSV input: quoted multi-line fields are parsed as one record.
csvColumntakes a header name or a 1-based number. If the file changes between a restart and the original run, row numbers may shift. - The platform's dataset retention applies; download your results in time.
FAQ
How do I clean an email list?
Add the addresses to emails, paste them into text, or give a public csvUrl. Download clean-emails.csv from the run's key-value store for the addresses worth keeping, and review-emails.csv for the ones to fix.
Does it verify that a mailbox exists? No. It checks syntax, whether the domain can receive mail (MX), disposable domains, role addresses and likely typos. It never connects to a mail server, so it cannot confirm a specific mailbox.
Can it find disposable email addresses? Yes, against a bundled list of about 10,000 disposable domains. New throwaway domains may be missed until the list is refreshed.
Can it fix typos such as gmial.com?
It suggests the likelier domain in typoSuggestion and suggestedEmail; it does not change your data.
Related Actors
- Phone Number Validator & Formatter: validate and format phone numbers in bulk, offline.
- PDF to Markdown for RAG: turn PDF, DOCX, PPTX and HTML into Markdown for LLMs.
- Domain Health Checker: SPF, DMARC, DKIM and SSL expiry checks for any domain, handy before a mailing.