# Bulk Email Address Validator — No Signup (`comall-agency/email-address-validator`) Actor

Clean an email list before a campaign or a CRM import: syntax, a live MX lookup, disposable-domain matching, role-account detection and typo suggestions such as gmial.com to gmail.com. No signup and no third-party API. No SMTP handshake, so mailbox existence is never claimed.

- **URL**: https://apify.com/comall-agency/email-address-validator.md
- **Developed by:** [Comall Agency](https://apify.com/comall-agency) (community)
- **Categories:** Lead generation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$6.00 / 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.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#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.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — 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

## Email Address Validator — Clean Lists, No Signup

Clean a list of email addresses before a campaign send, a CRM import or a
signup flow. One pass gives you syntax, a real DNS check on the domain,
disposable-address detection, role-account detection and a typo
suggestion.

**No signup, no third-party validation API, no key to go and create.**
Every signal is either pure computation or a direct DNS query against the
domain's own nameservers.

### What it checks, per address

- **Syntax** — the pragmatic subset of RFC 5322 that mainstream
  validators actually use in practice.
- **MX records** — a live DNS lookup on the domain. `has_mx: false` means
  the domain genuinely cannot receive mail, which is a far stronger
  signal than syntax alone.
- **Disposable domains** — matched against the community-maintained
  `disposable-email-domains` project, plus a handful of domains added by
  hand that the community list was missing.
- **Role accounts** — `info@`, `support@`, `sales@`, `noreply@` and
  similar. These are usually valid addresses that you still do not want
  in a marketing list.
- **Typo suggestion** — `gmial.com` → `gmail.com`, using edit distance
  against major providers, including French ones (`orange.fr`,
  `free.fr`, `laposte.net`, `wanadoo.fr`, `sfr.fr`). A suggestion is only
  offered when the domain is within a small edit distance, so genuinely
  different domains are left alone.

### The quality score

Every address gets a **`quality_score` from 0 to 100** and a
**`quality_grade`** of `good`, `risky` or `bad` — the single column you can
sort or filter a list on. `score_reasons` always spells out, in plain
English, every deduction that was applied, so any score can be checked by
hand.

| Situation | Score |
|---|---|
| Syntax is not a valid email | **0** (`bad`) |
| Domain has no MX record — cannot receive mail | **0** (`bad`) |
| Disposable / throwaway provider | **10** (`bad`) |
| Domain looks like a typo of a major provider | −35 |
| Role address (`info@`, `support@`…) | −25 |
| Free consumer mailbox (gmail.com, orange.fr…) | −5 |
| Nothing against it | **100** (`good`) |

Grades: **good** ≥ 70, **risky** 30–69, **bad** < 30. A row whose DNS lookup
failed on our side scores `null` and grades `unknown` — and is not charged.

**What this score is not.** It is not a probability that the mailbox exists,
and not a deliverability prediction. It is a transparent sum of the
deterministic signals listed above, nothing more. There is no model, no
external data and no reputation database behind it — which is exactly why
the same address always gets the same score.

### Duplicates are checked once and charged once

Send the same address twice — in any capitalisation — and you get two rows
back, in your original order, so the result still joins cleanly onto your
list. But the repeat carries `is_duplicate: true`, copies the first answer,
and **is not charged**. A list with 1,000 rows and 400 repeats is billed as
600 checks.

The run also writes a `SUMMARY` record to the key-value store: how many
addresses were submitted, how many were unique, how many duplicates were
skipped, how many domains were resolved, and the counts per grade and per
verdict.

### Use cases

- **Before a campaign send** — bounce rates hurt sender reputation for
  weeks. Removing dead domains and typos first is cheaper than repairing
  deliverability afterwards.
- **CRM and list imports** — stop junk entering the database instead of
  cleaning it later.
- **Lead qualification** — flag disposable and role addresses before they
  reach a sales rep's queue.
- **Signup forms** — catch a mistyped provider domain at the point of
  entry, not after a welcome email silently bounces.

### Input

```json
{ "emails": ["jane.doe@apify.com", "contact@apify.com", "test@gmial.com",
             "info@mailinator.com", "not-an-email", "JANE.DOE@apify.com"] }
```

### Output (one row per address)

```json
{
  "email": "test@gmial.com",
  "normalized_email": "test@gmial.com",
  "valid_syntax": true,
  "domain": "gmial.com",
  "has_mx": false,
  "mx_hosts": [],
  "is_disposable": false,
  "is_role_account": false,
  "is_free_provider": false,
  "suggested_correction": "gmail.com",
  "quality_score": 0,
  "quality_grade": "bad",
  "score_reasons": ["domain has no MX record - it cannot receive mail"],
  "is_duplicate": false,
  "verdict": "no_mail_server",
  "checked_at": "2026-08-28T17:00:00.000Z"
}
```

`verdict` is one of `valid`, `invalid_syntax`, `no_mail_server`,
`disposable` or `role_account`.

### Pricing, and when you are not charged

Pay-per-event: **$0.006 per unique email checked**, charged once a
completed answer is produced. Repeated addresses in the same run are not
charged again. An address that turns out to be invalid, disposable
or role-based is still a real answer to the question you asked, so it is
charged.

**You are not charged when our own DNS resolver fails** (a timeout or
network error on our side, as opposed to a domain that genuinely has no
mail server). That row comes back with `verdict: "error"` and no charge.

### Limitations — read this before you buy

- **No SMTP handshake.** This does not connect to the mail server to ask
  whether the individual mailbox exists. It confirms the domain can
  receive mail, not that `john@` is a real person there. Anyone promising
  per-mailbox certainty without an SMTP probe is overselling.
- **A disposable-domain list always trails reality.** New throwaway
  providers appear constantly and some rotate domains deliberately. A
  `false` on `is_disposable` means "not on the list", not "proven
  permanent".
- **Catch-all domains** accept everything, so a valid MX record tells you
  nothing about the individual address.
- No deliverability score, no reputation data, no spam-trap detection.

### FAQ

**Does a score of 100 mean the mailbox exists?**
No. It means nothing deterministic counts against the address. Confirming
a mailbox exists requires an SMTP handshake, which this Actor does not do
— see the limitations above.

**Why is a real address flagged `role_account`?**
Because it starts with a role prefix such as `info` or `support`. It is
almost certainly deliverable — the flag is about list quality, not
validity.

**Why does a valid-looking domain come back `no_mail_server`?**
The domain resolves but publishes no MX record, so it cannot receive
mail. That is usually a parked domain or a typo close to a real one —
check `suggested_correction`.

### Related Actors

Part of the same family of small, single-purpose checkers on this account —
each does one thing, priced per item checked:

- [IBAN Validator & Formatter](https://apify.com/comall-agency/iban-validator-formatter) — ISO 13616 length + mod-97 checksum, fully offline.
- [Card Number Validator (Luhn)](https://apify.com/comall-agency/card-number-validator) — Luhn checksum and card-network detection, output is masked.
- [Barcode Check-Digit Validator](https://apify.com/comall-agency/barcode-checkdigit-validator) — EAN-13, EAN-8 and UPC-A check digits.
- [EU VAT Number Checker](https://apify.com/comall-agency/eu-vat-checker) — official VIES lookup.
- [Password Strength Checker](https://apify.com/comall-agency/password-strength-checker) — entropy scoring, never returns the password.
- [Cron Expression Validator](https://apify.com/comall-agency/cron-expression-tool) — plain-English description and next run times.
- [French E-Invoice Partner Resolver](https://apify.com/comall-agency/fr-einvoice-partner-resolver) — SIRET / SIREN / VAT resolution.

# Actor input Schema

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

List of email addresses to check. Each unique address is checked once: syntax, MX record on the domain, disposable-domain match, role-account pattern and typo suggestion, then scored 0-100 and graded good/risky/bad. Repeated addresses are returned with the same answer but are not re-checked and not charged.

## Actor input object example

```json
{
  "emails": [
    "jane.doe@apify.com",
    "contact@apify.com",
    "test@gmial.com",
    "info@mailinator.com",
    "not-an-email",
    "JANE.DOE@apify.com"
  ]
}
```

# 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": [
        "jane.doe@apify.com",
        "contact@apify.com",
        "test@gmial.com",
        "info@mailinator.com",
        "not-an-email",
        "JANE.DOE@apify.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("comall-agency/email-address-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": [
        "jane.doe@apify.com",
        "contact@apify.com",
        "test@gmial.com",
        "info@mailinator.com",
        "not-an-email",
        "JANE.DOE@apify.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("comall-agency/email-address-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": [
    "jane.doe@apify.com",
    "contact@apify.com",
    "test@gmial.com",
    "info@mailinator.com",
    "not-an-email",
    "JANE.DOE@apify.com"
  ]
}' |
apify call comall-agency/email-address-validator --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,comall-agency/email-address-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/JBVVfdlxkJGKO0n12/builds/k1U9VWAffdcUiD3o7/openapi.json
