Bulk Email Verifier $1/1k: CSV, Sheets & Datasets
Pricing
from $1.00 / 1,000 email verifieds
Bulk Email Verifier $1/1k: CSV, Sheets & Datasets
✅ $1 per 1,000 emails, no subscription ✅ Paste a list, pick a lead-scraper dataset, upload a CSV or share a Google Sheet ✅ Keeps every column ✅ Syntax, MX, mailbox, catch-all & disposable checks ✅ Duplicates and non-addresses free ✅ Output to dataset or Google Sheet ✅ Resumable, no double charge
Pricing
from $1.00 / 1,000 email verifieds
Rating
0.0
(0)
Developer
Tenzin Phuntsok
Maintained by CommunityActor stats
0
Bookmarked
3
Total users
2
Monthly active users
14 days ago
Last modified
Categories
Share
Clean your email list before you send. Paste addresses, point at a lead-scraper dataset, upload a CSV or share a Google Sheet, and get back every row with a clear verdict: valid, risky (catch-all or unknown) or invalid (no mailbox, dead domain, disposable, typo). Keeps every column you gave it, verifies each duplicate only once, skips blanks and non-addresses for free, and can write the cleaned list straight into a Google Sheet.
What does Bulk Email Verifier do?
Email verification checks whether an address can receive mail without sending anything. For each address this Actor checks the format, looks up the domain's mail servers, asks the mail server whether the mailbox exists, and detects catch-all domains, disposable services and role addresses (info@, sales@). The mailbox check runs through MillionVerifier, an established verification service, so you get the same accuracy as the big list-cleaning tools at a fraction of the price and inside your Apify workflow (schedules, API, integrations, chaining with scrapers).
- Three ways in: paste a list; pick the dataset of another Actor (LinkedIn, Apollo, Google Maps or any lead scraper) and the email column is found automatically; upload a CSV/TXT or paste a Google Sheet link.
- Every column kept: name, company, phone and anything else travel with the address into the output, so the result is your enriched list, not just a list of emails.
- Free pre-checks: duplicates are verified once, blank cells and text that is not an address cost nothing, and a domain that has no mail server is decided locally in milliseconds (that verdict is still one charged address).
- Plain-English reasons:
reasonexplains each verdict ("The mail server says this mailbox does not exist"), next to the technicalsubresultcode. - Typo fixes:
didYouMeansuggestsjane@gmail.comforjane@gmial.com. - Output filter: all rows, only valid ones, or valid plus risky.
- Google Sheets: tick a box and the results land in your sheet (via our Dataset to Google Sheets Sync Actor).
- Fast and finishes: around 900 addresses a minute with the default settings (measured on the platform); parallel checks, per-address timeout, automatic retries, a second look at "unknown" answers (greylisting), and a run that stops cleanly before the platform timeout with everything so far saved. If a run stops early, Resurrect it in Console and it continues where it left off without paying again for what was verified.
Why verify email lists?
Mail providers judge you by your bounce rate. Above roughly 2% bounces, deliverability drops for everyone you write to, and cold-email tools suspend accounts. Scraped and purchased lists typically contain 10-30% dead addresses. Verifying first:
- protects your sending domain and keeps campaigns in the inbox,
- cuts the cost of tools that bill per contact,
- removes fake sign-ups and typos from forms and CRMs,
- lets you segment by risk (send to valid now, warm up risky separately).
How to verify an email list
- Open the Input tab. Paste addresses into Email addresses (one per line), or pick a dataset under Dataset from another Actor, or upload a file / paste a Google Sheet link under CSV / TXT file or Google Sheet (the sheet must be shared as "Anyone with the link can view").
- Optionally choose Which rows to output (all, valid only, valid and risky).
- Optionally paste a Google Sheet link under Output to receive the results in a sheet. Share that sheet as Editor with the service account shown in the Dataset to Google Sheets Sync README (the run log prints it too).
- Click Start. The Output tab shows one row per input row; the Storage > Key-value store > SUMMARY record has the counts, warnings and the sheet status.
- Download as CSV, Excel or JSON, or pipe the dataset into the next Actor.
To clean a scraper's output automatically, add this Actor as an integration on the scraper's run or run both from a schedule.
Input
| Field | What it does |
|---|---|
emails | Pasted addresses. Jane <jane@x.com> and mailto: links are understood. |
datasetId | A dataset with an email column. Other columns are kept. |
emailField | Column name holding the address (nested contact.email works). Empty = detected automatically. |
fileUrl | Uploaded CSV/TXT (up to 20 MB), a public file URL, or a Google Sheet link (shared "anyone with the link"). Header row optional. XLSX: export to CSV first. |
outputFilter | all (default), valid (result ok), valid-and-risky (ok, catch_all, unknown). |
keepInputFields | Copy the other columns into the output rows (default on). |
googleSheetUrl, googleSheetTab, googleSheetMode | Also write the results to a Google Sheet tab, replacing it or appending. |
recheckUnknown | Ask a second time when a server answered "try later" (default on, this Actor does not charge extra for it). |
verificationTimeoutSecs | Seconds to wait for a mail server per address (default 15, 2-60). |
maxConcurrency | Parallel checks (default 20). Speed depends mostly on how fast the mail servers answer. |
maxEmails | Stop reading input after this many rows (default 100,000, max 500,000). |
millionVerifierApiKey | Optional: your own MillionVerifier API key. Checks are paid from your credits and this Actor charges only a small platform fee per address. |
Output
One dataset row per input row, in input order. Your original columns come first, then the verification fields. You can download the dataset as JSON, CSV, Excel or HTML.
{"Name": "Jane Doe","Company": "Acme","email": "jane.doe@acme.com","result": "ok","quality": "good","subresult": "ok","reason": "Mailbox exists and accepts mail","isFree": false,"isRole": false,"didYouMean": null,"duplicateOf": null,"verifiedBy": "millionverifier","verifiedAt": "2026-10-09T14:02:11.482Z","error": null}
| Field | Meaning |
|---|---|
email | The address that was checked (trimmed, domain lower-cased). emailInput holds the original text when it differed. |
result | ok (deliverable), catch_all (domain accepts everything, mailbox unconfirmed), unknown (server did not answer conclusively), invalid, disposable, error (the check itself failed; not charged). |
quality | good, risky or bad: the send / warm-up / drop decision. |
subresult | Technical detail code: no_mailbox, mailbox_full, dns_no_mx, dns_no_domain, syntax, greylisted, anti_spam_system, ... |
reason | The same in plain English. |
isFree | Free mailbox provider (Gmail, Outlook, Yahoo...). |
isRole | Role address (info@, support@...), usually poor for personal outreach. |
didYouMean | Suggested correction for a likely typo. |
duplicateOf | Set when the same address appeared earlier in the input; it carries the first verdict and was not charged again. |
verifiedBy | local (format or DNS decided it) or millionverifier. |
error | Why a check failed when result is error. |
The SUMMARY record in the key-value store lists input rows, unique addresses, duplicates, counts by result and quality, how many were decided locally, how many were charged, warnings, and the Google Sheet outcome.
How much does it cost to verify emails?
$1 per 1,000 addresses verified, no subscription, Apify platform usage included. One email-verified event is charged per unique address that received a verdict, including addresses decided locally as invalid. Not charged: duplicates, blank cells, text that is not an address, rows the check could not complete (error), and anything after your run's cost limit.
| List size | Cost (no duplicates) | Actor fee with your own MillionVerifier key (plus your MillionVerifier credits) |
|---|---|---|
| 1,000 addresses | $1.00 | $0.20 |
| 10,000 addresses | $10.00 | $2.00 |
| 100,000 addresses | $100.00 | $20.00 |
A 10,000-row list with 15% duplicates costs about $8.50, because duplicates are free. If you also tick the Google Sheet output, the Dataset to Google Sheets Sync Actor charges its own fee on top: $0.002 per sync plus $0.00002 per row, about $0.20 for 10,000 rows.
If you already have a MillionVerifier account, paste your API key: the mailbox checks are then paid from your MillionVerifier credits and this Actor charges $0.20 per 1,000 as a platform fee.
Set Maximum cost per run in the run options to cap spending; the run stops cleanly at the cap and tells you how many rows are left. To continue later, open the run and click Resurrect: it carries on from where it stopped and does not charge again for the addresses already verified.
Tips
- Chain it after a scraper: use the scraper's dataset ID as input and keep
keepInputFieldson; the output is the scraped list plus the verdict. - Cold outreach: send to
quality = good. Treatcatch_allas a separate warm-up segment; never bulk-send tobad. - Form clean-up:
didYouMeanplusisFreefinds thegmial.comtypos worth fixing by hand. - Big lists: the default run timeout is 24 hours, so a 100,000-address list finishes in one run even when many mail servers are slow. If a run still stops early (timeout, cost limit, vendor outage), Resurrect it instead of starting a new run: already verified addresses are not charged twice.
- Slow corporate servers: raise
verificationTimeoutSecsto 30 if many results come backunknownwithtimeout.
Other Actors by osel_house
- Dataset to Google Sheets Sync: send any Actor's results to a Google Sheet on every run, no Google login (this Actor uses it for the sheet output).
- Sitemap URL Extractor & Change Monitor: every URL from a site's sitemaps, or only what changed since last time.
- NWS Official Weather: official NOAA/NWS daily high, low and METAR observations as JSON.
FAQ, privacy and support
Is this legal / GDPR friendly? Verifying addresses you lawfully hold is standard list hygiene. No email is sent to the addresses. Addresses are sent to MillionVerifier (Budapest, EU) for the mailbox check; they state uploaded data is deleted after 30 days. Nothing is stored outside your run's own dataset and key-value store, and your Google Sheet if you asked for one. You are responsible for having a lawful basis to hold and contact the addresses, and this Actor must not be used to build or validate lists for unsolicited mass mail.
Why "catch-all"? Some domains accept mail for any address and bounce later. No verifier can confirm those mailboxes; they are reported as risky, not invalid.
Why "unknown"? The mail server was slow, greylisted the check, or sits behind an anti-spam filter. The Actor retries once; running again later often resolves the rest.
The run stopped early. Do I pay twice? No. Resurrect the run (Console > the run > three-dot menu > Resurrect) and it continues from the last saved row. Addresses that already got a verdict are remembered and not charged again.
Can I verify from Excel? Export the sheet as CSV first, or paste the Google Sheet link.
Something broke? Open the Issues tab on this page; include the run ID. Custom pipelines (scrape, verify, enrich, deliver) are available on request.