# Email Verifier Batch - Syntax MX SMTP Disposable Detection (`seibs.co/email-verifier-batch`) Actor

Bulk email verifier: RFC 5322 syntax, MX lookup, 5400+ disposable-domain blocklist, role-based (info@/sales@) detection, optional SMTP HELO+RCPT probe (never sends mail), and a 0-1 confidence score. For lead-list cleanup and email-campaign hygiene.

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

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-usage

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.md):

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

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.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/platform/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

## Email Verifier Batch

Bulk email-address verifier. RFC 5322 syntax + MX lookup + 5400+ disposable-domain blocklist + role-based detection + optional SMTP HELO/RCPT probe + 0-1 confidence score. No paid databases, no third-party verifier APIs - just DNS and SMTP.

### What does Email Verifier Batch do?

Feed it a list of email addresses. For each one, the actor runs up to five checks and emits a single record with the verdict:

1. **Syntax check** - RFC 5322 compliant validation via `email-validator`.
2. **MX lookup** - asks DNS whether the domain accepts mail. Falls back to the A record (implicit MX per RFC 5321 5.1) when no MX exists.
3. **Disposable detection** - matches the domain against a bundled blocklist of 5400+ known throwaway-email providers (mailinator, guerrillamail, 10minutemail, tempmail, and ~5400 more).
4. **Role-based detection** - flags `info@`, `sales@`, `support@`, etc. so SDRs can skip group inboxes.
5. **SMTP probe (optional)** - connects to the MX host on port 25 and issues `HELO` + `MAIL FROM` + `RCPT TO`. The `DATA` stage is never reached, so no email is ever sent. Tests an additional random-mailbox `RCPT TO` to detect catch-all domains. Returns `deliverable` / `undeliverable` / `catch-all` / `unknown`.

The five signals are combined into a `confidence_score` from 0.0 to 1.0. Disposable domains are capped at 0.30; SMTP-undeliverable addresses floor at 0.05.

### Features

- Five independent checks per address - failures in one check never block the others.
- 5400+ bundled disposable-domain blocklist (sourced from the canonical `disposable-email-domains` GitHub project).
- ~45 bundled role prefixes (info, sales, support, billing, hr, recruiting, no-reply, postmaster, ...).
- SMTP probe never sends mail - `RCPT TO` only, then `QUIT`.
- Catch-all detection - a second `RCPT TO` to a random local-part flags domains that accept everything.
- Greylisting awareness - 4xx responses set `greylisted=true` and `retry_recommended=true`.
- Per-email timeout - one slow MX never holds up the batch.
- Concurrency-controlled (1-50 parallel) via asyncio + semaphore.
- Errors are emitted as records, not run failures - you always get a row per input address.

### Use cases

- **B2B sales prospecting** - clean a list of scraped LinkedIn-derived emails before importing to your sequencer.
- **Lead-list cleanup** - score a CSV from an outbound vendor; drop disposable + role-based + undeliverable before paying per-contact for upload.
- **Email-campaign hygiene** - run before every send; bounces above 2% wreck deliverability and sender reputation.
- **Anti-bounce filtering** - filter signups by `confidence_score >= 0.6` to keep your transactional senders out of penalty boxes.
- **Form-spam reduction** - reject signups where `is_disposable=true` at submit time.
- **CRM enrichment** - pass every contact in your CRM through this monthly to flag departed-employee inboxes (catch-all + role + 4xx greylist patterns).

### Input

| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
| `emails` | array of strings | yes | - | List of addresses. Case-insensitive dedupe. |
| `do_smtp_probe` | boolean | no | `true` | When false, only syntax/MX/disposable/role checks run. ~50x faster. |
| `concurrency` | integer | no | `10` | 1-50 parallel verifications. |
| `timeout_seconds` | integer | no | `10` | Per-address ceiling for DNS + SMTP. |

### Output

One record per input email. Key fields:

- `email`, `normalized_email`, `local_part`, `domain`
- `syntax_valid` (bool)
- `mx_records` (array of `{host, priority}`)
- `has_mx` (bool)
- `is_disposable` (bool)
- `is_role_based` (bool), `role_type` (matched prefix or null)
- `smtp_probe_result` - `deliverable` / `undeliverable` / `catch-all` / `unknown` / null
- `smtp_response` (raw SMTP code + message, for audit)
- `smtp_catch_all_tested`, `greylisted`, `retry_recommended`
- `confidence_score` (0-1)
- `verification_method` (array of checks that ran)
- `warnings`, `error`, `checked_at`

Two dataset views are provided: **Overview** (compact verdict table) and **Detailed** (every field).

### Pricing (pay per event)

- `verification_basic` - **$0.0005** per email (syntax + MX + disposable + role + confidence score). Always charged.
- `verification_smtp` - **$0.001** per email when the SMTP probe actually completes. Skipped automatically when SMTP probing is disabled or the domain has no MX.

A 10K-list scan with SMTP enabled costs ~$15. The same scan against ZoomInfo or Hunter would run $100-300 depending on plan.

### How the confidence score is computed

| Condition | Effect |
|---|---|
| Syntax invalid | score = 0.0 |
| No MX (and no fallback A) | score = 0.05 |
| SMTP undeliverable | score = 0.05 |
| Syntax + MX present, no SMTP probe | base = 0.55 |
| SMTP deliverable | base = 0.95 |
| SMTP catch-all | base = 0.55 (mailbox cannot be proven) |
| SMTP unknown (greylist / temp error) | base = 0.45 |
| Role-based local-part | -0.10 |
| Disposable domain | capped at 0.30 |

### FAQ

**Q: Does this send email?**
A: No. The SMTP probe stops at `RCPT TO` and immediately sends `QUIT`. The `DATA` stage - the only stage that actually transmits a message body - is never reached. This is the same technique every reputable email-verifier (Hunter, ZeroBounce, NeverBounce) uses.

**Q: Why are some big-provider results `unknown` or `catch-all`?**
A: Gmail, Outlook, and many large providers refuse `RCPT TO` probes outright (they return a generic 250 for any address, which we report as `catch-all`) or rate-limit aggressively from datacenter IPs. For those, the syntax + MX + disposable + role signals are usually all you need; `confidence_score` accounts for this.

**Q: What about greylisting?**
A: A 4xx response on `RCPT TO` sets `greylisted=true` and `retry_recommended=true`. Re-run the same input 5-15 minutes later and the MX will typically accept on the second attempt.

**Q: Can I bring my own disposable-domain list?**
A: Not via input today - the bundled list is rebuilt at build time from the `disposable-email-domains` GitHub project. Open an issue or fork the actor if you need to layer in a custom list.

**Q: Will this trip rate-limits or get my Apify IP blocked?**
A: SMTP `RCPT TO` is the universal verification primitive - it does not download mail, does not authenticate, and does not transmit a body. Keep `concurrency` at 10 or below for shared MX hosts (Gmail / Outlook / Yahoo) and you will be fine. The actor never reuses an SMTP session across addresses.

**Q: How does this compare to ZoomInfo / Hunter / ZeroBounce?**
A: For the verification step specifically, the methodology is the same (syntax + MX + SMTP + disposable + role). What those vendors add is a contact database. This actor is the verification half - perfect for cleaning a list you already have.

**Q: Can I schedule this?**
A: Yes. Pair with Apify Schedules + a webhook to your CRM and re-verify your active contact list every 30-90 days to catch employee turnover.

### Limitations

- SMTP probes against Gmail / Outlook / Yahoo will frequently land as `catch-all` or `unknown` - those providers refuse to disclose mailbox existence.
- IPv6-only MX hosts work but the SMTP probe falls back to whichever address family the OS resolver returns first.
- The actor does not perform deep SPF / DKIM / DMARC analysis - it answers "is this mailbox real" not "is this domain configured well to send mail".
- Catch-all domains return `confidence_score = 0.55` by design - the mailbox literally cannot be proven without sending an actual message.

### Data sources

- Disposable-domain list: `disposable-email-domains/disposable-email-domains` (GitHub, Creative Commons).
- Role-prefix list: curated from RFC 2142 + common industry conventions.
- DNS: any public resolver via `dnspython`.
- SMTP: direct port-25 connection to the target's MX host.

# Actor input Schema

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

List of email addresses to verify. Duplicates (case-insensitive) are deduped before processing. Bring as many as you want; concurrency is controlled below.
## `do_smtp_probe` (type: `boolean`):

When enabled, the actor connects to MX:25 and issues HELO + MAIL FROM + RCPT TO. The DATA stage is NEVER reached - no mail is sent. Slower (~1-5s per address) but the only way to tell 'deliverable' from 'mailbox unknown'. Disable for fast syntax/MX-only scans.
## `concurrency` (type: `integer`):

How many emails to verify in parallel. Higher = faster but increases risk of upstream MX hosts rate-limiting your probes. 1 to 50. Default 10.
## `timeout_seconds` (type: `integer`):

Hard ceiling on DNS + SMTP work for a single address. Records that exceed this still emit (with smtp_probe_result='unknown' and a warning). 3 to 60. Default 10.

## Actor input object example

```json
{
  "emails": [
    "founder@stripe.com",
    "info@openai.com",
    "totallyfakeperson12345@gmail.com",
    "test@mailinator.com"
  ],
  "do_smtp_probe": true,
  "concurrency": 10,
  "timeout_seconds": 10
}
````

# 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": [
        "founder@stripe.com",
        "info@openai.com",
        "totallyfakeperson12345@gmail.com",
        "test@mailinator.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("seibs.co/email-verifier-batch").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": [
        "founder@stripe.com",
        "info@openai.com",
        "totallyfakeperson12345@gmail.com",
        "test@mailinator.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("seibs.co/email-verifier-batch").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 '{
  "emails": [
    "founder@stripe.com",
    "info@openai.com",
    "totallyfakeperson12345@gmail.com",
    "test@mailinator.com"
  ]
}' |
apify call seibs.co/email-verifier-batch --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Email Verifier Batch - Syntax MX SMTP Disposable Detection",
        "description": "Bulk email verifier: RFC 5322 syntax, MX lookup, 5400+ disposable-domain blocklist, role-based (info@/sales@) detection, optional SMTP HELO+RCPT probe (never sends mail), and a 0-1 confidence score. For lead-list cleanup and email-campaign hygiene.",
        "version": "0.1",
        "x-build-id": "kFe8qbl5A8wfEzGmO"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/seibs.co~email-verifier-batch/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-seibs.co-email-verifier-batch",
                "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/seibs.co~email-verifier-batch/runs": {
            "post": {
                "operationId": "runs-sync-seibs.co-email-verifier-batch",
                "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/seibs.co~email-verifier-batch/run-sync": {
            "post": {
                "operationId": "run-sync-seibs.co-email-verifier-batch",
                "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",
                "required": [
                    "emails"
                ],
                "properties": {
                    "emails": {
                        "title": "Email addresses",
                        "type": "array",
                        "description": "List of email addresses to verify. Duplicates (case-insensitive) are deduped before processing. Bring as many as you want; concurrency is controlled below.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "do_smtp_probe": {
                        "title": "Run SMTP probe",
                        "type": "boolean",
                        "description": "When enabled, the actor connects to MX:25 and issues HELO + MAIL FROM + RCPT TO. The DATA stage is NEVER reached - no mail is sent. Slower (~1-5s per address) but the only way to tell 'deliverable' from 'mailbox unknown'. Disable for fast syntax/MX-only scans.",
                        "default": true
                    },
                    "concurrency": {
                        "title": "Concurrent verifications",
                        "minimum": 1,
                        "maximum": 50,
                        "type": "integer",
                        "description": "How many emails to verify in parallel. Higher = faster but increases risk of upstream MX hosts rate-limiting your probes. 1 to 50. Default 10.",
                        "default": 10
                    },
                    "timeout_seconds": {
                        "title": "Per-verification timeout (seconds)",
                        "minimum": 3,
                        "maximum": 60,
                        "type": "integer",
                        "description": "Hard ceiling on DNS + SMTP work for a single address. Records that exceed this still emit (with smtp_probe_result='unknown' and a warning). 3 to 60. Default 10.",
                        "default": 10
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
