# Email Finder API (`lergassy/email-finder-api`) Actor

Find work e-mail addresses from a person's name and their company or domain: the address, its layout, a confidence level, the evidence behind it and the mail provider. Export scraped data, run the scraper via API, schedule and monitor runs, or integrate with other tools or AI workflows.

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

## Pricing

from $14.00 / 1,000 work e-mail founds

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?

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

### What is Email Finder API?

**Email Finder API** turns a person's name and their company into that person's **work e-mail address**. Give it `Jane Doe, acme.com` — or `Jane Doe, Acme Consulting`, because it resolves company names to domains too — and it returns `jane.doe@acme.com` together with the reason it believes that address, the alternatives worth trying if it bounces, and the state of the company's mail domain. No login, no API key, no official API needed.

The difference from an ordinary **email finder** is what happens before the address is written. Most tools apply the same guessed layout to every company. This one first reads the company's own website and looks at the addresses it already publishes. A team page that says `michael.hart@acme.com` has told you the rule for everyone else at Acme, and the Actor says so in the output: the layout, the addresses it was read from, and how many there were. When a company publishes nothing personal, you are told that as well, and the address is marked as a guess rather than dressed up as a find.

It is a pure HTTP Actor — no browser, no proxy, no third-party paid API — so it is fast and cheap to run. A three-person lookup finishes in about five seconds.

### What data does Email Finder API return?

One row per person, one row per company, and one free row for anyone who could not be placed.

| Field | What it holds | Example |
|---|---|---|
| `fullName` | The person as you wrote them | `Jason Fried` |
| `email` | The most likely work address | `jason@basecamp.com` |
| `confidence` | `confirmed`, `high`, `medium`, `low` or `unusable` | `confirmed` |
| `emailPattern` | The layout used: `first.last`, `first`, `flast`, `firstlast`, `first_last`, `firstl`, `f.last`, `last.first`, `lastfirst`, `first-last`, `last`, `fl` | `first` |
| `emailPatternSource` | `site` — read off the company's own pages; `default` — the company published nothing to learn from | `site` |
| `foundOnSite` | True when the address was not constructed at all but found published | `true` |
| `alternatives` | The next most likely addresses, each with its layout | `[{"email":"jason.fried@basecamp.com","pattern":"first.last"}]` |
| `patternEvidence` | The published addresses the layout was read from | `["jason@basecamp.com"]` |
| `patternEvidenceCount` | How many of them there were | `1` |
| `domain` | The company's mail domain | `basecamp.com` |
| `domainSource` | `input`, `directory` or `guess` — how the domain was arrived at | `input` |
| `companyName` | Company name from the site's own structured data | `Basecamp` |
| `emailStatus` | `deliverable`, `risky`, `undeliverable` or `unknown` | `deliverable` |
| `emailProvider` | Who runs the company's mail | `google` |
| `emailMxHost` | Highest-priority mail server | `aspmx.l.google.com` |
| `emailIsRole` / `emailIsFree` / `emailIsDisposable` | Department address, consumer mailbox, throwaway domain | `false` |
| `mailboxVerified` | Always `false`, and here so nothing reads as more than it is — see the FAQ | `false` |
| `summary` | One sentence saying where the address came from | `jason@basecamp.com is published on basecamp.com itself.` |

Company rows carry the same layout fields plus `emailsFoundOnSite` (every public address on that domain), `pagesScanned` and `siteError`.

### How much does it cost to find e-mail addresses?

Pay-per-event, and you only pay for answers.

| Event | Price | Charged when |
|---|---|---|
| Work e-mail found | **$0.02** | One usable address is returned for one person |
| Company address layout read from its site | **$0.006** | One company's layout was read off addresses it publishes |

That is **$20 per 1,000 addresses**, plus about $6 per 1,000 companies if you leave company rows on. A person whose company could not be resolved, a name with no usable letters in it, a domain that takes no mail, and every error row are **free** — the Actor never bills you for a row it could not answer.

Apify's free plan includes $5 of platform usage a month, which is around 240 addresses before you pay anything. Bronze, Silver and Gold accounts pay 10%, 20% and 30% less per event.

Because the Actor sends plain HTTP requests and runs no browser, its compute cost is negligible — you are paying for the answer, not for a proxy bill.

### How to find someone's work e-mail address

1. Open the Actor and paste your people into **👤 People to find**, one per line: `Full Name, company`.
2. The company half can be a domain (`stripe.com`), a full URL (`https://stripe.com/about`) or the company's name (`Clifford Chance`). Mixed lists are fine.
3. Press **Start**. A run of a few people takes seconds; a thousand-person list takes a few minutes.
4. Read the **E-mails** table. Sort by `confidence` and work the `confirmed` and `high` rows first.
5. Export to CSV, JSON or Excel, or pull the same rows from the API.

![Email Finder API input form — names, companies and options](https://raw.githubusercontent.com/lergassy/apify-actor-assets/main/email-finder-api/email-finder-api-input-form.png)

### ⬇️ Input

```json
{
  "people": [
    "Jason Fried, basecamp.com",
    "Patrick Collison, stripe.com",
    "Maria Bennett, cliffordchance.com"
  ],
  "candidatesPerPerson": 3,
  "checkMx": true,
  "includeCompanyRows": true,
  "maxPagesPerCompany": 4
}
```

#### Lists that already have columns

If your data is already split into fields — from a CRM export, a spreadsheet or another Actor — use `peopleList` instead of the plain lines:

```json
{
  "peopleList": [
    { "firstName": "Jane", "lastName": "Doe", "company": "acme.com" },
    { "fullName": "Michael Hart", "domain": "example.co.uk" }
  ]
}
```

#### Chaining from another Actor

`inputDatasetId` reads the people straight out of an existing Apify dataset, and the four `*Field` inputs say which columns hold the name and the company. Point it at the output of [US New Business Leads](https://apify.com/lergassy/us-business-filings) and you have newly registered companies enriched with addresses in one step.

### ⬆️ Output

![Email Finder API output table — work emails with confidence and layout](https://raw.githubusercontent.com/lergassy/apify-actor-assets/main/email-finder-api/email-finder-api-output-table.png)

#### A person row

```json
{
  "type": "person",
  "fullName": "Maria Bennett",
  "firstName": "maria",
  "lastName": "bennett",
  "companyInput": "cliffordchance.com",
  "companyName": "Clifford Chance",
  "domain": "cliffordchance.com",
  "domainSource": "input",
  "email": "maria.bennett@cliffordchance.com",
  "emailPattern": "first.last",
  "emailPatternSource": "site",
  "confidence": "high",
  "foundOnSite": false,
  "alternatives": [
    { "email": "maria@cliffordchance.com", "pattern": "first" },
    { "email": "mbennett@cliffordchance.com", "pattern": "flast" }
  ],
  "patternEvidence": ["richard.franco@cliffordchance.com", "maria.arnone@cliffordchance.com"],
  "patternEvidenceCount": 22,
  "emailStatus": "deliverable",
  "emailProvider": "mimecast",
  "emailMxHost": "eu-smtp-inbound-2.mimecast.com",
  "emailIsRole": false,
  "emailIsFree": false,
  "emailIsDisposable": false,
  "mailboxVerified": false,
  "summary": "maria.bennett@cliffordchance.com follows the first.last layout confirmed on cliffordchance.com; the domain accepts mail."
}
```

#### A company row

```json
{
  "type": "company",
  "domain": "basecamp.com",
  "companyName": "Basecamp",
  "emailPattern": "first",
  "emailPatternSource": "site",
  "patternEvidence": ["jason@basecamp.com"],
  "patternEvidenceCount": 1,
  "emailsFoundOnSite": ["jason@basecamp.com"],
  "pagesScanned": 4,
  "summary": "basecamp.com writes its e-mail addresses as first, seen in 1 address(es) published on its own site."
}
```

### How the address layout is worked out

The Actor reads the company's home page and up to three more — contact, about, team, legal — and collects every address on the company's own domain. Then it asks of each one: is there a human name in this?

That question is the whole method. `jane.diaz@` and `complaints-in@` have the identical shape, and a tool that cannot tell them apart will decide that the company writes `firstname-lastname` on the strength of a complaints inbox. So each half of an address is checked against a list of common given names: an address with a recognised first name in it identifies the layout, an address made of department words is thrown out, and an address where nothing is recognisable is ignored rather than counted as weak evidence. The votes are then tallied, and a layout that two addresses agree on outranks one that a single address suggests.

What comes out the other side is the `confidence` column:

- **`confirmed`** — the address is not constructed. It is published on the company's own website.
- **`high`** — two or more of the company's own addresses agree on the layout.
- **`medium`** — exactly one address established the layout.
- **`low`** — the company publishes nothing personal, so the most common layout across companies (`first.last`) was used. This is a guess and is labelled as one.
- **`unusable`** — the domain exists but accepts no mail, so no address at it will arrive.

**How often a layout is actually found.** Measured on 34 company websites on 12 September 2026, reading four pages each: 8 published a personal address the layout could be read from. The split matters more than the total — **6 of 9 law firms** did, and only **2 of 25 technology companies**. Professional services, agencies, clinics, brokerages and firms with a staff directory are where this works best, and those are also what most B2B lead lists are made of. Large consumer-facing tech companies publish almost nothing, and for them you will mostly get `low`.

### Use cases for work e-mail addresses

#### Sales and lead generation

You have a list of decision-makers with names and companies and no addresses. Run it through and sort by confidence: the `confirmed` and `high` rows go into the sequence today, the `low` rows go in with a soft first touch or not at all.

#### CRM repair

Contacts imported years ago carry a name and an employer and an empty e-mail column. Point `inputDatasetId` at the export and fill the gaps, then keep `emailProvider` to know which contacts sit behind Microsoft 365 and which behind Google.

#### Recruiting

A shortlist of candidates from a conference programme, a paper's author list or a company's team page is names plus employers. This turns it into a way to write to them.

#### AI agents and automations

The Actor is small, literal and flat: one call in, one row per person out, every field a scalar. An agent can call it through the Apify MCP server or the API and act on `confidence` without reading any documentation.

#### Research and journalism

Finding the right person at a firm to put a question to, with the evidence for why that address is the right shape, and the mail provider that will handle it.

### Integrations

- **API** — start a run and read the dataset with the Apify API: `POST https://api.apify.com/v2/acts/lergassy~email-finder-api/runs?token=<TOKEN>`.
- **Python and JavaScript clients**:

```python
from apify_client import ApifyClient

client = ApifyClient("<TOKEN>")
run = client.actor("lergassy/email-finder-api").call(run_input={
    "people": ["Jane Doe, acme.com", "Michael Hart, Acme Consulting"]
})
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
    if row["type"] == "person":
        print(row["email"], row["confidence"])
```

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<TOKEN>' });
const run = await client.actor('lergassy/email-finder-api').call({
    people: ['Jane Doe, acme.com'],
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.filter((i) => i.type === 'person'));
```

- **n8n, Make, Zapier, Google Sheets** — through the Apify integrations, so the addresses land in the sheet or the CRM without any code.
- **MCP server** — the Actor is callable as a tool by Claude, ChatGPT and any other MCP client through Apify's MCP server.
- **Webhooks** — fire a webhook on run completion to push the finished rows wherever they are needed.

### Error items

Rows with `"type": "error"` are never charged. They carry a plain-language `error` field:

- *Could not work out a website for "…"* — the company name matched nothing and no obvious domain answered. Pass the domain instead.
- *No company given for this person* — the line had a name and nothing after the comma.
- *The name could not be turned into an address* — nothing usable in the name field.

A company row may also carry `siteError` (`website_unreachable` or `website_blocked`). The address is still produced from the default layout in that case, and marked `low`.

### ❓ FAQ

#### Do you verify that the mailbox exists?

No, and the output says so in the `mailboxVerified` field, which is always `false`. Checking whether a specific mailbox exists needs an SMTP conversation on port 25, and outbound port 25 is blocked from Apify's cloud — no Actor running there can do it, whatever its listing claims. What you get instead is domain-level truth (does the domain exist, does it accept mail, who runs it) and something better than an SMTP ping where it is available: evidence from the company's own website that this is the shape its addresses take.

#### How accurate is it?

Where `confidence` is `confirmed`, the address is published by the company itself — there is nothing to be wrong about. Where it is `high` or `medium`, the layout came from the company's own addresses and the remaining risk is the spelling of the person's name, not the format. Where it is `low`, treat it as a guess: `first.last` is the most common corporate layout, but the Actor found no proof for this company and does not pretend otherwise.

#### What if the first address bounces?

Use `alternatives`. It holds the next most likely addresses for the same person, each labelled with its layout, so a bounce costs you a retry rather than a dead lead.

#### Does it work with company names, not just domains?

Yes. A company name is resolved through a public company index first, and if that finds nothing, the obvious spelling of the name is tested against DNS. `domainSource` tells you which route was taken — `input`, `directory` or `guess` — so you can decide how much to trust a row whose domain was inferred.

#### Does it handle accents and compound names?

Accents are stripped the way mail systems strip them (`José` becomes `jose`). A compound given name is offered both ways: `jeanpierre.dubois@` is the primary and `jean-pierre.dubois@` sits directly behind it in `alternatives`. Surname particles stay attached — `van der Berg` becomes `vanderberg`.

#### Is it legal to look up business e-mail addresses?

The Actor reads only pages that companies publish openly and works out an address format from them; it does not access any private system. Business contact data is treated differently from personal data in most jurisdictions, but sending unsolicited mail is regulated separately — GDPR, CAN-SPAM, CASL and the rest apply to what you do with an address, not to knowing it. Check your obligations for your market, and consult a lawyer if a campaign is at stake.

#### Can I use Email Finder API with the Apify API?

Yes — start runs, pass input and read results through the standard Apify API and the Python or JavaScript clients, as shown above.

#### Can I use it through an MCP server?

Yes. It is exposed as a tool through Apify's MCP server, so an AI agent can call it directly. The input schema is small and the output is flat on purpose.

#### Can I integrate it with other apps?

Yes — n8n, Make, Zapier, Google Sheets, Slack and webhooks are all available through Apify's integrations.

#### Does one person always produce one row?

Yes. One row per person, plus one row per company when company rows are on, plus a free error row for anyone who could not be placed.

#### Do I need a proxy?

No. This Actor reads ordinary business websites with plain HTTP requests, and the proxy input is off by default. Turn it on only if you are reading thousands of sites in one run and some begin refusing.

### Your feedback

Found a company whose layout it read wrongly, or a name shape it does not handle? Open an **Issue** on the Actor page with the company and the expected address — those reports are what the given-name list and the layout rules grow from. Reviews are read and answered.

### You might also like

| Actor | What it does |
|---|---|
| [Website Contacts API](https://apify.com/lergassy/website-contacts-api) | Every public e-mail, phone, WhatsApp and social profile for a list of websites |
| [Email Verifier & Phone Number Validator](https://apify.com/lergassy/email-phone-verifier) | Check addresses and numbers in bulk: domain deliverability, role and throwaway flags, numbering-plan validation |
| [US New Business Leads](https://apify.com/lergassy/us-business-filings) | Newly registered US companies with addresses, industry codes and a lead score |

# Actor input Schema

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

One person per line, written as <code>Full Name, company</code>. The company can be a domain (<code>stripe.com</code>), a website (<code>https://stripe.com/about</code>) or just the company's name (<code>Clifford Chance</code>) — the Actor works out the domain either way. <code>Jane Doe @ acme.com</code> works too.

## `candidatesPerPerson` (type: `integer`):

How many address candidates to return. The first is the answer; the rest are the next most likely layouts, listed in <code>alternatives</code> for when the first one bounces.

## `checkMx` (type: `boolean`):

Look up the company's mail servers, so you know whether the domain accepts mail at all and who runs it (Google Workspace, Microsoft 365, and so on). Free and fast — leave it on.

## `includeCompanyRows` (type: `boolean`):

Write an extra row for each company with the address layout found, the addresses it was read from, and every public address on the site. These rows have different columns from the people rows, so the table shows blanks where a column does not apply — leave it off unless you want that company sheet.

## `maxPagesPerCompany` (type: `integer`):

How deep to read each company's website looking for published addresses. Contact, about, team and legal pages are read first, so more than six rarely finds anything new.

## `maxPeople` (type: `integer`):

A ceiling on how many people this run may look up, whatever the input contains. Leave the default unless you are running a big list on purpose.

## `peopleList` (type: `array`):

An array of objects: <code>{"firstName": "Jane", "lastName": "Doe", "company": "acme.com"}</code>. <code>fullName</code> works in place of the two name fields, and <code>domain</code>, <code>website</code> or <code>url</code> in place of <code>company</code>.

## `inputDatasetId` (type: `string`):

ID of an Apify dataset to read the people from — for example the output of <a href='https://apify.com/lergassy/us-business-filings' target='_blank'>US Business Leads</a> or any lead list you already have on the platform.

## `nameField` (type: `string`):

Which column of that dataset holds the person's full name.

## `firstNameField` (type: `string`):

Which column holds the first name, when the name is split into two.

## `lastNameField` (type: `string`):

Which column holds the last name.

## `companyField` (type: `string`):

Which column holds the company name, domain or website.

## `concurrency` (type: `integer`):

How many companies to read at once. Lower it if a target website starts refusing requests.

## `pageTimeoutSecs` (type: `integer`):

How long to wait for one page of a company website.

## `proxyConfiguration` (type: `object`):

Not needed for ordinary business websites — this Actor sends plain HTTP requests and no browser. Turn a proxy on only if you are reading thousands of sites and some start refusing.

## Actor input object example

```json
{
  "people": [
    "Jason Fried, basecamp.com",
    "Patrick Collison, stripe.com",
    "Maria Bennett, cliffordchance.com"
  ],
  "candidatesPerPerson": 3,
  "checkMx": true,
  "includeCompanyRows": false,
  "maxPagesPerCompany": 4,
  "maxPeople": 1000,
  "nameField": "fullName",
  "firstNameField": "firstName",
  "lastNameField": "lastName",
  "companyField": "company",
  "concurrency": 5,
  "pageTimeoutSecs": 15,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

One flat row per person: the work e-mail address, its confidence, the layout it follows and where that layout was read from, alternatives to try if it bounces, and the mail domain's status, provider and MX host. Company rows carry the layout and every address published on that company's site. Error rows carry the reason and are never charged.

# 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": [
        "Jason Fried, basecamp.com",
        "Patrick Collison, stripe.com",
        "Maria Bennett, cliffordchance.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("lergassy/email-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 = { "people": [
        "Jason Fried, basecamp.com",
        "Patrick Collison, stripe.com",
        "Maria Bennett, cliffordchance.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("lergassy/email-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 '{
  "people": [
    "Jason Fried, basecamp.com",
    "Patrick Collison, stripe.com",
    "Maria Bennett, cliffordchance.com"
  ]
}' |
apify call lergassy/email-finder-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,lergassy/email-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/8oY7W212BtWdduVBp/builds/Fd7QHLVXZZmDAs1J8/openapi.json
