# Email Verifier - Bulk Validation, MX & Disposable Check (`parseforge/email-verifier-scraper`) Actor

Verify email lists in bulk without SMTP: RFC syntax, MX and DNS, null MX, disposable and free providers, role accounts, typo fixes, SPF/DMARC and a clear verdict. Export CSV, Excel, JSON or XML.

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

## Pricing

from $1.28 / 1,000 result items

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

![ParseForge Banner](https://raw.githubusercontent.com/ParseForge/apify-assets/main/banner-v4.webp)

## ✉️ Email Verifier Scraper

> 🚀 **Export verified email lists in seconds.** Every address gets a verdict (valid domain, risky or invalid), a plain-English reason, a 0-100 score and 25 columns of evidence: syntax, MX records, mail provider, SPF, DMARC, disposable, free provider, role account, parked domain and a "did you mean" typo fix.

Paste addresses or link a CSV, and the Actor checks each one against the rules mail servers actually apply: RFC 5321/5322 syntax, whether the domain exists, whether it publishes MX records (or a null MX that refuses all mail), and whether it falls back to A/AAAA records. It then compares the domain with maintained open lists of 8,971 disposable domains, 14,176 free-provider domains, 1,018 role names and the 1,438 top-level domains in the IANA root zone, all refreshed every time the Actor is built.

DNS answers are cached per domain, so a list with 50,000 Gmail addresses costs one set of Gmail lookups. On our 58-address test set (big providers, company domains, disposable services, typos, dead domains and malformed strings) every verdict matched the expected answer.

| 🎯 Target Audience | 💡 Primary Use Cases |
|---|---|
| Growth and sales teams, email marketers, CRM admins, SaaS sign-up flows, data vendors, agencies | Clean a list before a campaign, block disposable sign-ups, fix typos at import, split B2B from free addresses, keep CRM data tidy |

### 📋 What the Email Verifier Scraper does

- ✅ **Syntax check (RFC-aware).** Dot-atom and quoted local parts, 64/254 length limits, IDN domains converted to punycode, IP-literal and malformed domains rejected with the exact issue.
- 🧹 **Clean-up first.** `Name <user@domain.com>`, `mailto:` links, stray quotes and trailing punctuation are stripped; the domain is lower-cased into `normalizedEmail`.
- 📮 **MX and DNS.** Domain existence (NXDOMAIN), MX records with priorities, null MX (RFC 7505), A/AAAA fallback, SPF and DMARC.
- 🏢 **Mail provider.** Google, Microsoft 365, Outlook.com, Yahoo, iCloud, Zoho, Proton, security gateways like Proofpoint and Mimecast, forwarding services and more, read from the MX hosts.
- 🗑 **Disposable, free and role accounts.** Flags temporary inboxes, consumer providers and shared inboxes like info@ or sales@.
- ✏️ **Typo fixes.** `gmial.com` becomes `gmail.com`, `company.cmo` becomes `company.com`.
- 🅿️ **Parked domains.** Name servers or MX hosts that belong to parking and domain-sale services.
- 🚦 **Verdict, reason and score.** One of `valid-format-deliverable-domain`, `risky`, `invalid` or `unknown`, with the reason spelled out.

> 💡 **Why it matters:** a bounce rate above a few percent hurts sender reputation for every email you send afterwards. Most bad addresses in real lists are typos, dead domains, disposable inboxes and role accounts, and all of those are caught here without sending a single message.

> ⚠️ **What it does not do:** this Actor does **not** connect to mail servers over SMTP, so it cannot tell whether a specific mailbox exists on a valid domain, and it cannot detect catch-all domains. A `valid-format-deliverable-domain` verdict means the address is well formed and its domain is set up to receive mail.

### 🎬 Full Demo (🚧 Coming soon)

### 📊 Output

| Field | Description |
|---|---|
| 📧 email | The value exactly as you provided it |
| ✉️ normalizedEmail | Cleaned address, domain lower-cased and in ASCII |
| 🚦 verdict | valid-format-deliverable-domain, risky, invalid or unknown |
| 💬 reason | Plain-English explanation of the verdict |
| ⭐ qualityScore | 0 (undeliverable) to 99 (clean address on a well configured domain) |
| ✅ syntaxValid | Yes / No |
| 🧩 syntaxIssue | The exact syntax problem, or N/A |
| 👤 localPart | The part before the @ |
| 🌐 domain | The part after the @ |
| 🏠 domainExists | Yes, No (NXDOMAIN) or Unknown |
| 📮 hasMx | Whether the domain publishes MX records |
| 📋 mxRecords | Every MX record as "priority host" |
| 🥇 primaryMx | The lowest-priority MX host |
| 🏢 mailProvider | Mail provider recognised from the MX hosts |
| 🏷 mailProviderType | Mailbox provider, Security gateway, Forwarding service, Email API service, Other or None |
| 🔁 aRecordFallback | When there is no MX: whether an A/AAAA record can still receive mail |
| 🛡 hasSpf | SPF record present |
| 🔐 hasDmarc | DMARC record present |
| 🗑 disposable | Temporary / throwaway email domain |
| 🆓 freeProvider | Consumer email provider (Gmail, Outlook.com, Yahoo...) |
| 👥 roleAccount | Shared role inbox (info@, sales@, support@...) |
| ✏️ typoSuggestion | Corrected address when the domain looks misspelled |
| 🅿️ parkedDomain | Domain served by a parking or domain-sale service |
| 🕒 scrapedAt | When the check ran |
| ❌ error | null on success |

Three real rows from the prefilled example:

```json
[
  {
    "email": "first.last@stripe.com",
    "normalizedEmail": "first.last@stripe.com",
    "verdict": "valid-format-deliverable-domain",
    "reason": "Valid syntax, domain accepts mail (MX found). Mailbox existence not tested (no SMTP)",
    "qualityScore": 95,
    "syntaxValid": "Yes",
    "syntaxIssue": "N/A",
    "localPart": "first.last",
    "domain": "stripe.com",
    "domainExists": "Yes",
    "hasMx": "Yes",
    "mxRecords": [
      "10 aspmx.l.google.com",
      "20 alt1.aspmx.l.google.com",
      "20 alt2.aspmx.l.google.com",
      "30 aspmx2.googlemail.com",
      "30 aspmx3.googlemail.com"
    ],
    "primaryMx": "aspmx.l.google.com",
    "mailProvider": "Google (Gmail / Workspace)",
    "mailProviderType": "Mailbox provider",
    "aRecordFallback": "N/A",
    "hasSpf": "Yes",
    "hasDmarc": "Yes",
    "disposable": "No",
    "freeProvider": "No",
    "roleAccount": "No",
    "typoSuggestion": "N/A",
    "parkedDomain": "No",
    "scrapedAt": "2026-09-25T01:52:06.916Z",
    "error": null
  },
  {
    "email": "your.name@gmial.com",
    "normalizedEmail": "your.name@gmial.com",
    "verdict": "risky",
    "reason": "Disposable / temporary email domain; Possible typo, did you mean gmail.com?; No MX record; delivery relies on the A/AAAA fallback",
    "qualityScore": 1,
    "syntaxValid": "Yes",
    "syntaxIssue": "N/A",
    "localPart": "your.name",
    "domain": "gmial.com",
    "domainExists": "Yes",
    "hasMx": "No",
    "mxRecords": [],
    "primaryMx": "N/A",
    "mailProvider": "None",
    "mailProviderType": "None",
    "aRecordFallback": "Yes",
    "hasSpf": "No",
    "hasDmarc": "No",
    "disposable": "Yes",
    "freeProvider": "No",
    "roleAccount": "No",
    "typoSuggestion": "your.name@gmail.com",
    "parkedDomain": "No",
    "scrapedAt": "2026-09-25T01:52:06.987Z",
    "error": null
  },
  {
    "email": "user@example.com",
    "normalizedEmail": "user@example.com",
    "verdict": "invalid",
    "reason": "Domain publishes a null MX (RFC 7505): it accepts no email",
    "qualityScore": 0,
    "syntaxValid": "Yes",
    "syntaxIssue": "N/A",
    "localPart": "user",
    "domain": "example.com",
    "domainExists": "Yes",
    "hasMx": "No",
    "mxRecords": [],
    "primaryMx": "N/A",
    "mailProvider": "None",
    "mailProviderType": "None",
    "aRecordFallback": "No",
    "hasSpf": "Yes",
    "hasDmarc": "Yes",
    "disposable": "No",
    "freeProvider": "No",
    "roleAccount": "Yes",
    "typoSuggestion": "N/A",
    "parkedDomain": "No",
    "scrapedAt": "2026-09-25T01:52:06.916Z",
    "error": null
  }
]
```

### ✨ Why choose this Actor

- 🧾 **A reason for every verdict.** No black-box score: each row says exactly why it is risky or invalid.
- 🔎 **Evidence you can audit.** The MX records, provider, SPF and DMARC come back with the verdict, so you can build your own rules on top.
- 🧠 **Catches what regex misses.** Null MX domains like example.com, non-existent TLDs like .con, and typo domains that are live but owned by someone else.
- 🔄 **Fresh lists.** Disposable, free-provider, role and TLD lists are pulled from their maintained open sources at every build.
- ⚡ **Fast and cheap to run.** DNS only, cached per domain, with no proxies and no browser.
- 🎛 **Your rules.** Choose whether role accounts or free providers count as risky.

### 📈 How it compares to alternatives

| | This Actor | Regex-only validators | SMTP verifiers |
|---|---|---|---|
| Syntax per RFC 5321/5322 | ✅ | Partial | ✅ |
| Domain exists, MX, null MX, A fallback | ✅ | ❌ | ✅ |
| Disposable, free, role, parked flags | ✅ | ❌ | Varies |
| Typo suggestions | ✅ | ❌ | Varies |
| SPF / DMARC and mail provider | ✅ | ❌ | Rarely |
| Mailbox exists / catch-all | ❌ (no SMTP) | ❌ | ✅ when the server answers honestly |
| Sends traffic to the recipient's mail server | Never | Never | Yes |

SMTP verifiers can confirm a mailbox, but many providers (Yahoo, Microsoft 365 behind gateways, catch-all domains) answer "accepted" for anything, and probing from shared cloud IPs gets blocked. This Actor focuses on the checks that are always reliable.

### 🚀 How to use

1. Create a free Apify account with $5 credit: [sign up here](https://console.apify.com/sign-up?fpr=vmoqkp).
2. Open the Email Verifier Scraper and paste your addresses into **Email addresses**, or add a CSV/TXT link under **Bulk import**.
3. Set **Max Items** to the number of addresses you want checked.
4. Optionally switch the verification rules (role accounts, free providers, SPF/DMARC, duplicates).
5. Click **Start** and download the results as CSV, Excel, JSON or XML.

Example run settings:

```
{ "emails": ["support@github.com", "your.name@gmial.com", "user@example.com"], "maxItems": 100, "freeProvidersAreRisky": true }
```

### 💼 Business use cases

#### 📣 Email marketing

Clean a list before a campaign: drop invalid and disposable addresses, fix typos, and keep your bounce rate and sender reputation healthy.

#### 🧲 Lead generation and sales

Score scraped or purchased leads, separate company domains from free providers with `freeProvider`, and see which prospects run Microsoft 365, Google Workspace or a security gateway.

#### 🛡 Sign-up and fraud prevention

Screen new accounts for throwaway inboxes, parked domains and misspelled addresses before they reach your database.

#### 🗂 CRM and data hygiene

Run the whole CRM export once a quarter, suggest corrections for typos, and flag role inboxes that should not be treated as a person.

### 🔌 Automating Email Verifier Scraper

- **Make / Zapier / n8n:** verify each new form submission or CRM contact the moment it arrives.
- **Slack:** post a summary of invalid and risky addresses after each run.
- **Google Drive / Sheets:** link a published sheet as a list file and export the results back.
- **Airbyte:** load verification results into your warehouse.
- **GitHub Actions:** schedule a nightly check of your newsletter list.
- **API:** call the Actor from any backend with the Apify API and read the dataset.

### 🌟 Beyond business use cases

- **Research:** measure how many addresses in a public dataset point at dead or disposable domains.
- **Personal:** tidy your own contact list or wedding guest list before a mail-out.
- **Non-profit:** keep donor and volunteer lists deliverable on a tight budget.
- **Experimentation:** study how organisations configure MX, SPF and DMARC.

### 🤖 Ask an AI assistant about this scraper

Ask ChatGPT, Claude or Perplexity: "How do I verify an email list with the ParseForge Email Verifier Scraper on Apify and filter out risky addresses?" and link them to this page for the field list above.

### ❓ Frequently Asked Questions

#### 📬 Does it check whether the mailbox really exists?

No. That needs an SMTP connection to the recipient's mail server, which this Actor never makes. It verifies everything up to the mailbox: syntax, domain, MX, provider and risk flags.

#### 🎯 Can it detect catch-all domains?

No. Catch-all detection needs an SMTP probe with a random address, so there is no catch-all column rather than a guess.

#### 🚦 What does valid-format-deliverable-domain mean?

The address is well formed and its domain exists and publishes MX records, so mail can be delivered to that domain. Whether the specific inbox exists is not tested.

#### ⚠️ Why is my address marked risky?

The `reason` column lists every cause: disposable domain, possible typo, parked domain, no MX (A record fallback only), unusual local part, role account, or free provider if you turned that rule on.

#### 🧭 What does unknown mean?

The domain's DNS servers did not answer in time, even after retrying through public resolvers. Run those rows again later.

#### 🧪 Why is user@example.com invalid when the domain exists?

example.com publishes a null MX record (RFC 7505), which is the official way to say "this domain accepts no email".

#### ✏️ How are typos detected?

The domain is compared with popular consumer mail domains using edit distance, with tight limits so real company domains are not "corrected". Top-level domains that do not exist, like .con or .cmo, get the closest common one.

#### 👥 Are role accounts bad?

Not always. They are real inboxes but shared, often filtered, and a poor fit for personal outreach. They count as risky by default; switch the rule off to treat them as valid.

#### 📥 Can I upload a CSV?

Yes. Put a public link to a CSV, TXT or JSON file under **Bulk import**. Every email address in the file is picked up, whatever column it sits in.

#### 🔁 Are duplicates removed?

Yes by default, comparing the cleaned-up, lower-cased address. Switch it off to get one row per input line.

#### 🌍 Does it support international addresses?

Yes. Internationalized domain names are converted to punycode and checked normally. Addresses with non-ASCII characters before the @ are valid but marked risky because both mail servers must support SMTPUTF8.

#### 🛰 Do I need a proxy?

No. The Actor only makes DNS queries, never web requests to the domains it checks, so no proxy is used.

### 🔌 Integrate with any app

Use the Apify API, the JavaScript and Python clients, webhooks, or the Make, Zapier and n8n integrations to send verification results wherever you work.

### 🔗 Recommended Actors

- [Contact Info Scraper](https://apify.com/parseforge/contact-info-scraper)
- [Website Contact & Leads Scraper](https://apify.com/parseforge/website-contact-leads-scraper)
- [Google Maps Contacts Scraper](https://apify.com/parseforge/google-maps-contacts-scraper)
- [YouTube Channel Email Scraper](https://apify.com/parseforge/youtube-channel-email-scraper)
- [Disposable Email Domains Scraper](https://apify.com/parseforge/disposable-email-domains-scraper)

> 💡 **Pro Tip:** browse the complete [ParseForge collection](https://apify.com/parseforge).

**🆘 Need Help?** [Open our contact form](https://tally.so/r/BzdKgA)

**Credits:** the free-provider list comes from [free-email-domains](https://github.com/Kikobeats/free-email-domains) (MIT, © Kiko Beats), the role-account list from [role-based-email-addresses](https://github.com/mixmaxhq/role-based-email-addresses) (MIT, © Mixmax, Inc) and the disposable list from [disposable-email-domains](https://github.com/disposable-email-domains/disposable-email-domains) (CC0, public domain). Full notices are in [THIRD\_PARTY\_NOTICES.md](THIRD_PARTY_NOTICES.md).

> **⚠️ Disclaimer:** this is an independent tool, not affiliated with any email provider or with the maintainers of the open lists it uses. It checks only publicly available DNS data and never contacts a mailbox.

# Actor input Schema

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

Email addresses to verify, one per line. Messy values are cleaned up first: "Name <user@domain.com>", "mailto:" links, quotes and trailing punctuation are handled.

## `maxItems` (type: `integer`):

Free users: Limited to 10 items (preview). Paid users: Optional, max 1,000,000

## `emailFiles` (type: `array`):

Public links to CSV, TXT or JSON files (for example a Google Sheets "publish to web" CSV link). Every email address found anywhere in the file is verified, added after the addresses above.

## `roleAccountsAreRisky` (type: `boolean`):

Role accounts (info@, sales@, support@, admin@...) are shared inboxes, not a person. On: they get the risky verdict. Off: they can be valid and are only flagged in the roleAccount column.

## `freeProvidersAreRisky` (type: `boolean`):

Switch on for B2B lists where a Gmail, Outlook.com or Yahoo address is not a business contact.

## `checkMailAuth` (type: `boolean`):

Look up the domain's SPF and DMARC records (two extra DNS queries per unique domain). A domain with neither is a weaker mail domain and gets a lower quality score.

## `removeDuplicates` (type: `boolean`):

Verify each address once, comparing the cleaned-up, lower-cased address.

## Actor input object example

```json
{
  "emails": [
    "support@github.com",
    "first.last@stripe.com",
    "someone@mailinator.com",
    "your.name@gmial.com",
    "user@example.com",
    "hello@this-domain-does-not-exist-7731.com",
    "not-an-email",
    "sales@salesforce.com",
    "first.last@nasa.gov",
    "user@gmail.con"
  ],
  "maxItems": 10,
  "roleAccountsAreRisky": true,
  "freeProvidersAreRisky": false,
  "checkMailAuth": true,
  "removeDuplicates": true
}
```

# Actor output Schema

## `overview` (type: `string`):

Key fields

## `fullData` (type: `string`):

Complete dataset with all 25 fields

# 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": [
        "support@github.com",
        "first.last@stripe.com",
        "someone@mailinator.com",
        "your.name@gmial.com",
        "user@example.com",
        "hello@this-domain-does-not-exist-7731.com",
        "not-an-email",
        "sales@salesforce.com",
        "first.last@nasa.gov",
        "user@gmail.con"
    ],
    "maxItems": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("parseforge/email-verifier-scraper").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": [
        "support@github.com",
        "first.last@stripe.com",
        "someone@mailinator.com",
        "your.name@gmial.com",
        "user@example.com",
        "hello@this-domain-does-not-exist-7731.com",
        "not-an-email",
        "sales@salesforce.com",
        "first.last@nasa.gov",
        "user@gmail.con",
    ],
    "maxItems": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("parseforge/email-verifier-scraper").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": [
    "support@github.com",
    "first.last@stripe.com",
    "someone@mailinator.com",
    "your.name@gmial.com",
    "user@example.com",
    "hello@this-domain-does-not-exist-7731.com",
    "not-an-email",
    "sales@salesforce.com",
    "first.last@nasa.gov",
    "user@gmail.con"
  ],
  "maxItems": 10
}' |
apify call parseforge/email-verifier-scraper --silent --output-dataset

```

## MCP server setup

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

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/kWpYoaF40LYaqxHnP/builds/tJWdQDUzFH8QfQ4ja/openapi.json
