# Email Validator — From $0.6/1K · MX, SPF & DMARC Checks (`apivault_labs/email-validator`) Actor

Check email syntax, DNS/MX and disposable signals; optional SMTP observations do not guarantee deliverability. Bulk export: JSON, CSV, Excel and API. PPE: from $0.6/1K email results; start fee, usage extra.

- **URL**: https://apify.com/apivault_labs/email-validator.md
- **Developed by:** [Apivault Labs](https://apify.com/apivault_labs) (community)
- **Categories:** Lead generation, Automation, MCP servers
- **Features:** Limited permissions
- **Stats:** 4 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.60 / 1,000 email verifieds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Email Validator & Verifier | Bulk Cleanup + Finder

Clean lists with syntax checks, public MX/SPF/DMARC observations, disposable/free/role flags and typo suggestions. Optional SMTP recipient observations and name/domain patterns complement these checks. **MX alone does not prove a mailbox exists.** No third-party API key required; Apify API/MCP requires your Apify account/token.

### First run: cleanup

```json
{"emails":["info@apify.com","qa-owner@example.com",".bad@gmail.com"],"smtpVerification":false,"freshDisposableList":true}
```

Inspect Dataset, SUMMARY and ERRORS; export JSON/CSV/Excel through Apify. The example covers a mail domain, a Null MX domain that advertises no mail service, and invalid syntax. SMTP off means no mailbox contact. For syntax/disposable cleanup use onlyValid:true and dropDisposable:true, optionally dropRoleBased:true. To require a positive recipient observation use smtpVerification:true and onlyDeliverable:true; unknown/DNS-only rows are excluded and output can be empty.

### Interpret evidence: agents and workflows

| Field | Meaning |
| --- | --- |
| syntaxValid | Supported ASCII dot-atom local part and domain; IDN domains become ASCII. Quoted locals, domain literals and SMTPUTF8 locals are unsupported. |
| verificationStatus | Legacy domain/heuristic valid/risky/invalid/unknown. valid can mean only MX observed. |
| technical_status | valid requires SMTP recipient acceptance and explicit catchAll false. domain_only means MX without mailbox confirmation. Other values: catch_all, disposable, invalid, unknown. |
| status | good only with recipient confirmation; bad for invalid/disposable; risky for uncertainty. No delivery guarantee. |
| verificationScope | syntax_and_heuristics, domain_and_heuristics, smtp_recipient_observation; Finder unverified_patterns until confirmed. |
| hasMx, nullMx | Non-null MX versus explicit `0 .` Null MX indicating no mail service. Recursive DNS is not an authoritative zone. |
| hasSpf, hasDmarc | Correctly prefixed policy TXT presence, not alignment/authentication validation or sender permission. Unknown lookup stays null. |
| mailboxExists, catchAll | Recipient/catch-all observation; null is unavailable/inconclusive. SMTP may hide nonexistent recipients. A 550 policy refusal alone is not proof of nonexistence. |
| score, deliverabilityScore | Heuristic, not measured probability/accuracy. Unknown classification has null score. |
| freeProvider, roleBased, disposable | List-based, incomplete signals; role/free addresses can be legitimate. |
| suggestedCorrection | Suggestion only, no silent rewrite. Real .co/.cm/.om domains are preserved. |
| sourceErrors, dnsStatus | Source availability and DNS response codes. Failed queries are not empty record sets. |

normalizedEmail collapses Gmail/googlemail dots and plus tags. Other providers retain local-part case, dots and tags to avoid merging distinct addresses. input preserves the original; email contains normalized domain. With deduplicate:false repeated entries are billed independently.

### Finder

```json
{"findEmails":["QA Owner, apify.com"],"smtpVerification":false,"freshDisposableList":false}
```

ASCII-name patterns use fixed heuristic ordering, not evidence of a person/address. candidates and mostLikely are unverified. **email remains null and found false until verified true.** Finder always checks DNS. Hosted SMTP fallback tries at most four patterns; catch-all true/unknown prevents confirmation. No confirmed result does not prove the person has no address. Useful person/pattern analysis is billed once, not per candidate.

### Inputs

emails is an array of strings (runtime also accepts email objects); emailsText is a pasted single column separated by newline/comma/semicolon/whitespace. emailsFile accepts UTF-8 raw text, an accessible public HTTPS upload URL (including a signed Apify record URL), or JSON KV reference `{"keyValueStoreId":"YOUR_STORE_ID","key":"UPLOAD"}` accessible to your run. For a JSON reference, select emailsFileStoreId with the matching store ID to grant READ under Limited permissions. No full-account access is required. The first Email/Emails header is ignored. Display names like `John Doe <john@example.com>` stay one entry. Single-column import is not a general CSV parser. Text/file limits: 2 MB; combined entries: 10000.

| Parameter | Default | Behavior |
| --- | --- | --- |
| checkMx | true | Domain validation checks; Finder always uses DNS. |
| smtpVerification | false | Opt-in direct/hosted recipient observations; requires checkMx. |
| smtpTimeout | 10 | 4–30 seconds per source step. |
| freshDisposableList | true | Refresh public lists once; SUMMARY gives actual counts. Built-in list survives source failure. |
| deduplicate | true | Provider-aware normalization before processing. |
| onlyValid | false | Keep supported syntactically valid validation inputs. |
| onlyDeliverable | false | Require recipient acceptance and explicit non-catch-all for validation/Finder. No delivery guarantee. |
| dropDisposable, dropRoleBased | false | Validation filters. |
| maxResults | 100 | 1–10000 delivered rows including Finder; bounded processing stops at row/event caps. |
| maxConcurrency | 5 | 1–20 rows; same-domain lookups share a task. |
| exportFormat | default | default JSON; csv flat columns; both JSON plus \_csv. Apify export also provides CSV from JSON. Flat columns include Business Status, Technical Status, Verification Scope and SMTP Source; Status retains the legacy domain classification. |
| proxyUrl | empty | Hosted HTTP verifier only. auto uses paid Apify Residential; custom URL or host:port:user:pass. No effect on direct SMTP. |
| proxySessions | 1 | Legacy field: one session is used; known rate limits are not bypassed with IP rotation. |

SUMMARY rowsDelivered/returned/classifications/peopleSearched count delivered output. attempted/filtered/duplicatesSkipped/notAttempted explain coverage; budgetLimited/resultLimited disclose stops. Pure processing/finder-input errors go to ERRORS without a result fee. Invalid syntax, negative DNS or useful syntax/flags with unknown DNS can be billed classifications; inspect their evidence.

### SMTP limitations and privacy

Direct port25 may be blocked on Apify. Optional fallback forwards supplied addresses and a random control address when needed to a public hosted verifier (Snov.io). Proxy uses that same service. This Actor sends no email message DATA. Network failures, rate limits, greylisting, policy blocks and missing catch-all evidence stay unconfirmed. Enable only when forwarding addresses fits your workflow. A proxy cannot guarantee verification. RCPT acceptance is not proof of delivery, ownership or consent.

### Pricing

Current result fees per 1000 useful returned email/person rows: **Free $2; Bronze $1; Silver $0.80; Gold/Platinum/Diamond $0.60**. Startup $0.00005 per GB, minimum one event. User pays platform usage and optional proxy resources. Filtered/duplicate/pure-processing-error inputs have no result event, generated candidates no individual fee. Your run shows effective tier prices.

Set maxTotalChargeUsd on the run API for an event cap. SDK accounts for startup and delivered rows. Platform/proxy costs remain separate and may accrue for filtered work.

### REST

```bash
curl -X POST 'https://api.apify.com/v2/acts/apivault_labs~email-validator/runs?build=latest&memory=256&timeout=300&maxTotalChargeUsd=0.05' \
  -H "Authorization: Bearer $APIFY_TOKEN" -H 'Content-Type: application/json' \
  -d '{"emails":["info@apify.com","qa-owner@example.com"],"smtpVerification":false,"maxResults":2}'
```

Poll `/v2/actor-runs/{runId}` to terminal. Read `/v2/datasets/{defaultDatasetId}/items?clean=true` (format=csv for export) and `/v2/key-value-stores/{defaultKeyValueStoreId}/records/SUMMARY` or ERRORS. Use Bearer auth; tokens never belong in shared input/URLs. Empty filtered output can succeed. Run status alone does not verify a mailbox.

### MCP

Connect authenticated clients to `https://mcp.apify.com/?tools=apivault_labs/email-validator`. Discover **apivault_labs--email-validator** with tools/list; tools/call takes normal input plus waitSecs:30. Poll/wait with returned run ID if still running. Read Dataset via get-dataset-items and SUMMARY/ERRORS via get-key-value-store-record with returned storage IDs. For a strict event cap use REST maxTotalChargeUsd.

Agents must separate candidates from observations, preserve nulls, inspect verificationScope/technical_status/catchAll/sourceErrors and never infer a mailbox from MX or score. n8n/Make/Zapier workflows should map evidence alongside email/status and retain SUMMARY coverage.

### Choose an email list cleanup workflow by evidence level

Use the email validator to classify a list before importing it into a
workflow. Syntax, domain mail routing, disposable-list membership and
recipient observations are different checks. Keeping those distinctions
visible is more useful than turning every successful run into a generic
green verified badge.

| Your task | Start with | Interpret the output as |
| --- | --- | --- |
| Remove malformed entries | Syntax checks, SMTP off | Supported-format classification |
| Inspect domain mail configuration | checkMx true, SMTP off | DNS and policy observations |
| Prepare a business list for review | Deduplicate and explicit role/disposable filters | A selected research list, not consent or deliverability |
| Require recipient evidence | SMTP opt-in and onlyDeliverable | Strict observed criteria with possible empty output |
| Investigate a name/domain pattern | Finder mode | Unverified candidates until a supported confirmation succeeds |

#### Classify three formatting and domain cases

This small input leaves SMTP off. It can return useful classifications
for a mail domain, a Null MX domain and malformed syntax. A returned
invalid row is still a classification result, not a failed processing
attempt or a working mailbox.

```json
{
  "emails": [
    "info@apify.com",
    "qa-owner@example.com",
    ".bad@gmail.com"
  ],
  "smtpVerification": false,
  "freshDisposableList": false,
  "maxResults": 3
}
```

#### Paste a single email column

The text input supports a single address column. It is not a general
multi-column CRM CSV parser. Preserve your own source-row mapping when
joining a normalized address back to the original customer file.

```json
{
  "emailsText": "Email\ninfo@apify.com\nqa-owner@example.com",
  "smtpVerification": false,
  "deduplicate": true,
  "maxResults": 2
}
```

#### Filter malformed and disposable entries without probing recipients

`onlyValid` checks supported syntax; it does not mean mailbox existence.
Role addresses can be legitimate company contacts, so enable the role
filter only when it matches your actual list requirements.

```json
{
  "emails": [
    "info@apify.com",
    "qa-owner@example.com",
    ".bad@gmail.com"
  ],
  "smtpVerification": false,
  "onlyValid": true,
  "dropDisposable": true,
  "maxResults": 3
}
```

#### Export evidence alongside a flat email status

Keep technical status and scope with the address. The legacy status
column can describe domain-level heuristics while the mailbox remains
unknown. Do not map that legacy value to a confirmed-inbox flag.

```json
{
  "emails": [
    "info@apify.com",
    "qa-owner@example.com"
  ],
  "smtpVerification": false,
  "freshDisposableList": false,
  "exportFormat": "csv",
  "maxResults": 2
}
```

### What a domain observation does and does not tell you

MX describes published domain routing, not whether a particular local
part exists. SPF/DMARC fields describe observed policy TXT records,
not authentication alignment, permission to send, or campaign delivery.
A successful DNS query and an unavailable query are different outcomes;
unknown values should stay unknown in your destination.

SMTP recipient acceptance, when available, is stronger evidence but is
still not proof a message will reach an inbox. Greylisting, policy
responses, catch-all domains and source limits can prevent confirmation.
The default workflow does not send email message DATA. Optional hosted
verification can forward submitted addresses to the documented service;
enable it only when that data flow fits your intended use.

### Deduplication and Finder results

Normalization is provider-aware. Gmail/googlemail aliases can collapse,
while other providers can preserve local-part case, dots and tags to
avoid merging distinct addresses. Keep input and normalizedEmail so
your downstream process can explain which source entries were grouped.
Turning deduplication off permits repeated delivered classifications
and their corresponding result charges.

Finder candidates are name/domain patterns, not newly discovered private
contacts. An unconfirmed mostLikely candidate is not a verified address.
Keep found/verified, verificationScope and the candidate list together,
and do not automatically promote a pattern into an outreach destination.

### Plan the cost of a cleanup batch

Active result rates checked on 20 October 2026 are $0.002 on Free,
$0.001 on Bronze, $0.0008 on Silver and $0.0006 on Gold/Platinum/Diamond
per delivered useful email/person row. A five-row batch with one
$0.00005 start unit has event fees of $0.01005, $0.00505, $0.00405 or
$0.00305 respectively. Platform and selected proxy usage are additional.

These are arithmetic examples, not total-run quotes. Filtered and
duplicate inputs have no result event, but inspecting them can use
resources. Invalid syntax or negative DNS can be useful billed
classifications. Generated candidate patterns do not each incur a
separate result fee; inspect actual rowsDelivered and charged events.

### Recover exports and handle uncertain outcomes

Save completed run and dataset IDs. Downloading an existing result again
does not repeat recipient checks or start another classification job.
Starting the same input is a new run with applicable charges. Read
SUMMARY and ERRORS before retrying failures or interpreting an empty
filtered result as absence of valid addresses in the original file.

### Frequently asked questions about email verification

#### Can I guarantee deliverability from a high score?

No. Scores are heuristics, not measured probabilities. Keep the underlying
scope and observations instead of relying on a numeric threshold alone.

#### Should I delete every role or free-provider address?

Those are list classifications, not universal quality defects. Choose
filters for your workflow; company role inboxes can be intentional contacts.

#### Does an unknown result mean the mailbox is invalid?

No. It can mean an unavailable source, DNS failure, blocked network path
or inconclusive recipient observation. Keep it distinct from a supported
negative classification.

#### Is this a permission or consent checker?

No. Technical observations do not establish permission to send messages,
recipient consent or suitability for a particular outreach campaign.

### n8n and developer integrations

Use this Actor in your automation or application with the existing community integrations below. An Apify account and API token are required; Actor and platform charges follow the [current pricing](https://apify.com/apivault_labs/email-validator/pricing).

- **n8n community node:** [n8n-nodes-apivault-email-validator](https://www.npmjs.com/package/n8n-nodes-apivault-email-validator). Install package name `n8n-nodes-apivault-email-validator` in a self-hosted n8n instance that permits community packages.
- **Python client and examples:** [GitHub](https://github.com/apivault-labs/apivault-labs/tree/main/python-clients/apivault-email-validator).
- **n8n source and usage:** [GitHub](https://github.com/apivault-labs/apivault-labs/tree/main/community-nodes/n8n-nodes-apivault-email-validator).

These are community packages. Publication on npm does not establish n8n verification or availability in n8n Cloud. Review the linked package README for supported inputs and setup.

# Changelog

This Actor's version history is a separate document: https://apify.com/apivault_labs/email-validator/changelog.md

# Actor input Schema

## `emails` (type: `array`):

Email addresses to validate (one per line), e.g. john.doe@acme.com.

## `emailsText` (type: `string`):

Optional. Paste many addresses at once (one per line, or comma/semicolon separated — e.g. a copied spreadsheet column). They are merged with the list above and de-duplicated.

## `emailsFile` (type: `string`):

UTF-8 single-column text/CSV: native public HTTPS upload URL (including signed Apify record URLs), raw text or JSON keyValueStoreId/key reference. For JSON references select emailsFileStoreId to grant READ access. Max 2 MB.

## `findEmails` (type: `array`):

Generate unverified ASCII-name/domain patterns. email remains null until a recipient is accepted and catch-all is explicitly false. No guessed address is presented as found.

## `checkMx` (type: `boolean`):

Public domain DNS observations (MX/SPF/DMARC); DNS cannot establish mailbox existence. Finder always uses DNS.

## `smtpVerification` (type: `boolean`):

Optional SMTP recipient observation: direct port25 or public hosted verifier fallback. Catch-all unknown stays unconfirmed. Network/rate-limit/temporary/policy failures remain unknown; no message DATA is sent.

## `proxyUrl` (type: `string`):

Optional HTTP proxy for hosted-verifier requests only; no effect on direct SMTP. auto uses Apify Residential and incurs extra resource costs. A proxy does not guarantee verification or remove source limits.

## `proxySessions` (type: `integer`):

Legacy compatibility field; one hosted-verifier proxy session is used. Known rate limits are not retried with rotating IPs.

## `smtpTimeout` (type: `integer`):

Per-step timeout for the SMTP mailbox check.

## `freshDisposableList` (type: `boolean`):

Refresh public disposable-domain lists once per run. Falls back to built-in entries if unavailable; SUMMARY reports actual entry count, not complete disposable coverage.

## `deduplicate` (type: `boolean`):

Remove duplicate addresses using provider-aware normalization (Gmail dots and +tags are ignored). Keeps the first occurrence.

## `onlyValid` (type: `boolean`):

If on, drop addresses that fail the syntax check from the output.

## `onlyDeliverable` (type: `boolean`):

Strictly keep rows with technical_status valid / SMTP recipient accepted / catchAll false. DNS-only and unknown rows are excluded. This is an observation, not a delivery guarantee.

## `dropDisposable` (type: `boolean`):

If on, remove addresses on known temporary-mailbox domains.

## `dropRoleBased` (type: `boolean`):

If on, remove group mailboxes like info@, sales@, support@ (keep only personal addresses).

## `exportFormat` (type: `string`):

default = full JSON. csv = flat CSV-friendly columns. both = JSON + nested \_csv.

## `maxResults` (type: `integer`):

Delivered row cap including finder rows.

## `maxConcurrency` (type: `integer`):

Concurrent rows (source requests are coalesced per domain).

## `emailsFileStoreId` (type: `string`):

For a JSON KV file reference, select its store to grant read-only access under Limited permissions. Native upload URLs can be read directly when accessible.

## Actor input object example

```json
{
  "emails": [
    "john.doe@gmail.com",
    "info@apify.com",
    "test@gmial.con",
    "user@mailinator.com",
    "bad email@@example"
  ],
  "findEmails": [
    "QA Owner, apify.com"
  ],
  "checkMx": true,
  "smtpVerification": false,
  "proxySessions": 1,
  "smtpTimeout": 10,
  "freshDisposableList": true,
  "deduplicate": true,
  "onlyValid": false,
  "onlyDeliverable": false,
  "dropDisposable": false,
  "dropRoleBased": false,
  "exportFormat": "default",
  "maxResults": 100,
  "maxConcurrency": 5
}
```

# Actor output Schema

## `results` (type: `string`):

Structured email validation records from the default Dataset.

## `summary` (type: `string`):

No description

## `errors` (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

```javascript
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": [
        "john.doe@gmail.com",
        "info@apify.com",
        "test@gmial.con",
        "user@mailinator.com",
        "bad email@@example"
    ],
    "findEmails": [
        "QA Owner, apify.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("apivault_labs/email-validator").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

```python
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": [
        "john.doe@gmail.com",
        "info@apify.com",
        "test@gmial.con",
        "user@mailinator.com",
        "bad email@@example",
    ],
    "findEmails": ["QA Owner, apify.com"],
}

# Run the Actor and wait for it to finish
run = client.actor("apivault_labs/email-validator").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

```bash
echo '{
  "emails": [
    "john.doe@gmail.com",
    "info@apify.com",
    "test@gmial.con",
    "user@mailinator.com",
    "bad email@@example"
  ],
  "findEmails": [
    "QA Owner, apify.com"
  ]
}' |
apify call apivault_labs/email-validator --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,apivault_labs/email-validator"
        }
    }
}
```

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/dyhXl9P3lmQfVN1VA/builds/GxzaZCRTIKLWvxxNx/openapi.json
