Email Pattern Finder
Pricing
from $2.00 / 1,000 successful lookups
Email Pattern Finder
Generate ranked, likely email address candidates for a person from their name and company domain, based on well-known corporate email conventions. Confirms only that the domain accepts mail (MX/A record) — never claims mailbox-level verification, which no HTTP-only tool can honestly provide.
Pricing
from $2.00 / 1,000 successful lookups
Rating
0.0
(0)
Developer
Adrian Voss
Maintained by CommunityActor stats
1
Bookmarked
2
Total users
1
Monthly active users
19 hours ago
Last modified
Categories
Share
You give this actor a list of people — a name plus their company's domain. For each one, it generates a ranked set of likely email address candidates using well-known corporate email conventions (first.last@, flast@, firstlast@, and the rest), and confirms the domain can actually receive mail via a live MX/A-record check. You get back the most likely address, the full ranked candidate list, and which pattern won, as one flat row per person.
This is a pattern generator with a mail-route check, not a mailbox verifier. Confirming a specific address is a real, live mailbox requires an SMTP RCPT TO probe on port 25 — outbound port 25 is blocked on essentially every cloud/serverless runtime, Apify's included, to prevent spam abuse. Nothing here pretends otherwise: mailboxVerified is always false. What this actor honestly delivers is the same first step every commercial "email finder" tool starts from — a confident, ranked guess plus proof the domain isn't a dead end — without charging for a domain that can't receive mail at all.
Who it's for
The accountable_eel catalogue sells company intelligence columns for outbound. Each actor takes a list of domains or company identifiers and returns one flat, stably-named row per input — firmographics, registry IDs, tech stack, email route, hiring activity — the shape a Clay table, an n8n workflow, or an AI agent can consume without post-processing. Pricing is pay-per-event: a few tenths of a cent for a row that actually resolved, and nothing for a miss, so a list that doesn't enrich costs you next to nothing. This actor reuses this portfolio's own email-deliverability-check mail-route logic verbatim rather than re-deriving it, so the two stay consistent on what "this domain accepts mail" means.
This one is for outbound prospecting specifically: you have a decision-maker's name and their company's domain (from a job posting, a LinkedIn profile, a company's team page) and need a best-guess email address to reach them at, before running it through a separate deliverability/verification step.
Why this one
- Never charged for a domain that can't receive mail. The MX/A-record check runs before any candidate is billed — a domain with no mail route is a free, honest miss, not a wasted guess.
- Ranked, not just listed. Candidates come back ordered by real-world pattern frequency, with a single
mostLikelyEmailpick, not an unordered dump you have to re-rank yourself. - Honest about what it can't confirm.
mailboxVerifiedis alwaysfalse— this actor will never claim a specific mailbox exists, because no HTTP-only tool honestly can. - Runs as a batch. Paste a whole list of names and domains from a lead list or a scraped team page, get back a dataset instead of guessing each address by hand.
- Handles real-world name mess. Apostrophes, hyphens, and accented characters (
O'Brien,Renée,Smith-Jones) sanitize into the plain local-part real mail systems actually use, not a broken guess. - Field names don't move between runs. The output schema is frozen —
mostLikelyEmailis alwaysmostLikelyEmail— so a Clay table or an agent's tool call built against it today still works against it next month.
What you get
One row per input person. Every field below is present on a found: true row; on a miss, only query, found, status, message, and scrapedAt are set.
| Field | Type / format | Description |
|---|---|---|
query | string | The input line exactly as you submitted it. |
found | boolean | true if the domain has a confirmed mail route and at least one candidate was generated, false otherwise. Never charged when false. |
status | string | OK on a hit; NOT_FOUND or BAD_FORMAT on a miss. |
firstName | string | The first name as submitted. |
lastName | string | The last name as submitted. |
domain | string | The company domain, lowercased. |
hasMailRoute | boolean | Always true on a hit — the domain has an MX or, failing that, an A record. |
mostLikelyEmail | string | The single top-ranked candidate address. |
mostLikelyPattern | string | Which pattern produced it (e.g. first.last, flast). |
candidateEmails | array of strings | Every ranked candidate, most-likely first. |
candidateCount | number | How many distinct candidates were generated (duplicates from short names, e.g. first and flast colliding, are removed). |
mailboxVerified | boolean | Always false — see the honesty note above. Never becomes true; it exists so a buyer's pipeline can filter on it deliberately rather than assume verification happened. |
scrapedAt | string (ISO 8601) | Timestamp of the mail-route check for this row. |
message | string (miss rows only) | Human-readable reason for a miss. |
Price
$4 per 1,000 people + domains, plus a $0.00005 start fee. Misses (found:false) are never charged.
$4 per 1,000 people, plus a $0.00005 start fee — the same rate as this portfolio's other validator-class actors (email-deliverability-check, iban-bic-validator). A domain with no mail route is never charged.
How to use
- In the Apify Console. Open the actor page and click Start — the
peoplefield is already pre-filled with a working example. Results land in the run's dataset as soon as each item is found. - Via the API. Call it directly with a POST request — no Console needed once you have an API token:
curl "https://api.apify.com/v2/acts/accountable_eel~email-pattern-finder/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \-X POST \-H "Content-Type: application/json" \-d '{"people":["Jane Doe, acme.com"]}'
- On a schedule. Save this actor as an Apify Task with the input you want, then add a Schedule (hourly, daily, weekly) so it runs on its own — no server of your own required.
- Paste one person per line as
First Last, domain.com(an@also works instead of the comma). A first and last name are both required — a single name (a mononym, or a first-name-only lead) doesn't have enough signal to rank patterns against and comes backBAD_FORMAT. - Press Start. Each line becomes one dataset row, tagged
found: trueorfound: false. - Use
mostLikelyEmailas your first guess, or take the wholecandidateEmailslist into a separate deliverability check (this portfolio's ownemail-deliverability-check, or your own SMTP-capable verifier) before sending anything. - Export the dataset as CSV/JSON, or pull it via the API —
onlyFoundandcolumns(see the integrations section below) let you trim the response before it lands in your table.
Input
{"people": ["Jane Doe, acme.com"]}
One per line: "First Last, domain.com". A ranked set of likely email address candidates is generated for each — confirmed only at the mail-route level (the domain accepts mail), never mailbox-verified. Accepted formats: Jane Doe, acme.com, Jane Doe @ acme.com.
Sample output
| query | found | status | firstName | lastName | domain | hasMailRoute | mostLikelyEmail | mostLikelyPattern | candidateEmails | candidateCount | mailboxVerified | scrapedAt |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Jane Doe, google.com | true | OK | Jane | Doe | google.com | true | jane.doe@google.com | first.last | ["jane.doe@google.com","jane@google.com","janedoe@google.com","jdoe@google.com","jane_doe@google.com","doe.jane@google.com","doejane@google.com","doe@google.com"] | 8 | false | 2026-08-31T06:30:27.572Z |
A miss looks like: {"query": "Not A Real Domain, thisdomaindoesnotexist12345zz.com", "found": false, "status": "NOT_FOUND", "message": "This domain has no mail route (no MX or A record) — it can't receive email, so no pattern was generated.", "scrapedAt": "2026-08-24T16:54:25.233Z"} — no charge, one row.
Use it from Clay, n8n, Make, or an AI agent
This actor runs synchronously over plain HTTP — call it directly from a script, a workflow tool, or an AI agent, no Apify Console needed once you have an API token.
curl "https://api.apify.com/v2/acts/accountable_eel~email-pattern-finder/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \-X POST \-H "Content-Type: application/json" \-d '{"people":["Jane Doe, acme.com"]}'
n8n. Add an HTTP Request node: Method POST, URL https://api.apify.com/v2/acts/accountable_eel~email-pattern-finder/run-sync-get-dataset-items?token=<YOUR_TOKEN>, Body Content Type JSON, JSON Body {"people":["Jane Doe, acme.com"]} (swap in an expression from an earlier node for a real value).
Clay. Add an "HTTP API" column: Method POST, URL https://api.apify.com/v2/acts/accountable_eel~email-pattern-finder/run-sync-get-dataset-items?token=<YOUR_TOKEN>, Body {"people":["{{person + domain}}"]}, mapping the row's person + domain into the people array.
MCP. In Claude, Cursor, or any MCP client with the Apify MCP server, ask for "Email Pattern Finder | Apify" — the agent will find and run this actor.
Tips
- Feed
mostLikelyEmailalone into a downstream deliverability check first — it's right often enough (first.last@and a bare first name are the two most common corporate defaults) to be worth checking before spending on the full candidate list. - Use
columnsto request onlymostLikelyEmailif you don't need the full ranked list — it trims the response without changing what you're charged. - A domain with no MX or A record is a strong signal the domain itself is dead or was typed wrong — worth double-checking the source data before assuming the person doesn't exist.
- This actor does not detect which pattern a specific company actually uses from known examples — it ranks by general frequency across companies. If you already have one or two confirmed real addresses at a target company, that's stronger evidence of their actual convention than this actor's ranking.
vs. alternatives
For a one-off guess, most people just type first.last@company.com by hand. This actor exists for the batch case and the honesty guarantee — a whole list in, a dataset out, with the mail-route check and pattern ranking already done, and nothing billed for a dead domain.
| What it costs | What you get | Trade-off | |
|---|---|---|---|
This actor (email-pattern-finder) | $0.004 per resolved row (FREE tier), $0.00005 actor start, nothing for a dead domain | Ranked candidate emails plus a confirmed mail-route check, per person | Never claims mailbox-level verification — pair with a deliverability check before sending. |
| A commercial email-finder platform | $0.03–$0.10+ per lookup in credits, often with a monthly seat | Pattern-plus-verification in one step, sometimes with a confidence score from a proprietary database of confirmed hits | Pricier per row, usually bundled into a broader enrichment seat rather than callable as one column. |
| Guessing by hand | Free, your time | The same first.last@ default most people reach for anyway | No batch mode, no mail-route check — you find out a domain is dead only when your email bounces. |
Prices for third-party tools are their published list prices as of August 2026 and are not tracked here — check the vendor before relying on the comparison.
FAQ
Does this confirm a specific email address is real?
No — it confirms the domain can receive mail and ranks candidate addresses by how common each pattern is. Confirming one specific mailbox exists requires an SMTP probe, which is blocked on this actor's runtime (and most cloud platforms) to prevent spam abuse. mailboxVerified is always false.
What happens when a domain can't receive mail at all?
It's a clean miss: found: false, status: "NOT_FOUND", and you're never charged. No candidates are generated for a domain that can't receive mail — there'd be nothing honest to guess at.
Why do I need both a first and last name?
The ranked pattern list (first.last, flast, last.first, and the rest) needs both parts to build most of its candidates. A single name doesn't carry enough signal, so it comes back BAD_FORMAT rather than a degraded guess.
Is this cached, or a live check every run? Live. Every row runs a fresh MX/A-record check when the actor executes — there's no stored snapshot from a previous run.
Can this detect the actual pattern a specific company uses, not just a general guess? Not currently — it ranks by general cross-company frequency. If you already have a couple of confirmed real addresses at the target company, that's stronger signal than this actor's ranking and should take priority.
Does this actor use a proxy? No — the only network call is a DNS-over-HTTPS query to Cloudflare's public resolver, not a scrape of any target site, so there's no anti-bot layer to route around.
Can I schedule this to run automatically, or call it from an AI agent? Yes to both. Set up an Apify schedule for recurring lead-list enrichment, or call it via the Apify API from a script or n8n/Make workflow. It's also discoverable through the Apify MCP server, so an AI agent (Claude, Cursor, or any MCP client) can find and run it directly by name — see the integrations section above.
Related actors
- Email Deliverability Check — mail route, disposable-domain and role-address flags, and provider fingerprint for a specific email address (run this actor's candidates through it before sending).
- Domain RDAP Lookup — registrar, registration and expiry dates for the same domains.
- Company Domain Enrichment — multi-source company intelligence fan-out from a single domain.