Most email-format lookups answer from a database: addresses collected somewhere, grouped by domain, the most common shape reported. The question this guide answers is different — what format does a company use, according to evidence the company itself produced, and how sure can you be.
Why commits carry the answer
Every Git commit records an author name and an author email, and GitHub's own documentation describes setting that email with git config user.email — to a GitHub-provided noreply address or to any address. Many engineers commit to their employer's repositories with their work address. A commit by "Ana Perez" from ana.perez@company.com is one observation of first.last.
Most addresses are not evidence. Across 8,265 distinct addresses in the repositories of 46 companies, the split was:
| Address kind | Share of 8,265 | Used as evidence |
|---|---|---|
| The company's own domain | 29.2% | Yes |
| GitHub noreply | 25.1% | No |
| Personal (gmail, outlook…) | 23.1% | No |
| Other companies' domains | 18.5% | No |
How a pattern is matched
The Company Email Pattern Finder takes a domain, finds the GitHub organization behind it, and reads the latest commits of its most recently updated repositories — by default 5 repositories × 300 commits, skipping forks and archived repositories. By default it uses the git protocol to fetch commit metadata only, about 300 commits per repository in a second, without spending API quota.
Each company-domain address is compared with its author's name and scored against the candidate shapes: first.last, first, flast, firstlast, firstl, first-last and the rest. The organization match is reported with its reasons; confirmed means the organization's commits contain addresses on the requested domain, which held for 38 of 44.
How confidence is computed
The README documents the rule in full:
- An address that matches its author's name counts 1.
- An address that only has the shape of a pattern, with no name to confirm it, counts 0.3.
- A named address that matches no pattern counts 0.5 against.
- Confidence is the pattern's share of the evidence, times a saturation by number of matches — 0.5 for one, 0.75 for two, 0.88 for three, capped at 0.99 — and halved when the domain has no MX.
Ties are flagged with patternTie, and the alternatives ship with their own confidence. A row reading first.last at 0.77 with first at 0.09 behind it is a different statement from a lone 0.10 guess.
How well it works, measured on 46 domains
On 1 October 2026, 46 company domains — US, EU and Latin American tech companies, chosen before measuring — were run at 5 repositories × 300 commits, 148,821 commits in all:
| Result | Count |
|---|---|
| GitHub organization found | 44 of 46 (95.7%) |
| Pattern measured from commits | 38 of 44 (86.4%) |
| Confidence 0.75 or higher | 22 of 44 (50%) |
| Confidence 0.5 or higher | 28 of 44 (63.6%) |
| Latin American companies, pattern measured | 5 of 8 |
The winning patterns were first.last 22 times, first 7, flast 6, and firstlast, firstl and first-last once each. Assuming first.last would have been wrong for 16 of 38. Depth helps less than expected: one repository found a pattern for 32 of 44 companies, three for 36, five still 36.
Why it stops at the MX record
RFC 5321 makes the MX lookup the first step of delivering mail, and the Actor performs that lookup to report mxValid, the hosts and the provider. It goes no further. Per-address verification means opening an SMTP session and asking about a recipient; RFC 5321 already lets servers disable the VRFY command, so verifiers probe with RCPT TO instead, and that probing is what gets sending IPs blocklisted. catchAll is therefore always null.
One nuance the README's phrasing glosses: RFC 5321 treats a domain with no MX records as having an implicit MX pointing at the domain itself. mxValid: false means mail is unlikely to be configured, not that delivery is impossible. The wider limits of reading infrastructure from DNS are in what a nameserver can and cannot tell you, and why this stated-versus-inferred line matters for founder data is in what is stated and what is inferred.
The GitHub rate limit decides run size
GitHub's REST API allows 60 requests an hour without authentication and 5,000 with a personal access token. That translates to about 15 domains per run without a token and about 500 an hour with one. A fine-grained token with no permissions is enough, since only public data is read, and the token is never logged.
{
"domains": ["vercel.com", "mercadolibre.com", "jetbrains.com"],
"githubToken": "github_pat_…",
"maxReposPerOrg": 3
}When the limit is reached the run ends successfully, delivers what it finished, lists the domains it did not process in an error row and does not charge them. A 20-domain run without a token on 2 October 2026 hit the limit after 17. The Actor does not rotate IPs to obtain a fresh quota: an earlier build did so once after a secondary-limit 403, and that was changed before publication.
What GitHub's own rules say
github.com/robots.txt, fetched on 10 October 2026, disallows web paths such as /*/*/commits/, /*.git$ and */.git/ for all user agents. The Actor uses the API and the git protocol's fetch endpoints, not the web commit pages; whether that satisfies the spirit of those rules is a judgement the robots.txt guide frames rather than settles.
Section 7 of GitHub's Acceptable Use Policies says information from the service may not be used for spamming, "including for the purposes of sending unsolicited emails to users or selling personal information, such as to recruiters, headhunters, and job boards". Section H of the Terms of Service repeats that for the API and adds that API tokens may not be shared to exceed rate limits. The default row contains no individual address for that reason; the evidence addresses appear only with includeSamples.
