# Email Verifier & Checker - Bulk Verify Email Addresses (`pnda/email-verifier`) Actor

Email verifier and email checker: verify email addresses in bulk with a live SMTP mailbox check, MX, catch-all, disposable and role detection. Email validation that cuts bounces. $0.95 per 1,000, pay only for valid/invalid.

- **URL**: https://apify.com/pnda/email-verifier.md
- **Developed by:** [PNDA](https://apify.com/pnda) (community)
- **Categories:** Lead generation, Automation, Developer tools
- **Features:** Limited permissions
- **Stats:** 145 total users, 105 monthly users, 100.0% runs succeeded, 3 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $0.86 / 1,000 email verifieds

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](#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 Verifier & Validator — Bulk SMTP Email Verification, Catch-All Check

**Bulk email verifier and email validator** for cleaning email lists before you send. Paste a list (or send it through the API) and get, for every address, a clear verdict — `valid`, `invalid`, `catch-all`, `risky` or `unknown` — with the reason behind it.

For each email the Actor checks the **syntax**, looks up the domain's **MX records**, then runs a **live SMTP mailbox check** (`RCPT TO`) against the recipient's mail server to confirm that the mailbox exists. **No email is ever sent.** It also flags **catch-all domains**, **disposable / temporary email providers**, **role accounts** (`info@`, `sales@`, `support@`) and **free providers** (Gmail, Outlook, Yahoo), and suggests fixes for **typos** like `gmial.com` → `gmail.com`.

**You pay for real answers only:** $0.95 per 1,000 emails returned as `valid` or `invalid`, and **half price** ($0.475 per 1,000) for `catch-all`. Risky, unknown and duplicate emails are **free**.

Export results to **JSON, CSV, Excel or HTML**, or plug the Actor into **n8n, Make, Zapier, Clay, Google Sheets** or your own code through the Apify API.

> 🔎 **Don't have the emails yet?** [Email Finder](https://apify.com/pnda/email-finder) finds the work email of a person from their name and company domain, already verified ($4.99 per 1,000 emails found).

***

### 💡 Who is it for?

- **Cold email & sales teams** cleaning lead lists from Apollo, LinkedIn, Google Maps or any scraper before a campaign — fewer bounces, better sender reputation.
- **Growth & marketing teams** running email list hygiene on newsletters and CRM exports (HubSpot, Salesforce, Pipedrive, Mailchimp, Brevo).
- **Agencies** verifying client lists in bulk without a monthly SaaS subscription.
- **Developers** who need an **email validation API** for sign-up forms, onboarding or data pipelines.
- **Data teams** enriching and deduplicating contact databases.

***

### ⚙️ How it works

Every address goes through a **12-layer verification**, in this order:

| # | Check | What it detects | Output field |
|---|---|---|---|
| 1 | ✅ **Syntax / format** | Malformed addresses (`john@@acme`, `not-an-email`) | `syntaxValid` |
| 2 | ✅ **Typo correction** | `gmial.com`, `hotmial.com`, `yahooo.com`, `gmail.con` → corrected address | `suggestion` |
| 3 | ✅ **DNS / MX lookup** | Domains with no mail server (double-checked to avoid false `invalid`) | `mxFound` |
| 4 | ✅ **Mail server ID** | Which server handles the mail (Google, Microsoft, custom…) | `mxHost` |
| 5 | ✅ **Live SMTP mailbox check** | Whether the mailbox really exists (`RCPT TO`, **no email is sent**) | `deliverable`, `smtpCode` |
| 6 | ✅ **Full inbox** | Mailboxes that exist but can't receive mail right now | `fullInbox` |
| 7 | ✅ **Disabled mailbox** | Accounts that were closed or suspended | `disabled` |
| 8 | ✅ **Catch-all detection** | Domains that accept every address (risky to send to) | `catchAll` |
| 9 | ✅ **Disposable email** | Throwaway providers (Mailinator, Yopmail, 10minutemail…) | `disposable` |
| 10 | ✅ **Role account** | Generic inboxes (`info@`, `sales@`, `support@`) | `roleAccount` |
| 11 | ✅ **Mailbox type** | Free provider (Gmail, Outlook, Yahoo) vs professional domain | `freeProvider` |
| 12 | ✅ **Known hard bounces** | Addresses already reported as bounced by real email sends | `hardBounce` |

Every row ends with a clear **safe-to-send verdict** in `status`: `valid` (safe to send), `invalid` (do not send), `catch-all`, `risky` or `unknown`.

Duplicates are removed case-insensitively, so every address is verified — and billed — once.

***

### 📥 Input

| Field | Type | Required | Description |
|---|---|---|---|
| `emails` | array of strings | ✅ | The emails to verify — one per line in the Console, an array through the API |
| `checkCatchAll` | boolean | — | `true` (default): catch-all domains get the status `catch-all`. `false`: they are reported as `risky`. Billed at half price either way. |
| `timeoutSecs` | integer | — | Max wait per mail server, 5–120 s (default `30`). Servers that don't answer return `unknown` (free). |
| `concurrency` | integer | — | Emails verified in parallel, 1–10 (default `5`) |

#### Example input

```json
{
  "emails": [
    "rand@sparktoro.com",
    "john@gmial.com",
    "info@acme.com",
    "test@mailinator.com"
  ],
  "checkCatchAll": true,
  "timeoutSecs": 30,
  "concurrency": 5
}
```

***

### 📤 Output

One row per unique email. Example item:

```json
{
  "email": "rand@sparktoro.com",
  "status": "valid",
  "reason": "Mailbox exists",
  "suggestion": null,
  "syntaxValid": true,
  "domain": "sparktoro.com",
  "mxFound": true,
  "mxHost": "aspmx.l.google.com",
  "disposable": false,
  "roleAccount": false,
  "freeProvider": false,
  "catchAll": false,
  "smtpConnected": true,
  "deliverable": true,
  "fullInbox": false,
  "disabled": false,
  "smtpCode": null,
  "smtpMessage": null,
  "charged": true
}
```

A typo example:

```json
{
  "email": "info@gmial.com",
  "status": "invalid",
  "reason": "Domain has no mail server (MX)",
  "suggestion": "info@gmail.com",
  "mxFound": false,
  "roleAccount": true,
  "charged": true
}
```

A `SUMMARY` record in the run's key-value store counts results per status, duplicates and billed emails.

#### Statuses

| Status | Meaning | Billed |
|---|---|---|
| `valid` | The mail server confirmed the mailbox exists. Safe to send. Role accounts stay `valid` with `roleAccount: true`. | ✅ yes |
| `invalid` | Bad syntax, no MX record, mailbox rejected or disabled (SMTP 550–553 "user unknown"). Remove it. | ✅ yes |
| `catch-all` | The domain accepts every address (accept-all), so the single mailbox can't be confirmed. | ½ half price |
| `risky` | Disposable / temporary email provider, full inbox, or catch-all when `checkCatchAll` is off. | ❌ free (catch-all: half price) |
| `unknown` | No clear answer: timeout, greylisting, temporary server error. Re-run later. | ❌ free |

#### Field reference

| Field | Meaning |
|---|---|
| `status` / `reason` | The verdict and a human-readable explanation |
| `suggestion` | Corrected address when the domain looks like a typo of a common provider |
| `syntaxValid` | RFC-style syntax check passed |
| `mxFound` / `mxHost` | The domain has a mail server, and which one (Google Workspace, Microsoft 365…) |
| `smtpConnected` / `deliverable` | The SMTP server answered / accepted the mailbox |
| `smtpCode` / `smtpMessage` | Raw SMTP reply code and message when the server rejected the address |
| `catchAll` | The domain accepts any address |
| `disposable` | Throwaway / temporary email provider |
| `roleAccount` | Generic inbox: `info@`, `sales@`, `support@`, `admin@`… |
| `freeProvider` | Gmail, Outlook, Yahoo, iCloud… |
| `fullInbox` / `disabled` | Mailbox full / mailbox disabled |
| `charged` | Whether this row was billed |

***

### 🚀 Why use this Email Verifier

- ✅ **Real SMTP verification**, not just syntax and MX — the mail server itself is asked whether the mailbox exists.
- ✅ **Pay for real answers only** — catch-all at half price, risky and unknown free. On B2B lists, where 20–40% of addresses sit on catch-all domains, that is a real saving.
- ✅ **Fewer false `invalid`** — "no MX" answers are double-checked with a second DNS lookup before an email is rejected.
- ✅ **Typo correction** built in — recover leads instead of deleting them.
- ✅ **Budget-safe** — set *Maximum cost per run* and the Actor never goes over it.
- ✅ **No API key, no subscription, no credits that expire** — pay per result, export anywhere.
- ✅ **Pipeline-ready** — chain it after any scraper, or call it from n8n, Make, Zapier or the Apify API.

***

### 📊 Comparison

| | **This Actor** | Typical Store email verifiers | Email verification SaaS |
|---|---|---|---|
| Price per 1,000 | **$0.95** | $0.89 – $5.00 | monthly plans or prepaid credits |
| Catch-all billed | **Half price** | Full price | Usually full price |
| Unknown / timeout billed | **No** | Yes | Varies |
| Duplicates billed | **No** (deduplicated) | Often yes | Varies |
| Live SMTP mailbox check | ✅ | ✅ / partial | ✅ |
| Typo suggestions | ✅ | Rare | Some |

Example — 1,000 B2B emails with 30% on catch-all domains: ~700 results at full price plus 300 catch-all at half price, about **$0.81**.

***

### 💼 Use cases

- **Clean a cold email list** before uploading it to Instantly, Lemlist, Smartlead or Apollo sequences.
- **Lower your bounce rate** under 2% to protect domain reputation and deliverability.
- **Validate emails scraped** from Google Maps, LinkedIn, YouTube channels or websites.
- **CRM hygiene** — re-verify old contacts quarterly and drop dead mailboxes.
- **Sign-up form validation** — call the API synchronously and reject disposable or mistyped emails.
- **Lead enrichment** — keep only `valid` emails, flag `catch-all` for a lower-priority sequence.

***

### 💰 Pricing

**Store discounts:** on Apify Silver, Gold, Platinum and Diamond plans, some events cost up to 20 % less. The Pricing tab of the Store page shows the exact price for each plan.

**Pay per event: $0.95 per 1,000 verified emails** ($0.00095 per email returned `valid` or `invalid`) and **$0.475 per 1,000 catch-all emails** (half price), plus Apify's tiny per-run start fee. Risky, unknown and duplicate emails cost nothing.

| Run | Emails | Max cost |
|---|---|---|
| Small list | 100 | ~$0.10 |
| Campaign list | 1,000 | ~$0.95 |
| Large list | 10,000 | ~$9.50 |
| Database cleanup | 100,000 | ~$95 |

Costs are a maximum: every catch-all (half price) or unknown (free) result lowers the bill.

**Works with a free Apify account too.** Free-plan accounts can use every feature at the same per-result prices, paid from their monthly Apify credit. The only limits are your credit and your maximum cost per run.

***

### 🔌 Use it through the API

Synchronous call — send emails, get results back in the same request:

```bash
curl -X POST "https://api.apify.com/v2/acts/pnda~email-verifier/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"emails": ["rand@sparktoro.com", "nobody@example.com"]}'
```

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("pnda/email-verifier").call(run_input={"emails": ["rand@sparktoro.com"]})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["email"], item["status"], item["reason"])
```

JavaScript:

```js
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });
const run = await client.actor('pnda/email-verifier').call({ emails: ['rand@sparktoro.com'] });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

***

### ❓ FAQ

**Does it send emails to the addresses?**
No. The SMTP conversation stops at `RCPT TO`, before any message is sent. Recipients see nothing.

**How accurate is the email verification?**
`valid` and `invalid` come straight from the recipient's mail server, so they are as reliable as SMTP allows. When the server can't give a definite answer, the email is reported as `catch-all`, `risky` or `unknown` instead of being guessed — catch-all at half price, the others free.

**What is a catch-all email?**
A catch-all (accept-all) domain accepts mail for any address, so no SMTP verifier can confirm one specific mailbox. Many Google Workspace and Microsoft 365 company domains are configured this way. These results cost half price here.

**Why do I get `unknown`?**
Some servers delay unknown senders (greylisting) or answer slowly. The Actor retries once; if the answer is still unclear, the result is `unknown` and free. Re-run those emails later or raise `timeoutSecs`.

**Can it detect disposable and temporary emails?**
Yes — Mailinator, Yopmail, 10minutemail, Guerrilla Mail and similar providers are flagged `disposable` and returned as `risky`.

**How fast is it?**
About 60 emails in 12 seconds with `concurrency: 10`. Slow mail servers take longer; lists of tens of thousands run fine in a single run.

**Can I verify a CSV file?**
Paste the email column into the `emails` field, or read your CSV in code and send the array through the API. Export results back to CSV or Excel from the dataset.

**Is it a ZeroBounce / NeverBounce / Hunter alternative?**
For list cleaning, yes: same kind of SMTP verification, pay-as-you-go, no subscription, catch-all at half price and unknown results free.

**Can I use it on the free Apify plan?**
Yes. It works with a free Apify account too, at the same prices, paid from your monthly Apify credit ([pricing](https://apify.com/pricing)).

**How do I control spending?**
Set *Maximum cost per run* in the run options. The Actor stops before it would exceed it.

**Does it store my data?**
The Actor only checks whether a mailbox exists; it doesn't store or enrich personal data beyond your run's dataset, which you control and can delete at any time.

***

### Related actors

- [Email Extractor](https://apify.com/pnda/email-extractor): Need emails first? Extract the contacts published on a list of websites, already verified.
- [Email Finder](https://apify.com/pnda/email-finder): Have a name and a company? Find the person's work email, verified.
- [Google Maps API & Scraper](https://apify.com/pnda/google-maps-scraper): Building a local B2B list? Get businesses with their website emails, then verify them here.
- [Shopify & WooCommerce Stores Database](https://apify.com/pnda/shopify-woocommerce-stores): Building an e-commerce list? Start from Shopify and WooCommerce stores filtered by country and category.

***

### ▶️ Start now

Paste your email list. Click **Run**. Download the clean list.
Valid emails in, bounces out — and you only pay for real answers.

# Actor input Schema

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

One email address per line (paste your list, or send an array through the API). Duplicates are removed automatically (case-insensitive) and verified once.

## `checkCatchAll` (type: `boolean`):

Catch-all servers accept every address, so the mailbox cannot be confirmed. On: such emails get the status "catch-all". Off: they are reported as "risky". Both are charged at half price.

## `timeoutSecs` (type: `integer`):

Maximum time to wait for the mail server of one address. Slow servers that do not answer in time are returned as "unknown" (not charged).

## `concurrency` (type: `integer`):

How many emails are verified in parallel.

## Actor input object example

```json
{
  "emails": [
    "rand@sparktoro.com"
  ],
  "checkCatchAll": true,
  "timeoutSecs": 30,
  "concurrency": 5
}
```

# Actor output Schema

## `dataset` (type: `string`):

All verifications (JSON, CSV, Excel).

# 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": [
        "rand@sparktoro.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("pnda/email-verifier").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": ["rand@sparktoro.com"] }

# Run the Actor and wait for it to finish
run = client.actor("pnda/email-verifier").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": [
    "rand@sparktoro.com"
  ]
}' |
apify call pnda/email-verifier --silent --output-dataset

```

## MCP server setup

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

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/n4DH6fL7RqbgyJjEq/builds/nYYlfjg6K8JODaGtj/openapi.json
