# Email Finder & Verifier – B2B Emails by Name & Company (`inovaflow/email-finder-verifier`) Actor

Find a person's work e-mail from name and company (the company's address pattern, learned live and checked against its mail server), list a domain's reachable addresses, or verify an address list in bulk. Every row says what was confirmed. No database resale, no login. Dataset-only, MCP-ready.

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

## Pricing

from $10.00 / 1,000 email addresses

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

**Find a person's work e-mail from their name and company, list every reachable address on a domain, or verify the addresses you already have — live, with the pattern, a confidence and exactly what the mail server confirmed on every row.** Give it `Jane Doe, acme.com` (or the rows of a people finder), a list of domains, or a list of addresses. Nothing is looked up in a resold database: the company's own address pattern is learned from its website, candidates are generated from the person's name, and each is checked against the domain's mail server.

E-mail tools on the market either resell stale databases by the thousand, or guess a pattern and call it "verified". This Actor does the work an outbound team does by hand — read the company site for addresses and names, learn how the company forms its addresses, generate the person's, check it — and reports the depth of every check instead of a single green tick.

### Email finder & verifier: what you get

One row per person, per domain address, or per verified address:

| Field | What it tells you |
| --- | --- |
| `email`, `status` | The address and its status — `found` / `not_found` for people; `valid` (mailbox confirmed), `risky` (catch-all domain), `invalid` (no mail server, rejected, bad syntax, disposable) or `unknown` (mail server only) for addresses |
| `pattern`, `confidence`, `domainPattern` | How the address is formed (`first.last`, `flast`, …), a 0–100 confidence (100 = seen on the company site for this person; 85 / 70 = the company's learned pattern; 45 and below = by prevalence; 95 = mailbox confirmed), and the pattern learned for the whole domain |
| `verified`, `verification`, `catchAll`, `mx` | `verified` is true only when the mailbox was confirmed; `verification` says how far the check went (`smtp-valid`, `smtp-catch-all`, `mx-only`, `no-mx`, `syntax-only`); catch-all flag and the mail exchanger |
| `type`, `roleAddress`, `freeMail`, `disposable` | Personal vs role address (`info@`, `sales@`…), free-mail and disposable flags |
| `personName`, `firstName`, `lastName`, `company`, `domain` | The person and company, ready for merge fields and joins |
| `source`, `sourceUrl`, `candidates[]`, `reason` | Where the address came from (`website:/team`, `search`, `pattern`, `input`), the alternatives that were tried with their own verification, and why nothing was delivered when that is the case |

Three dataset views: **E-mails** (one line per person / address), **Verification** (what was confirmed), **By domain** (addresses per domain with the learned pattern and the page they were found on).

### How it works

1. **Learn the domain** — the home page and the contact, about, team and imprint pages are read for addresses (hidden ones decoded) and named people. Addresses that match a named person teach the domain's pattern with strong evidence; other on-domain addresses teach it by shape. Optionally one web search per domain adds addresses seen elsewhere.
2. **Find the person** — an address seen on the site for that person wins outright; otherwise candidates are generated from the person's name in the learned pattern first, then by how common each pattern is across companies.
3. **Verify** — syntax, disposable and free-mail checks, the domain's mail server (MX), and — where the network allows an SMTP conversation — the mailbox itself with a catch-all probe. `verified` never says more than the mail server did.
4. **Deliver** — the best address with its candidates for people; every reachable address for domains (personal and role, plus the learned pattern applied to the people named on the site); the result for each address in a verify list.

No login, no cookies, no third-party data vendor, no nested scrapers.

### Chain it into a prospecting pipeline

- **In:** the rows of a people finder (`{ name | firstName + lastName, company, companyDomain }`) can be passed as `people` unchanged; the domains of a company list as `domains`.
- **Out:** rows keyed by `domain` with `email`, `confidence` and `verification` — filter on `verified` or a confidence threshold and send to a sequencer.

### Who uses it

- **Outbound / GTM agents** — a keyword-discoverable, MCP-callable step that turns people into deliverable addresses unattended.
- **SDR teams** — the work address for every decision maker on a target list, with a confidence you can route on.
- **Ops and data teams** — a bulk verifier for existing lists, and a per-domain address inventory.

### Set it up in a minute

1. Paste **People** (`Name, domain` per line), **Domains**, and/or **E-mails to verify**.
2. Start. Rows arrive as each item is finished; the run summary is in the `OUTPUT` record.

Verification and discovery settings are collapsed below the essentials; the defaults are tuned for unattended runs.

### Use it from an agent or the API

```json
{ "people": ["Guillaume Moubeche, lemlist.com", "Tope Awotona, calendly.com"] }
```

```json
{ "people": [{ "firstName": "Jessie", "lastName": "Sloan", "companyDomain": "gong.io" }], "domains": ["syberry.com"], "emails": ["contact@lemlist.com"] }
```

Agents may also pass `contacts` / `names`, `companies` / `websites`, `addresses`, and objects with `email`. Results are in the default dataset (`?view=emails`, `?view=verification`, `?view=domains`); the run summary is in the `OUTPUT` record of the run's key-value store. Through the Apify MCP server, call `inovaflow/email-finder-verifier` with the same input.

### Output example

```json
{
  "mode": "person",
  "email": "tope.awotona@calendly.com",
  "status": "found",
  "type": "personal",
  "personName": "Tope Awotona",
  "firstName": "Tope",
  "lastName": "Awotona",
  "domain": "calendly.com",
  "pattern": "first.last",
  "confidence": 70,
  "verified": false,
  "verification": "mx-only",
  "catchAll": null,
  "mx": "aspmx.l.google.com",
  "source": "pattern",
  "domainPattern": "first.last",
  "candidates": [
    { "address": "tope.awotona@calendly.com", "pattern": "first.last", "confidence": 70, "verified": false, "verification": "mx-only" },
    { "address": "tope@calendly.com", "pattern": "first", "confidence": 35, "verified": false, "verification": "mx-only" }
  ]
}
```

### Pricing

Pay per event: **$0.01 per e-mail address** delivered (a person with an address, or a domain with at least one address) and **$0.001 per e-mail check** in a verify list, plus a small per-run start fee. People and domains where nothing is found are free.

### Good to know

- **Verification depth depends on the network.** Where outbound SMTP is blocked, addresses are verified down to the domain's mail server (`mx-only`) and delivered with their pattern confidence; where SMTP is reachable, mailboxes are confirmed (`smtp-valid`) and catch-all domains are flagged (`risky`).
- **A company name without a domain** is resolved to its website only when a page verifiably names the company; otherwise the person is delivered as `not_found` with `reason: company_not_resolved` — pass the domain for the best results.
- **Role addresses** (`info@`, `sales@`) are returned in domain lists (switch off with *Include role addresses*) and flagged `roleAddress: true` in verify lists.
- Results reflect what companies publish; `source`, `sourceUrl` and `candidates[]` carry the evidence for every row.

# Actor input Schema

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

One per line: `Jane Doe, acme.com` · `Jane Doe – Acme Inc` · `Jane Doe at acme.com`. Also accepted: objects {name or firstName + lastName, company, domain} — e.g. the rows of a people finder — and the aliases `contacts`, `names`.

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

Websites or domains, one per line. Every reachable address on the domain is returned (personal and role addresses found on the site, plus the learned pattern applied to the people named on it). Company names are resolved to their website when possible. Also accepted as `companies` or `websites`.

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

Addresses to verify, one per line (`jane@acme.com` or `Jane Doe <jane@acme.com>`). Also accepted as `addresses` or objects {email}.

## `verifyEmails` (type: `boolean`):

Check every address against the domain's mail server; addresses on domains without a mail server are dropped (people) or marked invalid (verify list).

## `smtpVerification` (type: `boolean`):

Also ask the mail server whether the mailbox exists and detect catch-all domains (falls back to the mail-server check when SMTP is unreachable).

## `crawlWebsite` (type: `boolean`):

Crawl the home page and the contact / about / team / imprint pages for addresses (hidden ones decoded) and named people — the source of the domain's address pattern and of addresses seen directly.

## `searchWeb` (type: `boolean`):

Also run one web search per domain for addresses on it (mostly role addresses). Off by default — uses Apify's Google search proxy (a few cents per domain).

## `maxPagesPerSite` (type: `integer`):

Home page plus contact-type pages crawled per domain.

## `maxCandidates` (type: `integer`):

How many address patterns are tried and reported per person (the learned pattern first).

## `includeRoleEmails` (type: `boolean`):

In domain lists, also return info@, sales@, support@ and similar role addresses (marked `type: role`).

## `maxAddressesPerDomain` (type: `integer`):

Cap on rows per domain in domain lists.

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

Upper bound on people + domains + addresses processed in one run.

## `maxConcurrency` (type: `integer`):

How many people / domains / addresses are processed at once.

## Actor input object example

```json
{
  "people": [
    "Jane Doe, acme.com",
    "John Smith – Acme Inc"
  ],
  "domains": [
    "lemlist.com",
    "syberry.com"
  ],
  "emails": [
    "jane.doe@acme.com",
    "info@acme.com"
  ],
  "verifyEmails": true,
  "smtpVerification": true,
  "crawlWebsite": true,
  "searchWeb": false,
  "maxPagesPerSite": 6,
  "maxCandidates": 4,
  "includeRoleEmails": true,
  "maxAddressesPerDomain": 25,
  "maxItems": 2000,
  "maxConcurrency": 8
}
```

# Actor output Schema

## `emails` (type: `string`):

One row per person / address with the address, pattern, confidence and verification.

## `verification` (type: `string`):

What was confirmed per address: mail server, mailbox, catch-all, flags.

## `domains` (type: `string`):

Addresses grouped by domain with the learned pattern and the source page.

## `summary` (type: `string`):

Counts and stats.

# 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 = {
    "people": [
        "Guillaume Moubeche, lemlist.com",
        "Tope Awotona, calendly.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("inovaflow/email-finder-verifier").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 = { "people": [
        "Guillaume Moubeche, lemlist.com",
        "Tope Awotona, calendly.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("inovaflow/email-finder-verifier").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 '{
  "people": [
    "Guillaume Moubeche, lemlist.com",
    "Tope Awotona, calendly.com"
  ]
}' |
apify call inovaflow/email-finder-verifier --silent --output-dataset

```

## MCP server setup

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

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/yt0c5q0zsNYOyMjxP/builds/VwNDLQzzzbfZhYoN0/openapi.json
