# Email Verification API - Verify, Find and Reverse Lookup (`nabeelbaghoor/email-verification-finder-api`) Actor

Verify email addresses with SMTP checks, a safe-to-send verdict and a reason code, find the address behind a person at a company, and reverse-look-up the person or company behind an address, a domain or a profile URL. Flags catch-all, disposable, free, role and gibberish. Pay per result.

- **URL**: https://apify.com/nabeelbaghoor/email-verification-finder-api.md
- **Developed by:** [Nabeel Hassan](https://apify.com/nabeelbaghoor) (community)
- **Categories:** Business, Developer tools, Lead generation
- **Stats:** 2 total users, 1 monthly users, 83.3% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$12.00 / 1,000 results

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 Verification API - Verify, Find and Reverse Lookup

Clean a list, find the addresses missing from it, and work backwards from an address to the person behind it. Fifteen modes over one API token, one flat row per input.

### What this actor does

- **Verifies with a reason, not just a verdict.** Every address comes back as valid, invalid, catch-all or unknown, with a safe-to-send rating on top and a numeric reason code underneath. The code is where the decisions live: 407 is a greylisting server that will verify perfectly on a retry, 406 is a mailbox that does not exist. Both are offered as filters, and every row carries the reason spelled out next to the code so a dataset is readable without a lookup table.
- **Finds the address behind a person at a company.** Give it a name and a company and it returns the address with a confidence score, the business or consumer flag, and every runner-up candidate it considered. Paste one company and a list of names to run a whole account in a single pass.
- **Recovers a slow find instead of throwing it away.** When a lookup outruns its timeout the provider keeps working in the background and hands back a queue id. The actor takes the id and polls it, because the credit has already been spent and giving up wastes it.
- **Works backwards from an address, a domain or a profile URL.** Reverse lookup returns the person: name, job title, company, company domain, public profile URL and total years of experience. That turns a bare list of addresses into a list of people you can actually write to.
- **Flags disposable, free, role, gibberish, catch-all and business addresses.** Each is a column and a filter, and each is also available as a standalone mode when a single flag is all you need and a full verification is not worth the credit.
- **Validates names.** Signup and lead forms collect as much keyboard noise as they do real names. The name mode returns a verdict plus separate gibberish and profanity flags, with three sensitivity levels.
- **Reads mail exchanger and registration records for a domain.** Useful for judging whether a domain can receive mail at all before spending anything on the addresses under it.
- **Suggests a typo correction.** When an address looks like a misspelling of a real domain, the suggested address comes back on the row. That is the difference between discarding a signup and recovering it.
- **Tells the three kinds of "no" apart.** An empty credit balance, an exhausted daily limit and a per minute rate limit arrive looking similar and need opposite reactions. The rate limit is retried automatically; the other two stop the run instead of spending an hour on requests that cannot succeed.
- **Checks the balance before it starts.** The balance read is free, and knowing a run will dry up at row four hundred is worth much more before the run than after it.
- **Never charges for a miss.** Only rows carrying a resolved result are billed.

### Input

| Field | What it does |
| --- | --- |
| `mode` | Which of the fifteen questions to ask. |
| `emails` | Addresses, for the verify, reverse email and flag modes. |
| `people` | Names, for the find mode. Paired line by line with `companies`. |
| `companies` | Company names or websites. |
| `domains` | Domains, for reverse domain, mail exchanger and registration modes. |
| `profileUrls` | Public profile URLs, for the reverse profile mode. |
| `names` | Names, for the validate names mode. |
| `statuses` | Keep only these verification verdicts. |
| `safeToSend` | Keep only these safe-to-send ratings. |
| `subStatusCodes` | Keep only these reason codes. |
| `excludeDisposable` | Drop throwaway addresses. |
| `excludeFreeEmail` | Drop free consumer mailboxes. |
| `excludeRoleAccounts` | Drop shared inboxes such as info and support. |
| `excludeGibberish` | Drop machine-generated mailbox names. |
| `excludeCatchAll` | Drop addresses on catch-all domains. |
| `requireBusinessEmail` | Keep only company addresses. |
| `minConfidence` | Minimum finder confidence to keep a found address. |
| `gibberishThreshold` | Sensitivity of the name gibberish check. |
| `timeoutMs` | Milliseconds the provider may spend on one lookup. |
| `queueSlowFinds` | Poll for a find that outran its timeout. On by default. |
| `requestsPerMinute` | Pace the run under your plan's rate limit. |
| `skipNotFound` | Leave inputs with no result out of the dataset. |
| `maxResults` | Hard cap on rows, and therefore on spend and run time. |
| `authScheme` | Which token shape to send. Automatic by default. |
| `apiKey` | Your own API token. Stored as a secret. |

### Example output

```json
{
  "found": true,
  "mode": "verify",
  "query": "jane.doe@example.com",
  "email": "jane.doe@example.com",
  "status": "valid",
  "safeToSend": "yes",
  "subStatusCode": 200,
  "subStatusReason": "Success",
  "bounceType": null,
  "account": "jane.doe",
  "domain": "example.com",
  "mxRecord": "aspmx.l.google.com",
  "smtpProvider": "google",
  "disposable": false,
  "free": false,
  "role": false,
  "gibberish": false,
  "suggestedEmail": null,
  "profile": "business",
  "verifiedOn": "2026-08-26T09:14:02.000Z",
  "timeTakenMs": 412,
  "error": null,
  "raw": { }
}
```

### Frequently asked questions

#### What does an email verification API actually check?

It works in layers. The address is checked for correct syntax, the domain is looked up for mail exchanger records, and the receiving mail server is then contacted over SMTP and asked whether that specific mailbox exists. On top of that the provider applies its own knowledge of disposable providers, role addresses, catch-all configurations and machine-generated mailbox names. Each row returns the verdict of that whole process, a safe-to-send rating, and the numeric reason code that decided it.

#### What is the difference between the verdict and the reason code?

The verdict is one of valid, invalid, catch-all or unknown. The reason code is the detail underneath it, and it is the field worth reading twice. Two addresses can both come back unknown when one hit a greylisting server that will verify on the second attempt, code 407, and the other could not be connected to at all, code 402. Filtering on the reason code lets you retry the first group and discard the second instead of throwing away both. Every row carries the code and the reason it stands for.

#### What is the difference between the verdict and safe to send?

The verdict describes the mailbox. Safe to send describes the risk of actually mailing it. A valid address on a badly configured server, or on a domain that accepts everything and only reveals the truth when mail arrives, is technically valid and still a bad idea to send to. The safe-to-send rating folds those cases in, which is why a run aimed at protecting sender reputation usually filters on it rather than on the verdict.

#### How does the email finder work?

Give it a person's name and a company name or website. It returns the most likely address with a confidence score from zero to one hundred, a flag for whether the address is a business or consumer account, and the full list of candidates it considered. Paste one company and a list of names and the single company applies to every person, which is the usual way to run a whole account in one pass.

#### What happens when a find takes too long?

The provider does not simply fail. It hands back a queue id and finishes the lookup in the background, and this actor takes that id and polls until the answer arrives. That matters because the credit is spent either way: abandoning a slow lookup means paying for an answer you never collect. Turn `queueSlowFinds` off if you would rather have the run move on.

#### What can reverse lookup tell me?

Given an address, a domain or a public professional profile URL, it returns the person or company behind it: name, job title, employer, employer domain, profile URL and total years of experience. It is the inverse of the finder, and it is what turns an inherited list of bare addresses into a list of people with enough context to write to.

#### What is a catch-all domain and why does it matter?

A catch-all domain is configured to accept mail for every possible mailbox, whether or not it exists. An SMTP check against any address there comes back positive and proves nothing about the individual mailbox, which is why these come back as catch-all rather than valid and are rated risky rather than safe. Use the catch-all mode when that single question is all you need, and the drop catch-all filter when you want them out of a verification run.

#### Why check names as well as addresses?

Because the name field on a signup form collects as much keyboard noise as it does real names, and a lead with a gibberish name is not a lead. The name mode returns a verdict with separate gibberish and profanity flags, at three sensitivity levels. It costs less attention than discovering the problem later in a mail merge.

#### Do I need my own API key?

Yes. This actor does not include data access. You use your own API token from Clearout, which is the provider whose email verification and email finder API this actor calls, created on their dashboard. Your own plan, credit balance and terms apply. Paste the token into the `apiKey` field, where it is stored as an Apify secret. The provider accepts two token shapes, a bearer token from the current dashboard and an older account id and secret pair, and the actor picks the right one by looking at your key. Override it with `authScheme` if you ever need to.

#### What happens when a lookup returns nothing?

An invalid address is a verdict, not a miss: the provider telling you a mailbox does not exist is the question you asked, so that row is written and billed like any other. A miss is an input the provider returned no result for at all, such as a person whose address could not be found, and those are written with `found: false` and never billed. Set `skipNotFound` to true to leave them out of the dataset entirely.

#### How much does a run cost?

Pricing is pay per result: you are charged for each input resolved into the dataset, and never for misses, for rows dropped by the filters, or for duplicates. Apify platform usage is included in the per-result price. Your own API provider's credit balance is separate and billed by them, and the actor reads and reports that balance before the run starts.

### Keyword map

email verification API, email validation API, bulk email verifier, email finder API, find email by name and company, email list cleaning, SMTP verification, MX record lookup, whois lookup, catch-all detection, disposable email detection, role account detection, gibberish email detection, email typo correction, safe to send, bounce rate reduction, sender reputation, list hygiene, signup form validation, reverse email lookup, email to person, domain to company, profile URL lookup, name validation API, profanity check, lead form validation, B2B contact enrichment

# Actor input Schema

## `mode` (type: `string`):

Which question to ask. Each mode reads a different input list, so fill in the list named in the mode you pick and leave the others empty.

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

Addresses to look up, one per line. Used by the verify, reverse email and single flag modes. An address pasted inside a longer string, such as a mail header or a name and address pair, is extracted before the request, and duplicates are removed so you are never charged twice for the same address.

## `people` (type: `array`):

Names to find addresses for, one per line, used by the find mode. Each line is paired with the matching line in Companies. Give a single company and it applies to every person on the list, which is the usual way to run everyone at one account.

## `companies` (type: `array`):

Company names or websites, one per line. Paired line by line with People in the find mode, and read on its own in the company to domains mode. A pasted URL is reduced to its bare hostname before the request, since the provider matches on the domain.

## `domains` (type: `array`):

Domains to look up, one per line. Used by the reverse domain, mail exchanger record and registration record modes. Pasted URLs are reduced to the bare hostname.

## `profileUrls` (type: `array`):

Public professional profile URLs to look up, one per line, used by the reverse profile URL mode.

## `names` (type: `array`):

Names to check, one per line, used by the validate names mode. Useful on signup and lead forms, where a name field collects as much keyboard noise as it does real names.

## `statuses` (type: `array`):

Only keep rows whose verification verdict is one of these. Restricting to valid is how you turn a raw list into one that is safe to send to. Leave empty to keep every verdict. Applied after the provider answers, so it reduces dataset noise and Apify spend rather than provider credits.

## `safeToSend` (type: `array`):

Only keep rows the provider rated this way. This is the blunter, more practical companion to the verdict: it folds in the reasons a technically valid address still bounces. Leave empty to keep every rating.

## `subStatusCodes` (type: `array`):

Only keep rows whose reason code is one of these, given as numbers such as 200, 406 or 411. The reason code is the detail under the verdict and it is where the useful decisions live: 407 is a greylisting server that will verify on a retry, while 406 is a mailbox that does not exist. Every row carries the code and the reason it stands for.

## `excludeDisposable` (type: `boolean`):

Leave out addresses on throwaway providers, which are created to expire and are worth nothing in a list.

## `excludeFreeEmail` (type: `boolean`):

Leave out addresses on free consumer providers, keeping only company addresses. Useful when the list is meant for business outreach.

## `excludeRoleAccounts` (type: `boolean`):

Leave out shared inboxes such as info, sales and support, keeping only addresses that belong to an individual.

## `excludeGibberish` (type: `boolean`):

Leave out addresses whose mailbox part looks machine generated rather than chosen by a person. These are what a form fills up with when it is being tested or abused.

## `excludeCatchAll` (type: `boolean`):

Leave out addresses on domains that accept everything sent to them. A catch-all domain answers yes to every mailbox, so a positive result there says nothing about the individual address.

## `requireBusinessEmail` (type: `boolean`):

Only keep addresses the provider identifies as belonging to a company rather than an individual consumer account.

## `minConfidence` (type: `integer`):

In the find mode, only keep addresses the provider is at least this confident about, on its zero to one hundred scale. Leave at zero to keep every candidate.

## `gibberishThreshold` (type: `string`):

How strictly the validate names mode judges a name to be gibberish. Off skips the check entirely, medium is a reasonable default for signup forms, and high is worth using when the form is being actively abused.

## `timeoutMs` (type: `integer`):

How long the provider may spend on one lookup before answering, from one thousand to one hundred and eighty thousand milliseconds. A short timeout returns more unknown verdicts, which cost you nothing but tell you nothing either. Leave empty to use the provider's own default.

## `queueSlowFinds` (type: `boolean`):

When a find outruns its timeout, let the provider finish it in the background and poll for the answer instead of giving up. On by default, and worth leaving on: the lookup has already been paid for, so abandoning it wastes a credit.

## `requestsPerMinute` (type: `integer`):

Pace the run so it stays under whatever rate your plan allows. Lower this if the provider starts reporting its per minute limit; raise it to finish a long list sooner.

## `skipNotFound` (type: `boolean`):

Leave inputs the provider returned nothing for out of the dataset. Note that an invalid address is a verdict, not a miss, so this does not drop invalid rows. Off by default. Misses are never charged for either way.

## `maxResults` (type: `integer`):

Stop after this many rows. This is the cap on both spend and run time.

## `authScheme` (type: `string`):

This provider accepts two token shapes. Tokens created on the current dashboard go as a bearer token, while the older account id and secret pair goes with no scheme word in front of it. Automatic picks by looking at your key and is right almost always; the other two are there for when it is not.

## `apiKey` (type: `string`):

Your own API token for the email verification API, created on the provider's dashboard. Required for every lookup. Stored as a secret.

## Actor input object example

```json
{
  "mode": "verify",
  "emails": [
    "jane.doe@example.com"
  ],
  "statuses": [],
  "safeToSend": [],
  "excludeDisposable": false,
  "excludeFreeEmail": false,
  "excludeRoleAccounts": false,
  "excludeGibberish": false,
  "excludeCatchAll": false,
  "requireBusinessEmail": false,
  "minConfidence": 0,
  "queueSlowFinds": true,
  "requestsPerMinute": 60,
  "skipNotFound": false,
  "maxResults": 100,
  "authScheme": "auto"
}
```

# Actor output Schema

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

One row per input, carrying the verification verdict and the reason behind it, the address found for a person, or the person or company found behind an address, a domain or a profile URL.

# 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@example.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("nabeelbaghoor/email-verification-finder-api").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@example.com"] }

# Run the Actor and wait for it to finish
run = client.actor("nabeelbaghoor/email-verification-finder-api").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@example.com"
  ]
}' |
apify call nabeelbaghoor/email-verification-finder-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nabeelbaghoor/email-verification-finder-api"
        }
    }
}

```

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/LSUoxESRxQNChVEkR/builds/ZcGmRn4bxvxTBlJvg/openapi.json
