# Bulk Email Validator - Syntax, MX, Disposable & Role Check (`plotpointtech/bulk-email-validator`) Actor

Pre-clean email lists for $0.30 per 1,000: syntax, domain/MX, mail provider, disposable, role, free-mail and typo checks (gmial.com -> gmail.com) with a risk score. No SMTP mailbox check; thousands of emails per minute.

- **URL**: https://apify.com/plotpointtech/bulk-email-validator.md
- **Developed by:** [Plot Point Technologies](https://apify.com/plotpointtech) (community)
- **Categories:** Lead generation, Developer tools, Automation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.19 / 1,000 email checkeds

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

## Bulk Email Validator: Syntax, MX, Disposable & Role Check

**Clean an email list before you send to it or pay for full verification.** Paste addresses or link a CSV, and get one record per email with a **low / medium / high risk score** and the reasons: bad syntax, domains that do not exist or accept no mail, disposable (temporary) providers, role accounts like info@ or noreply@, free-mail addresses, and typos such as `gmial.com`, with a suggested fix. It also tells you who hosts each domain's mail (Google Workspace, Microsoft 365, Proofpoint...). **$0.30 per 1,000 emails.**

> **What this tool does not do.** It does not connect to mail servers (SMTP), because outbound port 25 is blocked on Apify. So it **cannot confirm that a specific mailbox exists** and **cannot detect catch-all domains**. A `low` risk score means "no problems found in syntax and DNS", not "verified deliverable". Use it as a cheap pre-cleaning step; send the remaining `low`-risk addresses to an SMTP verifier only if you need mailbox-level certainty.

### What does this email validator check?

| Check | Output fields | How |
|---|---|---|
| **Syntax** (RFC 5321/5322, international addresses) | `syntaxValid`, `syntaxError`, `normalized`, `localPart`, `hasPlusTag` | `email-validator` library; reserved names such as `.test` and `.invalid` are rejected |
| **Domain and MX** | `domain`, `hasMx`, `mxHosts`, `acceptsMail` | Live DNS lookup, cached once per domain; detects non-existent domains, null MX (`0 .`) and A-record fallback |
| **Mail provider** | `mailProvider` | Read from MX hosts: Google Workspace, Microsoft 365, Gmail, Outlook.com, Yahoo, Zoho, Proofpoint, Mimecast, Cisco, Barracuda, IONOS, GoDaddy, Self-hosted and more |
| **Disposable / temporary** | `isDisposable` | 10,000+ domains from the open-source [disposable-email-domains](https://github.com/disposable-email-domains/disposable-email-domains) list (CC0 public domain), including subdomains |
| **Role accounts** | `isRole`, `isNoReply` | 140+ shared-mailbox names (info, sales, support, admin, hr, noreply...) |
| **Free mail** | `isFreeMail` | Gmail, Yahoo, Outlook/Hotmail, AOL, iCloud, Proton, GMX, Yandex, Mail.ru, ISPs and more; regional variants detected from MX |
| **Typos** | `typoSuggestion`, `suggestedEmail` | Misspellings of big providers (`gmial.com` -> `gmail.com`, `hotmail.co` -> `hotmail.com`) and of .com/.net/.org (`acme.con` -> `acme.com`) |
| **Risk** | `riskScore`, `riskReasons` | `high`, `medium` or `low`, with every reason listed |

`mailboxChecked` is always `false`, so anyone reading your export knows no SMTP check was made.

#### How the risk score works

- **high**: invalid syntax, domain does not exist, null MX or no MX/A record (cannot receive mail), disposable provider, no-reply address, or a likely typo.
- **medium**: role account, no MX record but the domain has an A record (unusual setup), or the DNS lookup failed.
- **low**: none of the above. Free-mail addresses stay `low` but carry the reason "free email provider" so B2B users can filter them.

### Who uses it?

- **Marketers and email senders** removing addresses that would bounce or hurt sender reputation before a campaign.
- **Sales and lead-gen teams** flagging free-mail, role and disposable addresses in scraped or purchased lead lists, and seeing which leads use Google Workspace or Microsoft 365.
- **SaaS and e-commerce teams** checking sign-up lists for throwaway addresses and typos (`gmial.com`) that cost you customers.
- **Data teams** cutting the cost of full SMTP verification by removing obvious junk first.

### How to use it

1. Click **Try for free** (or **Start**).
2. Paste addresses into **Email addresses**, one per line, and/or add links to CSV or text files in **Email list URLs** (every address in the file is picked up).
3. Leave the checks on and press **Start**. Thousands of emails are checked per minute; domains are looked up once and reused.
4. Download the results as CSV, Excel or JSON. Filter `riskScore = high` to remove, review `medium`, and fix entries with a `suggestedEmail`.

### Input example

```json
{
  "emails": [
    "webmaster@python.org",
    "jane.doe@gmial.com",
    "test@mailinator.com",
    "john.smith@example.com",
    "sales@acme.con",
    "not-an-email@"
  ],
  "emailListUrls": [],
  "checkMx": true,
  "checkTypos": true,
  "deduplicate": true
}
```

| Field | Description |
|---|---|
| `emails` | Addresses, one per line. `Name <a@b.com>` and `mailto:` forms are cleaned. |
| `emailListUrls` | Links to CSV/TXT files (e.g. a published Google Sheet CSV, a Dropbox or S3 link). |
| `checkMx` | Look up MX records (default on). Off = syntax, disposable, role, free-mail and typo checks only. |
| `checkTypos` | Suggest corrections for misspelled domains (default on). |
| `deduplicate` | Check each address once, case-insensitive (default on). |
| `maxEmails` | Upper limit per run. |

### Output example

A real record from the default run:

```json
{
  "email": "jane.doe@gmial.com",
  "normalized": "jane.doe@gmial.com",
  "syntaxValid": true,
  "syntaxError": null,
  "localPart": "jane.doe",
  "domain": "gmial.com",
  "hasMx": false,
  "mxHosts": [],
  "acceptsMail": true,
  "mailProvider": null,
  "isDisposable": true,
  "isRole": false,
  "isNoReply": false,
  "isFreeMail": false,
  "hasPlusTag": false,
  "typoSuggestion": "gmail.com",
  "suggestedEmail": "jane.doe@gmail.com",
  "riskScore": "high",
  "riskReasons": [
    "disposable / temporary email provider",
    "domain looks like a typo of gmail.com",
    "no MX record; mail would fall back to the domain's A record"
  ],
  "mailboxChecked": false,
  "checkedAt": "2026-10-31T19:17:42Z"
}
```

The dataset view shows email, risk, reasons, domain, MX, provider and flags as a table.

### How much does it cost?

**$0.30 per 1,000 emails** ($0.0003 per checked address), plus a $0.00005 start fee per run. Every input address produces one result and is charged once, including invalid ones; duplicates are removed for free when `deduplicate` is on.

| You check | You pay |
|---|---|
| 1,000 sign-ups | $0.30 |
| 25,000-address newsletter list | $7.50 |
| 200,000 scraped leads | $60.00 |

Full SMTP verifiers in the Apify Store typically charge about $0.89 to $1.50 per 1,000. Running this first and verifying only the `low`-risk remainder usually lowers the total bill.

**Volume discounts on higher Apify plans.** The prices above are for the Apify Free plan. On paid plans the per-result price drops automatically: about 15% lower on Bronze, 25% lower on Silver and 38% lower on Gold and above.

### Use it via API, Make, Zapier, n8n or an AI agent

**Apify API.** Start a run and get the results back in one HTTP request (replace `YOUR_API_TOKEN` with the token from Apify Console > Settings > Integrations):

```bash
curl -X POST "https://api.apify.com/v2/acts/plotpointtech~bulk-email-validator/run-sync-get-dataset-items?token=YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"emails": ["webmaster@python.org", "jane.doe@gmial.com"]}'
```

For large lists, start the run asynchronously and read the dataset when it finishes. Official `apify-client` libraries exist for Python and JavaScript; the **API** tab on this page has ready-made code.

**No-code automation.** Connect the tool to **Make, Zapier, n8n, Google Sheets, HubSpot (via webhooks), Airtable** or any webhook with Apify integrations, for example to check each new form sign-up.

**AI agents (MCP).** Give Claude, ChatGPT, Cursor, VS Code or any MCP-compatible agent direct access to this tool through the hosted Apify MCP server:

```
https://mcp.apify.com?tools=plotpointtech/bulk-email-validator
```

### FAQ

**Does it verify that a mailbox exists?**
No. Mailbox verification needs an SMTP conversation on port 25, which Apify blocks. The tool checks everything that can be known without it: syntax, the domain's DNS and MX setup, and known lists. An address can pass every check and still bounce if the mailbox was deleted.

**Can it detect catch-all (accept-all) domains?**
No. Catch-all detection also needs SMTP. Note that many typo and disposable domains accept all mail, which is why those are scored `high` anyway.

**How accurate is the disposable list?**
It is the widely used community-maintained [disposable-email-domains](https://github.com/disposable-email-domains/disposable-email-domains) list (CC0 1.0 public domain), bundled with the tool and updated when the tool is rebuilt. New throwaway services appear daily, so no list is complete. A domain whose MX points to Mailinator is also flagged.

**Is it legal to validate emails?**
Yes. The tool only reads public DNS records and compares addresses against lists; it sends nothing to the addresses and contacts no mailbox. You remain responsible for having a lawful basis (for example under GDPR or CAN-SPAM) to hold and email the addresses you check.

**How fast is it?**
In our tests 6,000 addresses across about 2,900 unique domains took under 30 seconds. Lists with many repeated domains (Gmail, Outlook) are faster because each domain is looked up only once.

### Related tools from Plot Point Technologies

- [Email & Contact Scraper](https://apify.com/plotpointtech/website-contact-finder): emails, phones and social links from company websites.
- [WHOIS & Domain Lookup](https://apify.com/plotpointtech/bulk-domain-lookup): registrar, expiry, DNS, email provider, SPF/DMARC and SSL for any domain list.
- [Local Business Leads Scraper](https://apify.com/plotpointtech/local-business-leads): local businesses with MX-checked emails and phones.
- [Website Tech Stack Detector](https://apify.com/plotpointtech/website-technology-detector): CMS, analytics and 290+ technologies per site.

Plot Point Technologies is not affiliated with Google, Microsoft, Yahoo, Mailinator or the maintainers of the disposable-email-domains list.

***

If this tool saved you time, we would be grateful for a short review on this page; it helps other people find it. If something did not work as expected, please open an issue on the **Issues** tab and we will look into it quickly.

# Actor input Schema

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

One email address per line. Entries like "Jane Doe <jane@example.com>" or "mailto:info@example.com" are cleaned automatically.

## `emailListUrls` (type: `array`):

Optional. Links to CSV, TXT or other text files (e.g. a Google Sheets 'publish to web' CSV link, a Dropbox/S3 file or an Apify key-value store record). Every email address found in each file is checked.

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

Look up each domain's MX records (cached per domain) to see whether it can receive email and which provider hosts it. Turn off for a syntax-, disposable-, role- and typo-only check.

## `checkTypos` (type: `boolean`):

Flag domains that look like misspellings of big mailbox providers or of .com/.net/.org (e.g. gmial.com -> gmail.com, acme.con -> acme.com) and suggest the corrected address.

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

Check each address only once (case-insensitive). You are charged per checked address, so keeping this on saves money.

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

Stop after this many addresses.

## Actor input object example

```json
{
  "emails": [
    "webmaster@python.org",
    "jane.doe@gmial.com",
    "test@mailinator.com",
    "john.smith@example.com",
    "sales@acme.con",
    "not-an-email@"
  ],
  "checkMx": true,
  "checkTypos": true,
  "deduplicate": true,
  "maxEmails": 1000000
}
```

# Actor output Schema

## `results` (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": [
        "webmaster@python.org",
        "jane.doe@gmial.com",
        "test@mailinator.com",
        "john.smith@example.com",
        "sales@acme.con",
        "not-an-email@"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("plotpointtech/bulk-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": [
        "webmaster@python.org",
        "jane.doe@gmial.com",
        "test@mailinator.com",
        "john.smith@example.com",
        "sales@acme.con",
        "not-an-email@",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("plotpointtech/bulk-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": [
    "webmaster@python.org",
    "jane.doe@gmial.com",
    "test@mailinator.com",
    "john.smith@example.com",
    "sales@acme.con",
    "not-an-email@"
  ]
}' |
apify call plotpointtech/bulk-email-validator --silent --output-dataset

```

## MCP server setup

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