# Company Email Finder - Work Email Format by Name + Domain (`flash_scraper/email-pattern-finder`) Actor

Find work emails from a name and company domain. Generates ranked address guesses (first.last@, flast@, first@...), crawls the company site to detect its REAL email pattern, and MX-checks the domain + provider. Confidence-scored, no API key, no proxies, pay-per-result.

- **URL**: https://apify.com/flash\_scraper/email-pattern-finder.md
- **Developed by:** [Flash Scrape](https://apify.com/flash_scraper) (community)
- **Categories:** Lead generation, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.40 / 1,000 person processeds

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/platform/actors/running/actors-in-store#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 Pattern Finder — find the email address pattern of any company from a name + domain

**Find the email address pattern of a company** and turn plain names into ranked work-email guesses. Give it a company domain and a list of full names; it returns each person's most likely addresses (`first.last@`, `flast@`, `first@`…) scored by how common each pattern is, plus a DNS check that the domain can actually receive mail and which provider runs it (Google Workspace vs Microsoft 365). It's the natural front end of a **find → verify → enrich** prospecting flow — **no API key, no proxies, no per-seat email-finder subscription**, just pay-per-result.

### What it does

- **Generates up to 12 ranked email candidates per person** from a library of common corporate patterns: `first.last`, `flast`, `firstlast`, `f.last`, `first`, `first_last`, `firstl`, `first-last`, `lastfirst`, `last.first`, `lfirst`, `last`.
- **Scores each candidate 0–99** based on how common that pattern is in the wild (`first.last` ranks highest), and surfaces the single `best_guess` per person.
- **Checks the domain's MX records** via a DNS-over-HTTPS lookup to confirm the domain can receive mail at all — if no mail server exists, every candidate's confidence is cut, so dead domains can't inflate your list.
- **Detects the email provider** from the MX host (Google Workspace, Microsoft 365, or other) — useful both as a deliverability signal and as a firmographic data point.
- **Normalizes names**: strips accents (`José` → `jose`), splits first/last name, and handles single-name inputs (those only get the `first@` pattern rather than fabricated surnames).
- **Accepts messy domain input** — `acme.com`, `https://www.acme.com/about`, it all resolves to the bare domain.
- Lets you **restrict generation to specific pattern IDs** when you already know the company's format and just want it applied to a batch of names.

Everything is **read-only and privacy-respecting**: the actor only builds address strings from the names you provide and performs one DNS lookup on the domain. It never sends an email and never probes individual mailboxes.

### Use cases

- **Sales prospecting** — you found 20 decision-makers on LinkedIn at a target account but no contact info. Paste the names + domain, get ranked address guesses in seconds instead of paying per-credit on Hunter or Apollo.
- **Recruiting outreach** — reach engineers and managers directly at their work address instead of fighting the InMail queue.
- **Lead-list completion for agencies** — you're delivering a lead list on Fiverr/Upwork and half the rows have a name and company but no email; batch-fill the gap and mark each row with its confidence score.
- **CRM enrichment** — export contacts missing an email, group them by company domain, run each group through the finder, and re-import the `best_guess` column.
- **Pattern discovery** — confirm one address for any employee (from a signature, a press release), see which pattern it matches, then re-run the actor with that pattern locked in via `patterns` for the whole department.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `domain` | string | *(required)* | The company domain emails should use, e.g. `acme.com` or `https://acme.com`. |
| `names` | array | *(required)* | People to generate email guesses for, one full name per line (e.g. `Jane Doe`). |
| `verifyMx` | boolean | `true` | Look up the domain's MX records (DNS) to confirm it can receive mail and detect the email provider. Boosts confidence. No mailbox probing, no email sent. |
| `maxCandidatesPerPerson` | integer | `6` | How many ranked email guesses to return per person (1–12). |
| `patterns` | array | *(empty)* | Optional: only generate these pattern ids (e.g. `first.last`, `flast`, `first`). Leave empty for all. |

Example input:

```json
{
  "domain": "stripe.com",
  "names": ["Patrick Collison", "Jane Doe"],
  "verifyMx": true,
  "maxCandidatesPerPerson": 6
}
```

### Output

One dataset row per person:

| Field | Description |
|---|---|
| `name` / `first_name` / `last_name` | The input name and its parsed parts |
| `domain` | Normalized company domain |
| `mx_found` | Whether the domain has mail servers (`null` if `verifyMx` was off) |
| `email_provider` | Detected provider from MX (e.g. Google Workspace, Microsoft 365) |
| `best_guess` | The single most likely address |
| `best_guess_confidence` | Its 0–99 score |
| `candidates` | All ranked guesses, each with `email`, `pattern`, and `confidence` |

Example row:

```json
{
  "name": "Jane Doe",
  "first_name": "jane",
  "last_name": "doe",
  "domain": "stripe.com",
  "mx_found": true,
  "email_provider": "Google Workspace",
  "best_guess": "jane.doe@stripe.com",
  "best_guess_confidence": 95,
  "candidates": [
    { "email": "jane.doe@stripe.com", "pattern": "first.last", "confidence": 95 },
    { "email": "jdoe@stripe.com", "pattern": "flast", "confidence": 88 },
    { "email": "janedoe@stripe.com", "pattern": "firstlast", "confidence": 78 },
    { "email": "j.doe@stripe.com", "pattern": "f.last", "confidence": 72 },
    { "email": "jane@stripe.com", "pattern": "first", "confidence": 65 },
    { "email": "jane_doe@stripe.com", "pattern": "first_last", "confidence": 60 }
  ]
}
```

Export to **CSV, Excel, or JSON** from the Apify Console or via API.

#### Example output

A real sample from a live run:

| name | domain | best\_guess | best\_guess\_confidence | mx\_found |
|---|---|---|---|---|
| Patrick Collison | stripe.com | patrick.collison@stripe.com | 95 | true |
| John Smith | stripe.com | john.smith@stripe.com | 95 | true |
| Jane Doe | stripe.com | jane.doe@stripe.com | 95 | true |
| Maria Garcia | stripe.com | maria.garcia@stripe.com | 95 | true |

### Pricing

**Pay-per-result**: you're charged only per person processed — a fraction of a cent per validated row. No subscription, no monthly credit packs that expire. A **free Apify plan** is enough to run your first batches and test the output on real accounts before paying anything.

### Tips / FAQ

#### Does it verify that the mailbox actually exists?

No — and that's deliberate. The actor generates **pattern-based guesses** ranked by real-world commonality and verifies the **domain** (MX lookup), not individual mailboxes. It performs no SMTP handshakes and sends nothing. For mailbox-level checking, pipe the `best_guess` column into the [Bulk Email Verifier](https://apify.com/flash_scraper/email-verifier).

#### How accurate are the guesses?

`first.last@` alone covers the largest share of corporate mailboxes, which is why it scores 95. Accuracy is highest at companies with standardized IT (most SMBs and mid-market firms); it's lower at very large enterprises with legacy formats or duplicate-name collisions. The confidence score tells you how much to trust each row — and if you can confirm one real address at the company, lock its pattern via `patterns` and accuracy for the rest of the batch jumps.

#### What happens with single names or names with accents?

Accents and diacritics are transliterated (`René Müller` → `rene.muller@…`). A single-token name (e.g. just `Madonna`) only generates the `first@` pattern — the actor won't invent a surname.

#### Why did all my confidences drop for one domain?

The MX check found no mail servers, so every candidate's score was reduced (to roughly 60% of its base, floor 5) and `mx_found` is `false`. That usually means the domain can't receive mail at that apex — check whether the company actually uses a different email domain.

#### Can I process people from many different companies in one run?

One run handles **one domain** with any number of names. For a multi-company list, group your rows by domain and trigger one run per domain via the Apify API — each run is billed only for the people it processes.

#### How do I integrate it?

Start runs from the [Apify API](https://docs.apify.com/api/v2) or SDK, schedule recurring runs with Apify **Schedules**, and export the dataset as CSV/Excel/JSON or push it onward with Apify integrations (webhooks, Zapier, Make).

### Related actors

- [Bulk Email Verifier](https://apify.com/flash_scraper/email-verifier) — the natural next step: verify and score the guessed addresses before you send.
- [Company & Domain Enricher](https://apify.com/flash_scraper/company-domain-enricher) — enrich the same domains with company name, socials, and tech stack.
- [Phone Number Validator](https://apify.com/flash_scraper/phone-number-validator) — clean the phone column of the same lead list.

***

Found a bug or missing a feature? Open an issue on this actor's **Issues tab** — typical response within 1 business day.

# Actor input Schema

## `domain` (type: `string`):

The company domain emails should use, e.g. 'acme.com' or 'https://acme.com'.

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

People to generate email guesses for, one full name per line (e.g. 'Jane Doe').

## `verifyMx` (type: `boolean`):

Look up the domain's MX records (DNS) to confirm it can receive mail and detect the email provider. Boosts confidence. No mailbox probing, no email sent.

## `crawlForPattern` (type: `boolean`):

Crawl a few public pages (home, about, team, contact) for real same-domain emails and infer the company's ACTUAL address pattern — evidence, not just priors. When an email is observed, the matching pattern is promoted to 98% confidence and flagged as 'observed'. No mailbox probing, no email sent.

## `maxCandidatesPerPerson` (type: `integer`):

How many ranked email guesses to return per person.

## `patterns` (type: `array`):

Optional: only generate these pattern ids (e.g. 'first.last', 'flast', 'first'). Leave empty for all.

## Actor input object example

```json
{
  "domain": "stripe.com",
  "names": [
    "Patrick Collison",
    "Jane Doe"
  ],
  "verifyMx": true,
  "crawlForPattern": true,
  "maxCandidatesPerPerson": 6
}
```

# Actor output Schema

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

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

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

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "domain": "stripe.com",
    "names": [
        "Patrick Collison",
        "Jane Doe"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("flash_scraper/email-pattern-finder").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 = {
    "domain": "stripe.com",
    "names": [
        "Patrick Collison",
        "Jane Doe",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("flash_scraper/email-pattern-finder").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 '{
  "domain": "stripe.com",
  "names": [
    "Patrick Collison",
    "Jane Doe"
  ]
}' |
apify call flash_scraper/email-pattern-finder --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/mvb626RINfBd2keil/builds/1Qf08WDBqPbY9XdZ0/openapi.json
