Bulk Email Verifier (Apify Actor)

Validate an email list for $0.40 per 1,000: one row each with valid/invalid, MX, disposable, role and typo flags. Paste emails, a CSV or a Google Sheet. DNS failures are free. Runs as an Apify Actor, callable from MCP clients via the Apify MCP server (https://mcp.apify.com/?actors=pennydata/bulk-email-validator-no-smtp).

Hosted MCP Server

npx add-mcp 'https://mcp.apify.com/?actors=pennydata/bulk-email-validator-no-smtp'

Installs into Claude Code, Codex, Cursor and more

Documentation

Bulk Email Verifier: Check an Email List, $0.40 per 1,000 (pennydata/bulk-email-validator-no-smtp) Actor

Verify an email list for $0.40 per 1,000: valid/invalid, MX, disposable, role and typo flags per row. Paste emails, a CSV or a Google Sheet. No SMTP, no API key. DNS failures free. Click Start: the 5 example emails cost about $0.002.

Pricing

from $0.28 / 1,000 email validateds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events. Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes. In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours, and optionally produces a well-defined JSON output, datasets with results, or files in key-value store. In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects. You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the API section below.

Each client library has reference documentation the quickstart does not restate: JavaScript/TypeScript (npm install apify-client) and Python (pip install apify-client).

README

Paste email addresses, a CSV or a Google Sheet; get one row per email with valid / invalid, MX check, disposable, role-account and typo flags. $0.0004 per email checked ($0.40 per 1,000), DNS failures are free, no SMTP, no login. New Apify accounts include free monthly credit, enough to try a few dozen emails at no cost. Click Start: the prefilled input (5 emails) runs as is and costs at most $0.002.

Real output of this Actor's validation code (live DNS lookups, 2026-10-24) for the prefilled input, the same 5 emails as the demo input below.

inputvalidstatusscoreriskTypehasMx
hostmaster@iana.orgtruedeliverable_domain70roletrue
webmaster@w3.orgtruedeliverable_domain70roletrue
info@example.comfalseinvalid_domain (null_mx)0invalidfalse
temp123@mailinator.comfalsedisposable20disposabletrue
not-an-emailfalseinvalid_syntax0invalidfalse

Try it in Apify Console: the input form opens already filled with a demo input (below), so you can click Start with no setup. A new Apify account includes free monthly credit.

Demo input:

{"emails":["hostmaster@iana.org","webmaster@w3.org","info@example.com","temp123@mailinator.com","not-an-email"]}

Email verifier and bulk email checker to validate an email list in one run: paste addresses, give a CSV or Google Sheets URL, or pass another Actor's dataset, and get one row per unique email with syntax, MX/DNS, disposable-domain, role-account and free-provider flags plus typo suggestions. It never opens an SMTP connection, so there are no blocked mail ports or per-mailbox timeouts, and it does not claim a mailbox exists. You pay only for rows that were checked; DNS failures are free.

Track record, stated plainly: a young Actor (12 runs so far, 2 users). The only 2 failed runs were on early builds on 2026-10-16; later builds, including the default-input run, succeed. Inputs saved with the field emailList, emails, email or csvFile run unchanged.

Free to try: a new Apify account includes free monthly platform credit, enough to validate a few dozen emails before you pay anything. No hidden minimums.

Features

  • Migration-friendly output and input: every row also carries snake_case is_disposable, is_role_based, is_free_provider, is_catch_all (always null: not checked, no SMTP) and did_you_mean, plus hasTag, tag and normalizedEmail for user+tag@ addresses (tag stripped, Gmail dots folded). Saved inputs that use datasetId, emailColumn, timeout/timeoutSecs or skipInvalidSyntax run unchanged (timeout is ignored; skipInvalidSyntax: true leaves syntax-invalid rows out of the output).
  • Per-row status and run summary: every output row has rowStatus (ok, invalid or error) and rowReason, and each run saves a RUN_SUMMARY record in the key-value store with counts per status and rows billed. error rows (DNS failures) are never billed.

How to use Bulk Email Validator

  1. Open the Actor and paste addresses into emails, or set csvUrl to a public CSV or a Google Sheets link (shared as "Anyone with the link can view"; /edit links are converted to CSV export automatically, and the email column is auto-detected).
  2. Click Start. Duplicates are removed (case-insensitive) and validated once.
  3. Open the Output tab: the Human summary link (OUTPUT.md in the key-value store) shows valid / risky / invalid counts and the first 10 rows as a table. Or download JSON/CSV/Excel. The SUMMARY record shows counts by status.
  4. Re-run rows with status unknown (DNS failure) later; they were not charged.

Pricing

Pay per event, no subscription and no compute fees on top. Price: $0.40 per 1,000 emails (FREE tier; volume tiers are cheaper).

EventWhen it is chargedPrice
email-validatedOne email address checked (syntax, DNS/MX, disposable, role, free-provider).$0.0004

Worked example, 10,000-email list: 10,000 unique emails x $0.0004 = $4.00 on the FREE tier. Apify subscription tiers are cheaper per email: BRONZE $0.00036 ($3.60), SILVER $0.00032 ($3.20), GOLD and above $0.00028 ($2.80). If 300 of the rows come back unknown (DNS lookup error), they are not billed, so the FREE-tier total is 9,700 x $0.0004 = $3.88. Duplicate addresses are removed before checking and billed once.

No hidden costs: email-validated is the only billing event. There is no run-start fee and no proxy or residential-IP cost, because the Actor uses no proxy and never opens an SMTP connection (DNS lookups only). Apify platform compute is not charged on top of pay per event.

Rows with status unknown (DNS lookup error) are not billed. Every other checked row is billed, including invalid_syntax and invalid_domain. Set the run's maximum cost in the run options to cap spend: the Actor stops when that limit is reached.

Example input

{
  "emails": [
    "jane@gmail.com",
    "info@example.com",
    "bob@mailinator.com",
    "x@gmial.com",
    "not-an-email"
  ]
}

Example output

Illustrative sample of the output shape (field names from the Actor; values shown for a disposable address).

{
  "input": "bob@mailinator.com",
  "email": "bob@mailinator.com",
  "valid": false,
  "score": 20,
  "riskType": "disposable",
  "status": "disposable",
  "reason": "disposable_domain",
  "domain": "mailinator.com",
  "hasMx": true,
  "isDisposable": true,
  "isRole": false,
  "isFreeProvider": false,
  "didYouMean": null
}

Details and limits

Cleans an email list without contacting any mail server. For every address it checks:

CheckOutput field
Syntax (RFC 5321/5322-style, length limits, IDN domains converted to punycode)status = invalid_syntax, reason
Domain DNS: MX records, A/AAAA fallback, RFC 7505 null-MXhasMx, hasARecord, mxRecords
Disposable / throwaway domain (incl. subdomains of listed domains)isDisposable
Role account (info@, admin@, support@, noreply@ ...)isRole
Free mailbox provider (Gmail, Outlook, Yahoo, iCloud, Proton ...)isFreeProvider
Typo suggestion for common providers (gmial.com, hotmial.com, outlok.com)didYouMean

Score and risk type

Every row has score (0-100) and riskType (none, free, role, disposable, invalid, unknown), computed from the offline checks above:

  • invalid (bad syntax, no mail records, null MX, likely typo with no MX) scores 0; disposable scores 20.
  • Otherwise start at 100 and subtract 30 for a role account, 15 for a free provider, 10 for an A-record-only fallback (no MX), 15 when a typo fix is suggested. riskType is the first match of role, free, else none.
  • unknown (DNS lookup failed, not billed) has score: null. The score is a heuristic ranking, not a mailbox-exists guarantee.

Use it from Google Sheets

  1. In Google Sheets click Share, set "Anyone with the link" to Viewer, and copy the link (a File > Share > Publish to web link also works).
  2. Paste that link into csvUrl (add #gid=N for a tab other than the first). The email column is found automatically; set csvColumn to force one.
  3. Run. You get one validated row per unique address, merged with anything in emails; copy the results back into your sheet.

Read emails from another run's dataset

Set inputDatasetId to a dataset ID or name (for example a scraper's output) and emailField to the item field holding the email (default email). Results are merged with emails and csvUrl; if no row has that field the run fails with a clear message.

valid is true when the syntax is correct, the domain can receive mail (MX, or A/AAAA fallback) and it is not a disposable domain.

Validate leads from a Google Maps Scraper run

  1. Run a Google Maps scraper that outputs contact emails (for example compass/crawler-google-places with company contacts enabled) and copy the dataset ID of the run (Storage tab).
  2. Paste it into inputDatasetId here and leave emailField as email. The actor reads both the emails array and the email field of each place and validates every address.
  3. Each result row keeps the place's title, placeId, website and address when present, so you can join results back to the scrape. Keep rows where valid is true.

For phones from the same run use phone-number-validator-offline with the same dataset ID. This is checking syntax, domain and disposable/role status only, not whether a mailbox exists.

What this does NOT do (read before buying)

  • No SMTP probing. It cannot tell whether a specific mailbox (jane@company.com) exists. valid: true means "the address is well-formed and its domain accepts mail", not "the mailbox exists". Catch-all domains, full mailboxes and non-existent users on real domains pass.
  • Disposable detection is only as good as the open list (about 9 900 domains). New throwaway services are missed until the list is updated; the list in this version was fetched 2026-10-15.
  • The role and free-provider lists are short hand-curated lists, not exhaustive.
  • Typo suggestions cover about ten big providers only and are suggestions, not corrections.
  • DNS answers can change between runs (domains get new records); flags for a given domain are deterministic only while its DNS is.

Privacy

Only the emails you supply are processed. Nothing is stored beyond the run's dataset and summary (subject to your Apify retention settings). No third-party API is called; only DNS queries for the email domains are sent.

Data sources and licenses

Disposable domains: disposable-email-domains, CC0 1.0. See data/SOURCES.md.

Pair with: Website Contact Extractor (step 1 extract, step 2 validate)

  1. Extract: run Website Contact Extractor on your list of company websites. Each output row has an emails array (public business contact data only).
  2. Validate: copy that run's dataset ID into inputDatasetId here. The emails array is read automatically, so every address found is checked for syntax, MX and disposable/role status. Keep rows where valid is true.

Each step is a separate run billed at its own pay-per-event price.

More from PennyData

Works with: Shopify leads -> emails -> phones

Chain three PennyData actors to turn a list of store domains into checked contacts.

  1. Shopify Store Leads & Contacts takes {"domains": [{"url": "https://www.gymshark.com"}]} and returns rows with emails (array) and phones (array).
  2. This actor: copy the emails values into emails here, e.g. {"emails": ["press@gymshark.com", "support@gymshark.com"]}.
  3. Phone Number Validator (Offline) takes the phones values from step 1, e.g. {"phones": ["+44 20 7946 0958"], "defaultRegion": "US"}.

Each step is a separate run billed at its own pay-per-event price, so you only pay for the steps you use.

Switching from pnda/email-verifier?

The input runs here with no edits (tested 2026-10-24 on 5 role addresses such as info@github.com). Input map, from the rival's public build 1.0.27 input schema (https://api.apify.com/v2/acts/pnda~email-verifier/builds/default, read 2026-10-24):

pnda/email-verifierbulk-email-validator-no-smtp
emails (array of strings)emails, same shape
concurrency (1-10)concurrency
timeoutSecsaccepted and ignored (no SMTP waits)
checkCatchAllaccepted and ignored: this actor does no SMTP probe, so it cannot flag catch-all domains and never bills a catch-all fee

Price per email, read from the public pricingInfos at https://api.apify.com/v2/acts/pnda~email-verifier on 2026-10-24 (check its Pricing tab, prices change):

pnda/email-verifierhere
valid / invalid result$0.00095 (FREE tier)$0.0004
catch-all result$0.000475 from 2026-11-02 (new catch-all-email event; free before)no such fee
run start$0.00005 per GBnone

This actor checks syntax, MX/DNS, disposable, role and typos only. It does not confirm that a mailbox exists, so it does not replace SMTP-level checks. Output field names differ; run a small sample before switching a production job. Not affiliated with the other actor's author.

Switching from api-ninja/email-address-validator?

Both actors take a list of emails. This one adds CSV input and a row cap. Input mapping:

api-ninja/email-address-validatorbulk-email-validator-no-smtp
emails (array of strings)emails (array of strings), same shape
(none)csvUrl + csvColumn to read a public CSV, maxEmails to cap rows, concurrency

This actor checks syntax, MX/DNS, disposable domains, role accounts and typos without an SMTP mailbox probe, so it cannot confirm that a specific mailbox exists. If you need mailbox-level SMTP confirmation, it will not replace that. Output field names differ between the two actors, so map them from a small sample run before you switch a production job. Price here: $0.0004 per email checked ($0.40 per 1,000), see Pricing above and compare with the other actor's Pricing tab. Not affiliated with the other actor's author.

Drop-in alternative: accepts the same input fields

If you already have a saved input for another email validator, it runs here unchanged. Accepted input fields (aliases of the canonical emails): emailList, emailAddresses, emailAddress, email; CSV aliases: csvFile, csv, fileUrl. Each can be an array of strings, a newline/comma-separated string, or an array of { "email": "..." } objects. Extra keys such as timeout are ignored.

The input of fatihtahta/email-verifier-validator-pro is only emailList (read from its public schema on 2026-10-22). That actor's public Store stats on 2026-10-22: 1,199 users, and 38,010 of 50,777 runs in the last 30 days listed as failed. Your saved {"emailList": [...]} input works here with no edits. Output field names and checks differ: we do NOT do SMTP mailbox checks (syntax, MX/DNS, disposable, role, typo only), so run a small sample before switching a production job. Not affiliated with that author.

Migrating from easy-bulk-email-validator (xmiso_scrapers)?

The input is the same: { "emails": ["a@example.com", "b@example.org"] } runs here with no edits. The other actor's second input, timeout, is accepted and ignored here (there are no per-mailbox SMTP waits). Mapping below is from its public dataset view (build 0.0.14, read 2026-10-23; no runs were made on it). Their email_result and subresult values are not documented in that view, so those rows map by meaning only; run a small sample on both before switching a production job.

easy-bulk-email-validator outputHereNote
emailemail (normalised; original in input)duplicates removed before checking
email_resultvalid (true/false) and statusstatus is one of deliverable_domain, fallback_a_record, invalid_syntax, invalid_domain, disposable, unknown; rowStatus is ok, invalid or error
subresultreason (for example disposable_domain, dns_lookup_error)
email_qualityscore (0-100) and riskTypeheuristic from offline checks, not a mailbox verdict
free (Is_From_Free_Email_Provider)isFreeProvideralso isRole, isDisposable, hasMx, didYouMean

Pricing is pay per event: $0.0004 per email checked, no per-run start fee, DNS failures free (their listed price on 2026-10-21: $0.0025 per result plus $0.01 per run; check its Pricing tab, prices can change). This actor never opens an SMTP connection, so it cannot confirm that a specific mailbox exists; if you need mailbox-level confirmation it will not replace that. Not affiliated with the other actor's author.

Migrating from michael.g/email-verifier-validator?

Its published input schema (read 2026-10-21) takes emails, an array of strings, so a saved input runs here with no edits.

Field in your saved inputWhat this actor does
emails (array of strings; also accepts a newline/comma string)validated as-is

Listed price on 2026-10-21 (check each Pricing tab, prices can change): michael.g $0.001 per email, no start fee listed; this actor $0.0004 per email, no start fee.

We do NOT do SMTP mailbox checks: this actor checks syntax, MX/DNS, disposable domains, role accounts and typos, so it cannot confirm that a specific mailbox exists. Output field names differ, so check a small sample run before switching a production job. Not affiliated with the author.

Migrating from snipercoder/email-validator?

An input saved for snipercoder/email-validator runs here without edits. Accepted field names:

Field in your saved inputWhat this actor does
emails (array or newline/comma string)validated as-is
email (single string)validated as one address
csvFile (public CSV URL)read like csvUrl; uses the column whose header contains "email"

This actor checks syntax, MX/DNS, disposable domains, role accounts and typos without an SMTP mailbox probe, so it cannot confirm that a specific mailbox exists. Output field names differ, so check a small sample run before switching a production job. Rows whose DNS lookup fails are not billed. Not affiliated with the other actor's author.

FAQ

Can I verify a list of emails in bulk for free?
New Apify accounts include free monthly platform credit, so a small list costs nothing out of pocket; after that it is pay per event (see Pricing; it can change). Paste addresses into emails, or set csvUrl (and csvColumn) to a public CSV, and download one row per unique address.

{ "emails": ["jane@gmail.com", "info@example.com", "x@gmial.com"], "concurrency": 10 }

How do I check for disposable (temporary) email addresses?
Every row has isDisposable, matched against the open disposable-email-domains list (subdomains included), and valid is false with status: "disposable" for them. The list is only as current as its fetch date (2026-10-15), so brand-new throwaway services can be missed.

{ "emails": ["bob@mailinator.com", "temp123@mailinator.com"] }

Am I billed for rows that failed?
No for DNS failures: a row with status unknown (reason: dns_lookup_error) is written to the dataset but not charged, so re-run those later for free. Rows that were actually checked are charged, including addresses found invalid_syntax or invalid_domain, because the check ran. To cap spend, set the maximum cost per run in the run options; the Actor stops once that limit is reached. The SUMMARY record shows counts per status so you can compare it with your bill.

What does status unknown mean? Am I billed for it? Can I re-run it?
status: "unknown" (reason: dns_lookup_error) means the DNS lookup for the domain failed or timed out, so the Actor could not tell whether the domain accepts mail. It does not mean the address is bad. unknown rows are never billed. They are written to the dataset with no charge, so filter status = unknown and paste those addresses into a new run later. A re-run that again returns unknown is free again; if the lookup now works, the row is checked and charged as a normal row ($0.0004). The SUMMARY record shows how many rows ended up unknown.

What does it cost? Worked example.
$0.0004 per email checked (FREE tier price; volume tiers are cheaper), nothing else on top. 1,000 emails = $0.40. 25,000 emails = $10.00. Duplicates are removed before checking, so a repeated address is billed once.

How many emails per run?
maxEmails defaults to 10,000 and can be raised to 100,000 per run (the input field limit). It is a safety cap on unique addresses, not a hard product limit: extra addresses beyond it are ignored with a log warning, so raise it for bigger lists. For a CSV, set csvUrl (and csvColumn) instead of pasting.

Why no SMTP check?
SMTP probing (connecting to the mail server and asking whether the mailbox exists) gets sender IPs blocklisted, is blocked or faked by many providers (catch-all domains answer yes to everything) and is unreliable from cloud IPs. This Actor only does DNS lookups and list checks, which are fast, cheap and safe for your IP.

What does it NOT verify?
Whether a specific mailbox exists, is full, or will accept your mail. valid: true means the syntax is correct, the domain has MX (or an A/AAAA fallback) and it is not a known disposable domain. Catch-all domains, full mailboxes and non-existent users on real domains pass. Use it to clean obvious bad rows before sending, not as a guarantee of delivery.

Does it detect catch-all addresses or confirm a mailbox exists?
No. It never opens an SMTP connection, so it cannot detect catch-all domains, full mailboxes or non-existent users on real domains. valid: true means well-formed with a domain that accepts mail. That is also why it cannot get your IP blocklisted.

How do I flag role accounts, free providers and typos?
Use isRole (info@, admin@, support@ ...), isFreeProvider (Gmail, Outlook, Yahoo ...) and didYouMean (about ten big providers, e.g. gmial.com to gmail.com). Rows with unknown DNS status are not charged; re-run them later.

How do I clean a whole lead list, not just emails?
Find public business emails for store domains with Shopify Store Leads & Contacts, validate phone numbers with Phone Number Validator (Offline), and check the email domains with Bulk Domain WHOIS & DNS Lookup. You are responsible for a lawful basis (e.g. GDPR) to process the addresses you submit.

Need a custom field or a different source? Open an issue on the Actor page.

Built with AI assistance (Claude); maintained by the publisher.

Use from Claude Desktop / Cursor (MCP)

Apify's MCP server can expose this actor as a tool, so an AI agent can validate a list of emails from a plain-English prompt. Use this URL (?tools= takes a comma-separated list of actors, see the Apify MCP docs):

https://mcp.apify.com/?tools=pennydata/bulk-email-validator-no-smtp

Client config for Claude Desktop or Cursor (mcpServers format; sign in with OAuth when the client asks):

{"mcpServers": {"apify": {
  "url": "https://mcp.apify.com/?tools=pennydata/bulk-email-validator-no-smtp"
}}}

Runs started by an agent are billed like any other run, at the prices above.

Related pennydata actors

Other small pay-per-event Actors from the same publisher:


Other languages

Español: Validador de correos electrónicos masivo

Valida una lista de correos sin enviar nada: sintaxis, registros MX, dominios desechables, cuentas de rol y errores tipográficos. Pega los correos, un CSV o una hoja de Google y recibe una fila por cada correo. No usa SMTP ni clave de API. Precio: 0,0004 USD por correo validado (0,40 USD por 1.000); los fallos de DNS no se cobran.

Ejemplo de entrada:

{"emails":["jane@gmail.com","info@example.com","temp123@mailinator.com"]}

Português: Validador de e-mails em massa

Valida uma lista de e-mails sem enviar mensagens: sintaxe, registros MX, domínios descartáveis, contas de função e erros de digitação. Cole os e-mails, um CSV ou uma planilha do Google e receba uma linha por e-mail. Sem SMTP e sem chave de API. Preço: US$ 0,0004 por e-mail validado (US$ 0,40 por 1.000); falhas de DNS não são cobradas.

Exemplo de entrada:

{"emails":["jane@gmail.com","info@example.com","temp123@mailinator.com"]}

Deutsch: E-Mail-Adressen prüfen (Massenvalidierung)

Prüft eine Liste von E-Mail-Adressen ohne Versand: Syntax, MX-Einträge, Wegwerf-Domains, Rollenadressen und Tippfehler. Adressen einfügen, CSV oder Google Sheet angeben und pro Adresse eine Ergebniszeile erhalten. Ohne SMTP und ohne API-Schlüssel. Preis: 0,0004 USD pro geprüfter Adresse (0,40 USD pro 1.000); DNS-Fehler kosten nichts.

Beispieleingabe:

{"emails":["jane@gmail.com","info@example.com","temp123@mailinator.com"]}

I built this and earn from its runs. Written with AI assistance (Claude).

Actor input Schema

emails (type: array):

List of email addresses to validate. Same key as xmiso_scrapers/easy-bulk-email-validator, michael.g/email-verifier-validator and pnda/email-verifier, so their saved input JSON runs unchanged.

csvUrl (type: string):

Public http(s) URL of a CSV file, or a Google Sheets link (docs.google.com/spreadsheets/d//edit, shared as 'Anyone with the link can view'; add #gid=N for another tab). The email column is auto-detected (header containing 'email', else the column with the most email-like cells). Merged with the Emails list.

inputDatasetId (type: string):

Read emails from another run's dataset (ID or name), e.g. a Google Maps Scraper (compass/crawler-google-places) run. Fields emails and email are detected automatically and title, placeId, website, address are copied onto each result row. Merged with the Emails list and CSV.

emailField (type: string):

Field name holding the email in each dataset item. Leave as email to auto-detect emails (array) and email, as in Google Maps scraper output. A clear error is raised if no row has it.

csvColumn (type: string):

Header of the column holding emails.

maxEmails (type: integer):

Safety cap on unique emails processed.

maxCostUsd (type: number):

Hard spending guard. The run stops once this many dollars of emails have been billed ($0.0004 each). Leave empty for no cap beyond Max emails per run.

concurrency (type: integer):

Parallel DNS validations.

csvFile (type: string):

Alias of csvUrl, accepted so inputs saved for similar email-validator actors run unchanged.

emailList (type: array):

Alias of Emails, accepted so inputs saved for fatihtahta/email-verifier-validator-pro and similar Actors run unchanged. Used only when Emails is empty.

datasetId (type: string):

Alias of inputDatasetId, accepted so inputs saved for similar email-verifier Actors run unchanged.

emailColumn (type: string):

Alias of emailField, accepted so saved inputs from similar Actors run unchanged.

skipInvalidSyntax (type: boolean):

If true, addresses that fail the syntax check are left out of the output (and are not billed).

timeout (type: integer):

Accepted so an easy-bulk-email-validator input ({"emails": [...], "timeout": 10}) runs unchanged. Ignored: no SMTP probing, so there is nothing to time out. timeoutSecs (pnda/email-verifier) is also accepted and ignored.

Actor input object example

{
  "emails": [
    "hostmaster@iana.org",
    "webmaster@w3.org",
    "info@example.com",
    "temp123@mailinator.com",
    "not-an-email"
  ],
  "emailField": "email",
  "maxEmails": 100,
  "maxCostUsd": 0.5,
  "concurrency": 10
}

Actor output Schema

results (type: string):

No description

runSummary (type: string):

No description

summary (type: string):

No description

humanSummary (type: string):

No description

API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

JavaScript example

import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "emails": [
        "hostmaster@iana.org",
        "webmaster@w3.org",
        "info@example.com",
        "temp123@mailinator.com",
        "not-an-email"
    ],
    "maxEmails": 100,
    "maxCostUsd": 0.5
};

// Run the Actor and wait for it to finish
const run = await client.actor("pennydata/bulk-email-validator-no-smtp").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

Python example

from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "emails": [
        "hostmaster@iana.org",
        "webmaster@w3.org",
        "info@example.com",
        "temp123@mailinator.com",
        "not-an-email",
    ],
    "maxEmails": 100,
    "maxCostUsd": 0.5,
}

# Run the Actor and wait for it to finish
run = client.actor("pennydata/bulk-email-validator-no-smtp").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

CLI example

echo '{
  "emails": [
    "hostmaster@iana.org",
    "webmaster@w3.org",
    "info@example.com",
    "temp123@mailinator.com",
    "not-an-email"
  ],
  "maxEmails": 100,
  "maxCostUsd": 0.5
}' |
apify call pennydata/bulk-email-validator-no-smtp --silent --output-dataset

MCP server setup

{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,pennydata/bulk-email-validator-no-smtp"
        }
    }
}

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an Authorization: Bearer <APIFY_API_TOKEN> header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/LCwVvjCqjn1rS7Qbh/builds/ZUTtMHXOUjpTkPa5e/openapi.json