Work Email Finder - Name + Domain to Email, Pattern & Score avatar

Work Email Finder - Name + Domain to Email, Pattern & Score

Pricing

$2.00 / 1,000 per person resolveds

Go to Apify Store
Work Email Finder - Name + Domain to Email, Pattern & Score

Work Email Finder - Name + Domain to Email, Pattern & Score

Give it a first name, last name and company domain; get back ranked work-email candidates. Each guess is built from REAL addresses observed at that domain (GitHub, npm, team pages) plus MX/SPF/DMARC, so the confidence score is earned, not invented. Source URLs on every row. No fake SMTP checks.

Pricing

$2.00 / 1,000 per person resolveds

Rating

0.0

(0)

Developer

Scrapers Delight

Scrapers Delight

Maintained by Community

Actor stats

0

Bookmarked

3

Total users

2

Monthly active users

a day ago

Last modified

Share

πŸ“§ Work Email Finder β€” Name + Domain β†’ Email, Pattern & Score

Give it a first name, a last name and a company domain. Get back a ranked ladder of work-email candidates β€” where the pattern was decoded from REAL addresses the company already published, with the source URLs on every row so you can check the answer yourself.

Most email finders hand you first.last@company.com and a confidence number they will not explain. On the 16 domains where this actor found decodable evidence in its benchmark run, 8 of them do not use first.last β€” Twilio, Cloudflare, HubSpot, Jones Day and Sidley use {f}{last}, McKinsey uses {first}_{last}, Stripe leans {first}{last}. A ranker that defaults to first.last is wrong half the time and never tells you.

This one shows its work:

What you also getWhy it matters
evidenceSamples[]The actual Name β†’ address pairs we found, each with the URL it came from
patternVotes + patternAgreementHow the domain's addresses split across patterns β€” 100% or 43%?
candidates[]The full ranked ladder, because on a split domain the answer is often #2
mailDomainmwe.com's people are reachable at mcdermottlaw.com β€” appending the input domain returns dead addresses
MX / SPF / DMARC / DKIM / BIMI / RDAPThe domain's whole public mail posture, on every row
blockedSources[]When a source blocked us we say so β€” "blocked" is never reported as "nothing found"

πŸ” What it does

  1. DNS tier (always runs, direct, never proxied). MX, SPF, DMARC, BIMI and 18 DKIM selectors over DNS-over-HTTPS, plus RDAP registration facts. This tier alone guarantees every person gets a row.
  2. Evidence tier (public sources only). The company's GitHub org commits (author name + address), npm maintainers/contributors, PyPI metadata, and the company's own website β€” homepage, then robots.txt β†’ sitemap-discovered team / people / contact pages, plus /.well-known/security.txt.
  3. Decode, don't guess. Every observed Name β†’ address pair is tested against 20 pattern templates. A pattern only earns a vote if rendering it with that name reproduces the local part exactly. Michael Broshi β†’ mbroshi votes {f}{last}; David Brownman β†’ xavdid votes for nothing, and is reported as undecodable rather than forced into a bucket.
  4. Rank and score. Confidence is agreement Γ— a sample-size factor, so a domain that splits 43% five ways cannot come back "high".

Sources verified live (2026-09-02/03, direct and through the Apify proxy)

SourceRequestResult
DNS-over-HTTPSGET cloudflare-dns.com/dns-query?name=stripe.com&type=MX (accept: application/dns-json)HTTP 200, 517 bytes, 10 aspmx.l.google.com.
DMARCGET .../dns-query?name=_dmarc.stripe.com&type=TXTHTTP 200, v=DMARC1; p=reject; ... rua=mailto:dmarc-reports@stripe.com
RDAPGET rdap.org/domain/stripe.com (follows redirect)HTTP 200, 2,834 bytes, registration 1995-09-12T04:00:00Z
GitHubGET api.github.com/repos/stripe/stripe-node/commits?per_page=100HTTP 200, 486,440 bytes, 56/100 commits from @stripe.com
npmGET registry.npmjs.org/-/v1/search?text=stripe&size=20HTTP 200, 25,654 bytes, maintainer addresses at the domain
WebsiteGET www.mwe.com/people/HTTP 200, 369,600 bytes, 11 addresses, names recoverable from embedded JSON

πŸ“₯ Input

FieldTypeDefaultWhat it does
peoplearray (JSON)β€”The list to resolve: [{ "firstName":"Michael", "lastName":"Broshi", "domain":"stripe.com" }]. fullName works instead of first/last; companyDomain / website work instead of domain; a full URL is reduced to its host.
personLinesarray (strings)[]Paste-friendly alternative: Michael Broshi, stripe.com or Michael, Broshi, stripe.com.
firstName / lastName / companyDomainstringβ€”Convenience path for one person.
useGithubbooleantrueRead the company's public GitHub org commits. The richest source on technology companies; contributes nothing on a domain with no org.
useRegistriesbooleantrueRead npm + PyPI package metadata.
useWebsitebooleantrueRead the company site: homepage β†’ sitemap-discovered team/people/contact pages β†’ security.txt. This is the tier that works on non-technology companies.
maxWebsitePagesinteger8Discovered pages to read per domain, on top of the homepage (0–30).
maxGithubReposinteger3Most-recently-pushed public repos to read 100 commits from (0–10).
githubTokenstring (secret)β€”Optional read-only GitHub PAT. Unauthenticated GitHub allows 60 requests/hour per IP; a token raises it to 5,000. No scopes needed.
maxCandidatesinteger8Length of the ranked candidates[] ladder (1–20).
maxSecondsPerDomaininteger75Hard evidence budget per domain. When it expires the row still ships from what was gathered plus DNS/RDAP, and blockedSources says so.
maxPeopleinteger1000Safety cap on people per run (0 = no cap, 5,000 hard limit).
proxyConfigurationobject{ "useApifyProxy": true }Applies to GitHub / npm / PyPI / websites. DNS always runs direct. Switch to RESIDENTIAL if a company site refuses datacenter IPs.
{
"people": [
{ "firstName": "Michael", "lastName": "Broshi", "domain": "stripe.com" },
{ "firstName": "Jeff", "lastName": "Lawson", "domain": "twilio.com" }
],
"maxWebsitePages": 8,
"maxGithubRepos": 3
}

Evidence is cached per domain, so 50 people at one company cost barely more work than the first.


πŸ“€ Output β€” one row per person, 70 fields

Identity + answer

FieldTypeDescription
firstName, lastName, fullNamestringEchoed from the input, so the row joins back to your CRM.
companyDomainstringThe domain you supplied.
inputIndexintegerPosition in your input list.
emailstringThe top-ranked candidate.
emailPatternstringThe pattern that produced it, e.g. {f}{last}.
confidencenumber0–0.95. Driven by pattern agreement, damped by sample size.
confidenceLabelstringhigh β‰₯0.75 Β· medium β‰₯0.50 Β· low β‰₯0.30 Β· very-low below.
confidenceReasonstringPlain English: what we proved and what we did not.
matchTypestringobserved-direct (we found this person's actual published address) Β· pattern-inferred Β· provider-heuristic (no evidence β€” generic prior).
candidates[]array{ email, pattern, score, votes }, best first.
candidateCountintegerLength of that ladder.

The audit trail (this is the product)

FieldTypeDescription
evidenceCountintegerReal addresses observed at this company's mail domain.
evidenceDecodedCountintegerHow many of those we could tie to a named person and decode into a pattern.
patternVotesobjectpattern β†’ vote count. An ambiguous pair splits its vote.
patternAgreementnumberTop pattern's share of the vote. 1 = unanimous, 0.43 = a five-way split.
evidenceSamples[]arrayUp to 12 { name, email, pattern, source, url, nameTrust, nameOrderAmbiguous } β€” the receipts.
evidenceSources[]arraygithub-commit, npm-package, npm-maintainer, pypi, website.
evidenceUrls[]arrayEvery URL we read for this domain. Open them and check us.
patternSourcestringdecoded-from-observed-addresses Β· structural-shape-of-observed-addresses Β· generic-prior.
blockedSources[]arraySources that refused us (anti-bot interstitial, HTTP 403, GitHub rate limit, budget expiry).
websitePagesReadintegerCompany pages actually read.

Where the mail actually lives

FieldTypeDescription
mailDomainstringThe domain the addresses are really on.
mailDomainDiffersFromInputbooleantrue when it is not the domain you supplied.
mailDomainBasisstringWhy we picked it.
webDomainstringHost the company website resolved to after redirects.
hasMx, mxRecords[], mxHostCountbool / array / intMX hosts with priorities.
mailProvider, mailProviderBasisstringGoogle Workspace, Microsoft 365, Proofpoint, Mimecast, Zoho, Proton, Fastmail, Cloudflare Email Routing and ~20 more β€” plus the exact MX host or SPF include that identified it.
spfRecord, spfIncludes[], spfPolicy, hasSpfstring / arrayFull SPF record, its include: list, and the all qualifier (-all, ~all, …).
dmarcRecord, dmarcPolicy, dmarcReportAddress, hasDmarcstring / boolDMARC record, p= policy, and the rua= reporting mailbox.
dkimSelectorsFound[]arrayWhich of 18 common DKIM selectors publish a key.
bimiRecord, bimiLogoUrlstringBIMI record and logo, when present.
catchAllLikely, catchAllBasisbool / stringSee honest limits β€” for Google/Microsoft domains this says no verifier can tell a real mailbox from a fake one here.

Company + domain facts

FieldTypeDescription
domainCreatedDate, domainAgeDays, domainExpiryDatestring / intFrom RDAP.
domainStatus[], domainRegistrarId, domainRegistrararray / stringEPP statuses, IANA registrar ID and name.
companyNameFromRegistrystringRDAP registrant organisation. Redacted by ICANN privacy on effectively every gTLD β€” expect null.
companyWebsiteStatus, companyTitleint / stringHTTP status and <title> of the company homepage.
robotsDisallowsPeoplePathsbooleanWhether the site's robots.txt disallows people/team-shaped paths.
githubOrg, githubOrgUrl, githubPublicReposstring / intThe GitHub org we matched to this domain.
securityTxtContactstringContact: line from /.well-known/security.txt.
isRoleAddress, isFreeMailDomain, isDisposableDomainbooleanSanity flags on the chosen address and the mail domain.
roleAddressesFound[]arrayRole mailboxes seen at the domain (info@, press@, …).

Honesty fields

FieldTypeDescription
smtpVerifiedbooleanAlways false. See honest limits.
smtpVerificationAvailablebooleanAlways false.
verificationMethodstringExactly what produced this answer.
undeliverableReasonstringSet when the domain cannot receive mail (no MX, free-mail, disposable).
resolvedAt, sourcesQueried[], lookupDurationMsstring / array / intProvenance and cost of this domain's lookup.

πŸ“Š Measured β€” run QOb1MsFAxLfhsskMe, build 0.1.4, 2026-09-03

Not estimates. This is one real Apify run at 1,024 MB through the Apify proxy.

MetricValue
StatusSUCCEEDED
People resolved30 across 26 domains
Runtime644.8 s
chargedEventCounts{ "email-resolved": 30 } β€” billed == delivered
Fields per row70
Fields at 100% fill39
Fields at β‰₯50% fill64
Confidence bandshigh 9 Β· medium 4 Β· low 7 Β· very-low 10
Match typespattern-inferred 25 Β· provider-heuristic 5

Coverage β€” the number that matters, and it is not flattering

Domain groupAny public address foundAddress decoded to a pattern
Technology companies (11)11 / 1110 / 11
Non-technology companies (15)11 / 156 / 15
All 2622 / 2616 / 26

The 10 domains with no decodable evidence still shipped a full row β€” MX, SPF, DMARC, DKIM, RDAP and a ranked ladder β€” but flagged provider-heuristic / structural and scored very-low. That is the correct answer, not a failure. Read the section below before you buy.

What the evidence actually said

DomainAddresses seenDecodedAgreementTop patternConfidence
datadoghq.com2314100%{first}.{last}0.95
sentry.io2012100%{first}.{last}0.95
shopify.com2814100%{first}.{last}0.95
twilio.com229100%{f}{last}0.95
elastic.co136100%{first}.{last}0.85
hashicorp.com336100%{first}.{last}0.85
mckinsey.com94100%{first}_{last}0.85
vercel.com107100%{first}.{last}0.85
mwe.com β†’ mcdermottlaw.com10786%{f}{last}0.73
cloudflare.com451573%{f}{last}0.70
jonesday.com6475%{f}{last}0.64
kirkland.com7450%{first}.{last}0.43
sidley.com1091040%{f}{last}0.38
stripe.com95743%{first}{last}0.37
hubspot.com401100% (n=1){f}{last}0.35
ferguson.com11100% (n=1){first}.{last}0.35

Eight of these sixteen domains do not use first.last. That is the whole argument for this actor. And note Stripe and Sidley: a big pile of observed addresses with low agreement scores low, because the domain genuinely uses several conventions β€” the ladder in candidates[] is the answer there, not the top row.

mwe.com is the case that breaks naive tools. McDermott's website is mwe.com; its people's addresses are at mcdermottlaw.com. This run detected that, switched mailDomain, set mailDomainDiffersFromInput: true, and decoded 7 addresses at 86% agreement. A tool that appends the input domain returns undeliverable @mwe.com guesses.

Badge-risk preflight (timeout=300, 1,024 MB)

InputRunsResult
Prefill-only (what Apify's daily health test sends)3SUCCEEDED, 2 items each β€” 18.0 s / 30.0 s / 42.7 s
Empty {}2SUCCEEDED, 2 items each β€” 33.4 s / 75.4 s
Peak platform cost on any of those runsβ€”$0.006409

Fleet health monitor: PASS, 19.1 s, 2 items.


πŸ’΅ Pricing

Pay per event β€” $0.002 per person resolved ($2.00 per 1,000). One event, email-resolved. Both of Apify's auto-events (apify-default-dataset-item, apify-actor-start) are removed, so your bill shows only people you actually resolved.

  • Rows are shipped with Actor.pushData(rows, 'email-resolved'), which is budget-aware: delivered equals billed, and a buyer who hits their charge cap never keeps rows they did not pay for.
  • A person we can produce no candidate for is delivered free (pushed without the event).
  • Evidence is cached per domain, so the 50th person at a company costs the same as the second.

For comparison, measured from the Apify API on 2026-09-02: the largest actor in this lane charges $0.029 per email resolution (14.5Γ— this), and a pattern-finder in the same lane bills $0.008 per pattern tested β€” roughly $0.064 for one person, and you pay for every wrong guess. This actor bills once per person and hands you the whole ladder.


⚠️ Honest limits β€” read these before you buy

1. There is no SMTP verification here, and smtpVerified is hardcoded false forever. Outbound TCP port 25 is blocked on the Apify platform β€” measured 2026-09-02 from a real Apify run: MX hosts on :25 returned ETIMEDOUT in ~260 ms while smtp.gmail.com:587 answered with a live 220 banner from the same run. And even where port 25 is reachable, it lies: during recon a deliberately garbage mailbox, zzqqxx9988@stripe.com, got the same 250 2.1.5 OK from Google's MX as a real one. Google Workspace and Microsoft 365 host most B2B mail and accept every recipient at the gateway. Any product that calls those addresses "verified" is guessing with extra steps. We put that fact in catchAllBasis on every affected row instead.

2. Coverage is tech-skewed. Measured above: 10 of 11 technology domains decoded, 6 of 15 non-technology domains. GitHub commits are the single richest source and a plumbing distributor does not have a GitHub org. Non-tech domains fall back to the website tier, and if the company publishes no addresses at all you get provider-heuristic at very-low confidence. That is what cushmanwakefield.com, grainger.com, trane.com and wwgrainger.com returned in this run β€” a complete DNS row and an honest "we have no evidence about this domain."

3. A correct pattern is not a live mailbox. We prove the domain's convention. We do not prove the person still works there, that the mailbox exists, or that they do not use a nickname β€” observed in a run against the stripe/stripe-python repos: David Brownman β†’ xavdid@stripe.com and Zachary Chua β†’ zacchua@stripe.com. Both are reported pattern: null rather than guessed. confidenceReason says this on every row.

4. Some sites block us, and we say so rather than reporting "nothing found." Measured on this build: grainger.com returns HTTP 403 to the Apify container IP; mcdermottlaw.com (Imperva) served a _Incapsula_Resource interstitial to a datacenter IP, to an Apify RESIDENTIAL IP and to a plain home connection during testing β€” yet the same page returned 369,600 bytes of real content on other attempts, so this is IP reputation and rate, not a permanent wall. Those rows carry blockedSources[] naming the URL and the reason. Bring your own residential proxy via proxyConfiguration if a target site refuses Apify's ranges.

5. GitHub's unauthenticated rate limit is 60 requests/hour per IP (measured:

X-RateLimit-Limit: 60
). Large bulk runs should supply githubToken for 5,000/hour. When the limit is hit the actor degrades to the DNS + website tiers and records it in blockedSources β€” it never fails the run.

6. companyNameFromRegistry filled 0/30 in this run. ICANN privacy redacts the registrant organisation on essentially every gTLD. The field is kept because some registries do publish it; on .com/.org/.io expect null. Use companyTitle (86.7% fill) instead.

7. Name order from a web page is not evidence. Kirkland files Ken Au at /lawyers/a/au-ken, so proximity-derived names can be surname-first. When a local part decodes under both orderings the vote is split and both candidates appear on the ladder β€” which is why kirkland.com scores 0.43, not 0.85.


βš–οΈ Sources, robots and fair use

Every source this actor reads is public and unauthenticated: DNS records, RDAP registration data, GitHub's public API, npm and PyPI registry metadata, and the company's own public web pages. There is no login, no target-site cookie, no CAPTCHA solving, no named-crawler impersonation, and no LinkedIn scraping of any kind β€” LinkedIn discovery is the practice that ended Proxycurl, and this actor takes the name and domain from you instead.

The company-website tier reads robots.txt primarily to discover sitemaps, and the row reports robotsDisallowsPeoplePaths so you can see whether a given site's robots.txt disallows the people/team paths involved. Fleet policy is that a robots.txt Disallow is disclosed, not treated as a licence question the actor decides on your behalf β€” the compliance call is yours.

Output is personal work-contact data. Depending on where you and your recipients are (GDPR, CAN-SPAM, CASL, PECR), you may need a lawful basis to process or contact these people, and you are responsible for that. This actor is built for legitimate B2B outreach, CRM enrichment and deliverability research. Do not use it for spam, harassment, or to contact private individuals.