Validate and score a list of email addresses in Python — checks syntax, MX records, mailbox deliverability, disposable / role flags, and assigns a 0-100 risk score. Drop bounces before they kill your sender reputation.
Python project that batches email address validation through the Bulk Email Verifier Apify actor — a ZeroBounce-backed verifier that returns deliverability, mailbox existence, disposable / role / free-provider flags, MX record presence, and a numeric risk score per address. $1 per 1,000 verifications, no monthly commitment.
Cold-email open rates depend on sender reputation, and reputation is mostly a function of bounce rate. Major inbox providers (Gmail, Outlook, Yahoo) start aggressively spam-foldering or hard-blocking senders whose bounce rate climbs above ~2%. If you bought a list, scraped it off the web, or merged stale CRM data, you're almost guaranteed to have invalid addresses, role inboxes, and disposable domains in there. One clean-up pass before launching a campaign is the difference between a 35% open rate and a 5% open rate.
The classic Python alternatives — email-validator for syntax, dnspython for MX records, custom SMTP RCPT TO probes — get you partial coverage. Commercial verifier APIs (ZeroBounce, NeverBounce, Hunter Verifier) cost $1–$5 per 1,000 verifications with monthly minimums. This actor is built on the same ZeroBounce backend, but with pay-as-you-go pricing and no minimums.
- Cold outreach list cleanup — verify before launching a sequence in Smartlead / Apollo / Instantly.
- Newsletter signup form — verify on submit and reject invalid addresses before they enter your ESP.
- CRM hygiene — quarterly batch verification of every contact email; mark bounces as "do not contact".
- Lead-list buying QC — score a vendor's list before paying for it.
- Account-takeover prevention — flag disposable domains during user signup.
- Sales-handoff validation — verify a lead's email right after they fill out a demo-request form, before the SDR calls them.
- Python 3.10+
- A free Apify account
- No ZeroBounce account needed — billing is metered through Apify
git clone https://github.com/pro100chok/bulk-email-verifier-python.git
cd bulk-email-verifier-python
pip install -r requirements.txt
cp .env.example .env
# paste your APIFY_API_TOKEN
python main.pymain.py verifies a sample of ten mixed-quality emails (some valid corporate addresses, one disposable, one made-up domain) and splits the results into send.csv and drop.csv. Plug your real list into the EMAILS_TO_CHECK constant.
Your Python script posts a JSON request to the actor with a list of up to 50 emails. The actor:
- Validates each address syntactically (RFC 5322 + practical edge cases).
- Resolves the domain's MX records (rejects anything with no MX).
- Opens an SMTP RCPT TO probe to the receiving server to confirm mailbox existence (the ZeroBounce method).
- Flags disposable / temporary / honeypot domains using ZeroBounce's curated lists.
- Flags role-based inboxes (
info@,sales@,support@,noreply@). - Returns a deliverability status, free-provider flag, and risk score.
Up to 50 emails per run; larger lists should be batched in chunks of 50 (see examples/02_load_from_csv.py).
import os
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_API_TOKEN"])
run = client.actor("pro100chok/email-verifier").call(run_input={
"emails": ["test@example.com"],
})
for it in client.dataset(run["defaultDatasetId"]).iterate_items():
print(it){
"address": "hello@anthropic.com",
"status": "valid",
"deliverable": true,
"isDisposable": false,
"isRole": true,
"isFreeProvider": false,
"isCatchAll": false,
"isToxic": false,
"mxFound": true,
"mxRecord": "smtp-in.anthropic.com",
"smtpProvider": "google",
"didYouMean": null,
"riskScore": 12
}status is one of: valid, invalid, catch-all, unknown, spamtrap, abuse. As a rule of thumb, only valid (with low riskScore and isDisposable=false) is safe to send to.
| Parameter | Type | Required | Description |
|---|---|---|---|
emails |
string[] | yes | Up to 50 email addresses per run. |
concurrency |
integer | no | Number of emails verified in parallel. Default 5. Lower if you hit rate-limit warnings on a high-volume provider. |
| File | Demonstrates |
|---|---|
examples/01_basic_usage.py |
Single email check. |
examples/02_load_from_csv.py |
Verify a CSV-loaded prospect list in 50-row chunks. |
examples/03_split_by_quality.py |
Tier results into send / review / drop. |
examples/04_export_to_csv.py |
Pandas export with all flags. |
examples/05_export_to_google_sheets.py |
Append verification runs to a shared Sheet. |
How much does it cost? $1 per 1,000 verifications. Apify's free $5 monthly credit covers 5,000 verifications before billing.
Why is the per-run cap 50?
Each verification involves DNS lookups and an SMTP probe — both slow operations. Capping at 50 per run keeps any one job bounded and lets you parallelize across runs naturally. For larger batches, see examples/02_load_from_csv.py.
How does this compare with email-validator (Python library)?
email-validator only checks syntax and DNS MX. It can't tell you whether the specific mailbox accepts mail. This actor does the SMTP RCPT TO probe — the deciding step for actual deliverability — plus disposable/role/risk flags.
Will the SMTP probe damage my sender reputation? No. The probe runs from ZeroBounce's infrastructure, not yours. Your domain and IP are not involved in the verification step.
What's a "catch-all" domain?
Some domains (especially small businesses) accept email to any address — so a probe always returns "deliverable", but the mailbox you sent to might not actually exist. Catch-all results are conservatively risky; many senders treat them as review, not send.
Can I verify emails for free providers like Gmail / Outlook?
Yes, the actor handles them. Gmail/Yahoo/Outlook addresses get isFreeProvider: true — useful for B2B outreach where you typically want corporate domains.
What about GDPR / CAN-SPAM compliance? Email verification itself isn't regulated — you're just checking whether an address works. Outreach to those addresses is regulated. Stay compliant with whatever rules apply to your jurisdiction and the recipient's jurisdiction.
Can I use this in a signup form? Yes — call the actor synchronously when a user submits the form. Latency is typically 1–3 seconds per email. For best UX, verify asynchronously and notify the user after submit completes.
- Website Contact Scraper — get the emails to verify in the first place.
- Google Maps Scraper — Emails, Reviews & Photos — emails of local businesses.
- Clutch.co Scraper — Companies, Reviews & Contacts — agency contact directory.
See all my actors at apify.com/pro100chok.
MIT — see LICENSE.
Built on top of the Bulk Email Verifier Apify actor.