# Bulk Email Verifier (`eliai/email-list-verifier`) Actor

Clean a list before you send it. Catches null-MX domains that guarantee a bounce, keeps implicit-MX domains other tools wrongly delete, and separates disposable from role addresses. Never charges for an address it could not resolve. $0.80 per 1,000 on paid plans.

- **URL**: https://apify.com/eliai/email-list-verifier.md
- **Developed by:** [Anthony Snider](https://apify.com/eliai) (community)
- **Categories:** Lead generation, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.50 / 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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## Bulk Email Verifier

Clean a list before you send to it. Paste addresses, get back which will deliver, which are risky,
and which will bounce — each with a reason you can act on.

**You are only charged for addresses that return a verdict.** If DNS is temporarily unreachable an
address comes back `unknown`, free, with a note to re-run it. No verifier can be certain in that
moment, and pretending otherwise is how good customers get deleted.

---

### Why lists bounce even after "verification"

Most cheap verifiers run a regex and check whether an MX record exists. That is wrong in four ways,
and each one costs money in a different direction.

#### 1. A null MX record means the domain refuses mail — and naive tools call it valid

Under **RFC 7505**, a domain can publish a single MX record whose exchange is a lone dot:

````

example.com.   IN   MX   0 .

````

That is not a mail server. It is an explicit, standards-defined statement that **this domain accepts
no email at all**. A tool that only asks "is an MX record present?" sees one record and returns
*valid*. Every message you send there bounces. We detect it and mark the address `invalid` with the
reason stated.

#### 2. A domain with no MX record can still receive mail — and naive tools delete it

**RFC 5321** defines an *implicit MX*: if a domain has no MX record but does have an A or AAAA
record, mail is delivered to that host. Plenty of small business domains work exactly this way. A
verifier that requires an MX record marks these `invalid` and you quietly remove real, reachable
customers from your list. We check A and AAAA as a fallback and report `mxKind: "implicit-a"` so you
can see why it passed.

#### 3. A typo domain resolves, accepts mail, and is not your customer

`gmial.com`, `hotnail.com`, `yahooo.com` — these are registered, they run mail servers, and they
accept whatever arrives. That is the entire business model of typosquatting: collecting misdirected
email. Check only for an MX record and they come back *valid*, which is worse than useless — you're
told a wrong address is safe. We flag them `risky` and return the likely correction in
`didYouMean`.

#### 4. A DNS timeout is not evidence of a bad address

If a lookup fails for a moment, that tells you nothing about the address. Tools that return
*invalid* on a lookup error silently destroy list quality over time. We return `unknown`, don't
charge for it, and tell you to re-run.

---

### Disposable and role addresses are different problems

Most tools lump them together as "risky", which makes the flag useless because you can't act on it.

**Disposable** — `mailinator.com`, `10minutemail.com`, `guerrillamail.com` and similar. The address
works right now and will be abandoned. Someone wanted your lead magnet without giving you a real
address. These are churn: they inflate your list size and deflate every engagement metric.

**Role-based** — `info@`, `sales@`, `support@`, `billing@`, `careers@`. These are usually real,
monitored, and deliverable. They are *not* a person, so open and click rates look terrible, and some
ESPs weigh them negatively. For B2B outreach they may be exactly who you want; for a consumer
newsletter they are noise. Different decision, so we report them separately — and `+tag` addressing
(`you+newsletter@gmail.com`) is correctly read as personal, not as a role account.

---

### What each verdict means

| status | deliverable | what to do |
|---|---|---|
| `valid` | yes | Send. Domain accepts mail, no risk flags. |
| `risky` | yes | Your call — check `disposable`, `roleBased`, `didYouMean` to decide. |
| `invalid` | no | Remove. Bad syntax, dead domain, or a null-MX refusal. |
| `unknown` | unknown | Re-run. DNS was unreachable. **Not charged.** |

`mxKind` tells you exactly why: `mx`, `implicit-a`, `implicit-aaaa`, `null-mx`, `no-mx`, `dns-error`.

---

### Input

Paste a list — new lines, commas or spaces all work, and duplicates are removed automatically:

```json
{ "emailsText": "hello@acme.com\ninfo@example.com\ntest@mailinator.com" }
````

Or pass an array:

```json
{ "emails": ["a@b.com", "c@d.com"], "maxEmails": 5000 }
```

| Field | Type | Default | Notes |
|---|---|---|---|
| `emailsText` | string | — | Pasted list, any common separator |
| `emails` | array | — | For API and integration use |
| `email` | string | — | Verify a single address |
| `maxEmails` | integer | 1000 | Cap on addresses, and therefore on spend |

### Output

One record per address, plus a `SUMMARY` with counts and rates:

```json
{
  "email": "someone@gmial.com",
  "status": "risky",
  "deliverable": true,
  "reason": "Likely typo of gmail.com — this domain resolves and accepts mail, which is how typosquatters collect misdirected email. Confirm before sending.",
  "domain": "gmial.com",
  "mxFound": true,
  "mxKind": "mx",
  "disposable": false,
  "roleBased": false,
  "freeProvider": false,
  "didYouMean": "someone@gmail.com"
}
```

***

### What this does not do

Stated plainly, because a verifier that overclaims is the problem it's meant to solve.

- **No SMTP mailbox probing.** We do not open a connection to the mail server to ask whether a
  specific mailbox exists. Tools that do are throttled, blocked, or graylisted by every major
  provider, and catch-all domains accept everything anyway, so the answer is frequently wrong. We
  verify the *domain* can receive mail and report risk signals honestly rather than guessing at the
  mailbox.
- **No spam-trap database.** Nobody has a reliable public one; anyone claiming otherwise is selling
  confidence.
- **No engagement history.** We see the address, not what your recipients did.

If you need mailbox-level certainty, no DNS-based verifier can give it to you — send a
double-opt-in confirmation.

### For agents and automation

- **Capability:** bulk email deliverability verification via DNS
- **Required input:** one of `emailsText`, `emails`, or `email`
- **Returns:** one JSON record per address plus a `SUMMARY`
- **Bounded:** `maxEmails` caps the run and the spend
- **Side effects:** none — DNS lookups only. No mail is sent, nothing is stored externally.
- **Determinism:** deterministic given stable DNS. The non-deterministic case is marked `unknown`
  explicitly rather than guessed.

### Pricing

Pay per address that returns a verdict. Duplicates are removed before billing, and `unknown`
results are free. **$0.80 per 1,000 addresses** on paid plans.

# Actor input Schema

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

Paste addresses separated by new lines, commas or spaces. Duplicates are removed automatically.

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

For API and integration use.

## `email` (type: `string`):

Verify one address.

## `maxEmails` (type: `integer`):

Safety cap. You are charged per address that returns a verdict, so this is also your budget cap.

## Actor input object example

```json
{
  "emailsText": "hello@apify.com\ninfo@example.com\nnobody@thisdomaindoesnotexist12345.com",
  "maxEmails": 1000
}
```

# 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 = {
    "emailsText": `hello@apify.com
info@example.com
nobody@thisdomaindoesnotexist12345.com`
};

// Run the Actor and wait for it to finish
const run = await client.actor("eliai/email-list-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 = { "emailsText": """hello@apify.com
info@example.com
nobody@thisdomaindoesnotexist12345.com""" }

# Run the Actor and wait for it to finish
run = client.actor("eliai/email-list-verifier").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "emailsText": "hello@apify.com\\ninfo@example.com\\nnobody@thisdomaindoesnotexist12345.com"
}' |
apify call eliai/email-list-verifier --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=eliai/email-list-verifier",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Bulk Email Verifier",
        "description": "Clean a list before you send it. Catches null-MX domains that guarantee a bounce, keeps implicit-MX domains other tools wrongly delete, and separates disposable from role addresses. Never charges for an address it could not resolve. $0.80 per 1,000 on paid plans.",
        "version": "0.1",
        "x-build-id": "n60V5TBrmYFwgDoA6"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/eliai~email-list-verifier/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-eliai-email-list-verifier",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/eliai~email-list-verifier/runs": {
            "post": {
                "operationId": "runs-sync-eliai-email-list-verifier",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/eliai~email-list-verifier/run-sync": {
            "post": {
                "operationId": "run-sync-eliai-email-list-verifier",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "emailsText": {
                        "title": "Paste your list",
                        "type": "string",
                        "description": "Paste addresses separated by new lines, commas or spaces. Duplicates are removed automatically."
                    },
                    "emails": {
                        "title": "Emails (array)",
                        "type": "array",
                        "description": "For API and integration use.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "email": {
                        "title": "Single email",
                        "type": "string",
                        "description": "Verify one address."
                    },
                    "maxEmails": {
                        "title": "Max addresses",
                        "minimum": 1,
                        "maximum": 10000,
                        "type": "integer",
                        "description": "Safety cap. You are charged per address that returns a verdict, so this is also your budget cap.",
                        "default": 1000
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
