# Email Validator: Bulk MX, Disposable & Typo Check (`cyborg_cell/email-validator`) Actor

Bulk email validator and email list cleaner: syntax check, domain and MX lookup, disposable and free-provider detection, role accounts and typo suggestions. Never contacts the mailbox, so your sender reputation stays safe.

- **URL**: https://apify.com/cyborg_cell/email-validator.md
- **Developed by:** [Aditya Sapra](https://apify.com/cyborg_cell) (community)
- **Categories:** Lead generation, Marketing, 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 checkeds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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** is a bulk email validator and email list cleaner. For every address you get a clear verdict and the reasons behind it: is it well formed, can its domain receive mail, is it a throwaway address, a role account like `info@`, or a likely typo of a well-known domain?

It checks everything that can be checked **without ever contacting the recipient's mail server**. No test emails, no mailbox probing, nothing that could hurt your sender reputation or the recipient. Use it to clean signup lists, CRM exports and cold-email lists before you send, or call it from your signup form through the API.

### What is it good for?

- **Marketing and sales teams**: clean a list before you send, to protect your sender reputation.
- **Signup forms and CRMs**: block throwaway addresses and catch typos like `gmial.com`.
- **Agencies**: hand clients cleaner lists.
- **Developers**: a pay-per-address validation API with no subscription.

### Try it in 30 seconds

1. Press **Start**: the input is prefilled with real examples.
2. Open the **Output** tab and download JSON, CSV or Excel.
3. Replace the examples with your own and run again. You pay about **$0.50 per 1,000 emails**.

#### A taste of the output

| Email | Verdict | Why | Suggested fix |
|---|---|---|---|
| `john.doe@gmial.com` | risky | no_mx_record_uses_address_record, possible_typo, disposable_domain | `john.doe@gmail.com` |

The full record has more fields; see the example output further down.

### What does Email Validator check?

| Check | What it tells you |
|---|---|
| **Syntax** | RFC-compliant format, length limits (64 / 254), internationalised addresses (`ünï@bücher.de`) |
| **Domain and MX** | Whether the domain exists and publishes mail servers (with the standard fallback to the domain's own address record, and detection of "null MX" domains that refuse mail) |
| **Disposable domains** | About 9,000 known throwaway-mailbox services (Mailinator and similar) |
| **Free providers** | Gmail, Yahoo, Outlook and ~100 more, flagged so you can tell personal from business addresses |
| **Role accounts** | `info@`, `support@`, `sales@`, `noreply@` and similar shared mailboxes |
| **Typo suggestions** | `john@gmial.com` becomes `john@gmail.com`, `.con` and `.cmo` endings are fixed too |

### What does it not do?

It does **not** tell you whether a specific mailbox exists (`jane@company.com` versus `jjane@company.com`). That needs an SMTP conversation with the recipient's server, which this Actor never starts. `valid` means "well formed, and its domain accepts mail". If you need mailbox-level proof, use this Actor first to remove the obvious junk, then a mailbox-verification service for what is left.

### How do I validate an email list?

1. Paste addresses, one per line (commas, semicolons and spaces also separate them). Duplicates are removed and charged once.
2. Run it and download JSON, CSV or Excel, or call it through the API from your signup form or CRM.

#### Example input

```json
{
  "emails": ["hello@apify.com", "test@gmail.com", "info@mailinator.com", "john.doe@gmial.com", "not-an-email"],
  "checkMx": true,
  "detectDisposable": true,
  "suggestTypoFixes": true
}
```

#### What does the output look like?

One record per address, in the order you supplied them:

```json
{
  "email": "john.doe@gmial.com",
  "normalized": "john.doe@gmial.com",
  "status": "risky",
  "reasons": [
    "no_mx_record_uses_address_record",
    "possible_typo",
    "disposable_domain"
  ],
  "error": null,
  "validSyntax": true,
  "localPart": "john.doe",
  "domain": "gmial.com",
  "isDisposable": true,
  "isFreeProvider": false,
  "isRoleAccount": false,
  "hasMx": false,
  "mxHosts": [],
  "suggestion": "john.doe@gmail.com",
  "mailboxChecked": false
}
```

#### What do the status values mean?

| `status` | Meaning |
|---|---|
| `valid` | Well formed, and the domain accepts mail |
| `risky` | Well formed and the domain accepts mail, but it is a disposable domain, a role account, or a likely typo |
| `undeliverable` | Invalid syntax, or the domain does not exist or cannot receive mail |
| `unknown` | The DNS lookup failed temporarily. Try again later |

`reasons` lists every finding: `invalid_syntax`, `domain_not_found`, `no_mail_server`, `domain_does_not_accept_email`, `dns_lookup_failed`, `disposable_domain`, `role_account`, `possible_typo`, `no_mx_record_uses_address_record`. The flags `isDisposable`, `isRoleAccount` and `isFreeProvider` let you decide for yourself, for example keep role accounts for support mailings but drop them for sales outreach.

`mailboxChecked` is always `false`, to make the limit above explicit in the data itself.

### How much does it cost to validate emails?

You pay per address checked: **$0.0005 per email, about $0.50 per 1,000 emails**, plus a tiny fixed fee per run. Duplicates are removed and charged once. Apify bills the platform usage of the run (compute) on top, which is normally a small fraction of the per-address price. **Max addresses to check** is a hard cap on the cost of a run, and the run also stops if it reaches the maximum charge you set in the run options. The Pricing tab always shows the current rate.

### Can I use Email Validator through the API?

Yes. Like every Apify Actor it can be started from code, scheduled in the Apify Console, or connected to Make, Zapier, n8n, Google Sheets and webhooks through Apify integrations, for example to check every new signup or CRM contact automatically.

**Python**

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")
run_input = {
    "emails": [
        "hello@apify.com",
        "test@gmail.com",
        "john.doe@gmial.com"
    ]
}
run = client.actor("cyborg_cell/email-validator").call(run_input=run_input)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

**JavaScript**

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

const client = new ApifyClient({ token: '<YOUR_API_TOKEN>' });
const input = {
  "emails": [
    "hello@apify.com",
    "test@gmail.com",
    "john.doe@gmial.com"
  ]
};
const run = await client.actor('cyborg_cell/email-validator').call(input);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

**cURL**

```bash
curl -X POST "https://api.apify.com/v2/acts/cyborg_cell~email-validator/run-sync-get-dataset-items?token=<YOUR_API_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"emails": ["hello@apify.com", "test@gmail.com", "john.doe@gmial.com"]}'
```

### FAQ

#### Is this an email verifier that checks whether the mailbox exists?

No. It validates syntax and domain, flags disposable domains, free providers and role accounts, and suggests typo fixes, but it never talks to the recipient's mail server, so it cannot confirm that a specific mailbox exists. That is also why it is safe to run on any list: nothing is sent and nothing can bounce.

#### Can I use it as a disposable email checker?

Yes. Every address is compared with about 9,000 known throwaway-mailbox domains (Mailinator and similar). Matches get `isDisposable: true`, the reason `disposable_domain` and the status `risky`, so you can drop them from a signup list or a mailing.

#### Is there an MX record checker built in?

Yes. The Actor looks up the mail servers (MX records) of every domain, falls back to the domain's own address record the way mail software does, and detects "null MX" domains that refuse mail. Domains without a working mail setup are marked `undeliverable`.

#### Does it work as an email syntax checker?

Yes. Syntax is checked against the RFC rules, including length limits (64 characters before the @, 254 in total) and internationalised addresses. Invalid addresses are marked `undeliverable` with the reason `invalid_syntax`.

#### Can it clean an email list?

Yes, that is the main use. Paste the list, run it, then keep the rows with `status` `valid` (and decide about `risky` ones such as role accounts) and drop the rest. Duplicates are removed for you.

#### Will it hurt my sender reputation?

No. The Actor sends no email and makes no SMTP connection. It only looks up the DNS records of the domains in your list.

#### How many addresses can I check in one run?

Up to 100,000 addresses per run by default; raise **Max addresses to check** to go up to 1,000,000. Domain lookups are cached, so a list with thousands of addresses at the same few domains is fast.

#### Where does the disposable-domain list come from?

From the community-maintained [disposable-email-domains](https://github.com/disposable-email-domains/disposable-email-domains) list (public domain, CC0), snapshot of 4 October 2026, refreshed whenever this Actor is updated.

#### Could a real company domain be "corrected" by mistake?

No. Typo suggestions are only offered for well-known domains such as Gmail, Yahoo and Outlook.

#### Is it safe for personal data?

The Actor only processes the addresses you submit, sends nothing to them and keeps nothing after your run besides the results you download. You are responsible for having a lawful basis to process the addresses you submit and for how you use the results.

#### A verdict looks wrong, or a disposable domain was missed. What now?

Open an issue on the Actor page with the address (or just its domain) and we will look at it.

### Other Actors by the same author

- [ATS Job Scraper (Greenhouse, Lever, Ashby, Workday and four more platforms)](https://apify.com/cyborg_cell/ats-job-listings-api) and [Remote Jobs Scraper (RemoteOK, Himalayas, Jobicy, Arbeitnow)](https://apify.com/cyborg_cell/remote-jobs-aggregator): structured job data from company career pages and remote job boards.
- Also by the same author: [Website Screenshot API & URL to PDF Converter](https://apify.com/cyborg_cell/website-screenshot-pdf), [YouTube Transcript Scraper](https://apify.com/cyborg_cell/youtube-transcript-scraper).

# Actor input Schema

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

One per line (commas, semicolons and spaces also separate addresses). Duplicates are removed and charged once.

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

Looks up the domain's mail servers (MX records). Turn off for syntax-only checks.

## `detectDisposable` (type: `boolean`):

Flags throwaway-mailbox services (about 9,000 known domains).

## `suggestTypoFixes` (type: `boolean`):

Suggests the corrected address when a well-known domain looks mistyped (gmial.com -> gmail.com).

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

Hard cap on the number of addresses checked in one run. You are charged per address checked.

## `dnsTimeoutSecs` (type: `integer`):

How long to wait for each domain lookup.

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

How many domain lookups run at once.

## Actor input object example

```json
{
  "emails": [
    "hello@apify.com",
    "test@gmail.com",
    "info@mailinator.com",
    "john.doe@gmial.com",
    "not-an-email",
    "someone@no-such-domain-xyz-123.com"
  ],
  "checkMx": true,
  "detectDisposable": true,
  "suggestTypoFixes": true,
  "maxEmails": 100000,
  "dnsTimeoutSecs": 5,
  "maxConcurrency": 50
}
```

# Actor output Schema

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

One record per address.

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

Counts per status and how many domains were looked up.

# 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": [
        "hello@apify.com",
        "test@gmail.com",
        "info@mailinator.com",
        "john.doe@gmial.com",
        "not-an-email",
        "someone@no-such-domain-xyz-123.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("cyborg_cell/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": [
        "hello@apify.com",
        "test@gmail.com",
        "info@mailinator.com",
        "john.doe@gmial.com",
        "not-an-email",
        "someone@no-such-domain-xyz-123.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("cyborg_cell/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": [
    "hello@apify.com",
    "test@gmail.com",
    "info@mailinator.com",
    "john.doe@gmial.com",
    "not-an-email",
    "someone@no-such-domain-xyz-123.com"
  ]
}' |
apify call cyborg_cell/email-validator --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,cyborg_cell/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/uhUSilK7cz6y7TRJO/builds/I5nO8gyqBUDa72O4y/openapi.json
