EmailGuesser
Email permutation generator and email address guesser for OSINT
Turn a name, username, birth year, DOB, location and domain into a ranked list of the email addresses a person most likely uses, as JSON, CSV or plain text. Offline, zero dependencies, pure Python.
Quick start · Inputs · CLI · Python API · Output · FAQ · License
See it in action
emailguesser --first John --last Doe --year 1990 --domain gmail.com --limit 6 --category name
| Rank | Pattern | Score | |
|---|---|---|---|
| 1 | john.doe@gmail.com |
{first}.{last} |
0.95 |
| 2 | jdoe@gmail.com |
{first_initial}{last} |
0.90 |
| 3 | johndoe@gmail.com |
{first}{last} |
0.85 |
| 4 | j.doe@gmail.com |
{first_initial}.{last} |
0.80 |
| 5 | doe.john@gmail.com |
{last}.{first} |
0.60 |
| 6 | doej@gmail.com |
{last}{first_initial} |
0.60 |
The tool prints the same data as JSON by default, and as JSONL, CSV or a plain list of addresses on request (see output formats).
Why EmailGuesser
People pick email addresses from a small set of habits: first.last, flast, firstlast, a nickname plus a birth year. EmailGuesser encodes those habits as a pattern table, applies them to the details you supply, and ranks the results so the most probable addresses come first.
- One tool, many formats. Use it from the terminal, from a script, or as a Python library; emit JSON, JSONL, CSV or a plain address list.
- Private by design. No accounts, no API keys, no network calls. Everything runs on your machine.
- Tuned for real behaviour. Company domains favour
first.last; free-mail domains favour names with years, dates and usernames. A known address teaches the tool a company's format. - Easy to extend. Patterns, scores, nicknames and default domains live in small, readable files.
Features
- Hundreds of email format permutations from name, username, year, DOB, location and domain.
- Covers every login pattern from NAMINT, with and without number suffixes (checked by a test).
- Names handled properly: middle names and initials, multi-word and hyphenated names, apostrophes, accents (
José Müllerbecomesjose.muller). - Nickname aware:
Robertalso triesbob,rob,bobby; add your own with--alias. - Date-of-birth aware: suffixes such as
1990,90,1405,140590,14051990. - Username aware: repeatable
--username, with separator variants (j_doe,j.doe,jdoe). - Location aware: your city and country become tokens; the country code also pulls in regional providers (
yahoo.co.in,web.de,mail.ru). - Learns a company format: pass a known address with
--known-emailand matching candidates are ranked to the top. - Custom or default domains: your company domain, or Gmail, Outlook, Yahoo and more.
- Ranked output: every address has a 0 to 1
score, apatternid and acategory. - Batch mode: run a whole JSON, JSONL or CSV file of people in one call.
- Validated and de-duplicated local parts, with optional Gmail dot/plus folding and a per-domain cap.
- Cross-platform: Windows, macOS and Linux, Python 3.9+.
Common use cases
- OSINT and investigations: build candidate addresses to check with breach-lookup, account-discovery or search tools you are authorised to use.
- Sales and recruiting outreach: guess a work email from a name and company domain, or learn the format from one known colleague.
- Penetration testing and red teaming: build target lists for authorised phishing simulations and social-engineering assessments.
- Self-audit and account recovery: work out which address you might have signed up with.
EmailGuesser only generates guesses. It does not check that an address exists. See the FAQ.
How it works
flowchart LR
A[Your inputs<br/>name, username, year,<br/>DOB, location, domain] --> B[Normalise<br/>accents, hyphens,<br/>nicknames]
B --> C[Build tokens<br/>first, f, last, l,<br/>1990, 90, 1405 ...]
C --> D[Apply pattern table<br/>skip patterns with<br/>missing tokens]
D --> E[Validate and<br/>de-duplicate]
E --> F[Score, sort<br/>and limit]
F --> G[JSON / CSV / TXT]
Installation
Requires Python 3.9 or newer.
pip install emailguesser
For non-Latin names (Cyrillic, Greek, Arabic, CJK), install the optional transliteration extra:
pip install "emailguesser[translit]"
Or clone and run without installing:
git clone https://github.com/OSINTVerseHQ/EmailGuesser.git
cd EmailGuesser
python -m emailguesser --help
After pip install, the emailguesser command is available in your terminal.
Quick start
1. Guess a work email from a name and company domain
emailguesser --first John --last Doe --domain example.com --limit 5 --pretty
2. Learn a company's format from one known address
emailguesser --first Jane --last Smith --known-email "Bob Jones <bjones@acme.com>" --format txt
3. Use everything you know
emailguesser --first John --middle Michael --last Doe --username jdoe \
--year 1990 --dob 1990-05-14 --location "Mumbai, India" \
--domain example.com --domain gmail.com --pretty
4. Get a plain list to pipe into another tool
emailguesser --first John --last Doe --year 1990 --min-score 0.5 --limit 0 --format txt
5. Read input from a JSON file, or run many people at once
emailguesser --input request.json --pretty
emailguesser --batch people.csv --format csv -o candidates.csv
people.csv just needs headers matching the input fields, for example first,last,domain.
6. Generate here, verify elsewhere
EmailGuesser never touches the network, so pair it with a verification step you are authorised to run. The plain list format pipes cleanly into other tools:
emailguesser --first John --last Doe --domain acme.com --format txt --limit 0 > candidates.txt
# then check candidates.txt with a breach-lookup, account-discovery or
# email-verification tool, for example the OSINTverse API (https://osintverse.com).
Input fields
| Field | CLI flag | Required | Notes |
|---|---|---|---|
| First name | --first |
With last name, unless a username is given | Multi-word names work (Mary Ann) |
| Middle name | --middle |
No | Enables middle-name and middle-initial patterns |
| Last name | --last |
With first name, unless a username is given | Hyphenated and multi-word names work (Van Der Berg) |
| Username | --username |
No | Repeatable. A pasted email address is reduced to its local part |
| Alias / nickname | --alias |
No | Repeatable extra first-name form (billg, jdoe) |
| Known email | --known-email |
No | "Name <local@domain>", Name:local@domain, or just local@domain. Learns the domain's format |
| Year | --year |
No | 4 digits (1900 to 2100) |
| Date of birth | --dob, --dob-format dmy|mdy|ymd |
No | 1990-05-14 is read as ISO; other formats follow --dob-format (default dmy) |
| Location | --location |
No | "City, Country" or "City, CC". The country code also adds regional providers |
| Domain | --domain |
No | Repeat or comma-separate. If omitted, popular free-mail providers are used |
You need at least a first and last name, or a username.
Command-line reference
| Option | Description |
|---|---|
--format json|jsonl|txt|csv |
Output format. Default json |
--limit N |
Maximum results. Default 50. Use 0 for unlimited |
--max-per-domain N |
Cap results per domain (0 = no cap) |
--min-score X |
Drop results scoring below X (0 to 1) |
--category C |
Only include one pattern category: name, personal, username, location. Repeatable |
--gmail-dots |
Treat Gmail dot and +tag variants as the same address when de-duplicating |
--input FILE |
Read input fields (and options) from a JSON file. - reads stdin. CLI flags override |
--batch FILE |
Run many inputs from a JSON array, JSONL or CSV file. - reads stdin |
--explain |
Add a per-address score breakdown (json/jsonl output) |
--pack FILE |
Custom pattern pack (JSON/TOML) adding patterns, nicknames and domains |
--calibration FILE |
Score→probability table (see below) adding a probability field |
--provider-aware |
(online) Detect each domain's mail provider by MX; fold dot-variants on Google-hosted domains |
--verify mx|smtp |
(online) Check deliverability. Needs the [verify] extra. Authorised use only |
--drop-undeliverable |
With --verify, drop addresses that are clearly undeliverable |
-o, --output FILE |
Write output to a file instead of stdout |
--pretty |
Indent JSON output |
--version |
Print the version and exit |
Errors go to stderr as {"error": "..."} and the exit code is 2.
Learn a company format, verify, explain
# Learn acme.com's convention from one known colleague, then rank Jane's address
emailguesser --first Jane --last Smith --known-email "Bob Jones <bjones@acme.com>" --format txt
# (online) keep only addresses whose domain can receive mail
emailguesser --first Jane --last Smith --domain acme.com --verify mx --drop-undeliverable
# see exactly why each address scored what it did
emailguesser --first John --last Doe --domain acme.com --explain --pretty
Verification and provider detection are opt-in, make network requests, and need
the extra: pip install "emailguesser[verify]". Use them only against domains
you are authorised to probe.
Calibrated probabilities
A score ranks candidates; it is not itself the chance an address is real. Fit a
score→probability table from your own verified data and apply it:
python -m emailguesser.calibrate your_data.csv -o table.json # needs a true_email column
emailguesser --first John --last Doe --calibration table.json # adds a "probability"
Custom pattern packs
Add patterns, nicknames and domains without editing source (see
examples/pack.example.json):
emailguesser --first John --last Doe --pack mypack.json
Run it anywhere
pipx install emailguesser # isolated CLI
docker run --rm emailguesser --first John --last Doe --domain acme.com
python scripts/build_pyz.py && python dist/emailguesser.pyz --help # single file, no install
A static, backend-free browser version lives in web/ (runs the
generator in-browser via Pyodide).
Python API
from emailguesser import generate
result = generate(
first_name="John",
middle_name="Michael",
last_name="Doe",
usernames=["jdoe"],
aliases=["johnny"],
year="1990",
dob="1990-05-14",
location="Mumbai, India",
domains=["example.com", "gmail.com"],
known_emails=["Bob Jones <bjones@example.com>"],
limit=20,
max_per_domain=0,
)
for item in result["emails"]:
print(item["score"], item["email"])
generate() also accepts a dictionary or an Inputs object as its first argument, plus the CLI options as keyword arguments: limit, min_score, max_per_domain, categories, gmail_dots, dob_format. It returns a plain, JSON-serialisable dict. To render it, use emailguesser.output.render(result, "csv") or render_batch([...], "jsonl").
Output formats
- json (default): the full result object below.
- jsonl: one JSON email object per line, ready for
jqand line-based tools. - txt: one email address per line, highest score first.
- csv:
email,local_part,domain,pattern,category,scorewith a header row.
In batch mode, jsonl and csv gain a leading query column identifying which input produced each row.
JSON output shape
{
"input": {
"first_name": "John", "middle_name": "", "last_name": "Doe",
"usernames": [], "aliases": [], "year": "1990", "dob": "",
"location": {}, "domains": ["gmail.com"], "known_emails": []
},
"meta": {
"count": 6,
"total_candidates": 251,
"truncated": true,
"limit": 6,
"min_score": 0.0,
"max_per_domain": 0,
"domains_used": ["gmail.com"],
"generated_at": "2026-10-18T09:00:00Z",
"warnings": ["no middle name given: middle-name patterns skipped"]
},
"emails": [
{"email": "john.doe@gmail.com", "local_part": "john.doe", "domain": "gmail.com",
"pattern": "{first}.{last}", "category": "name", "score": 0.95}
]
}
| Field | Meaning |
|---|---|
emails[].pattern |
The pattern that produced the address, such as {first}.{last} |
emails[].category |
name, personal, username or location |
emails[].score |
Likelihood estimate from 0 to 1. Results are sorted high to low |
meta.total_candidates |
Addresses found before --limit was applied |
meta.warnings |
Skipped patterns and notes about your input |
How scoring works
score = pattern popularity x domain-type multiplier x domain popularity (capped at 1)
- Pattern popularity:
first.lastranks abovelastf, which ranks abovefirst-m-last. - Domain type: company domains favour plain name patterns; free-mail domains favour name plus number, date and username patterns.
- Name variants: alternative spellings of multi-word names and guessed nicknames are down-weighted.
- Known format: a candidate matching a
--known-emailformat for that domain is boosted to the top.
All weights live in emailguesser/patterns.py and emailguesser/domains.py. After any change, run the calibration harness to see whether ranking of real addresses improved:
python tests/calibration.py
FAQ
Does EmailGuesser check whether an email address exists? No. It is offline and generation-only and never contacts a mail server.
How is it different from NAMINT? NAMINT is a browser-based tool that builds name and login search patterns. EmailGuesser is a Python command-line tool and library focused on email addresses. It covers all NAMINT login patterns and adds nicknames, usernames, date-of-birth, location, known-format inference, scoring, de-duplication and JSON/CSV/TXT output.
Which providers are used by default?
Gmail, Outlook, Yahoo, Hotmail, iCloud, Proton, Live, AOL, MSN and GMX. A location country code adds regional providers. Passing --domain replaces this list.
Why so many Gmail variants?
Gmail ignores dots in the local part. Pass --gmail-dots to collapse j.doe@gmail.com and jdoe@gmail.com into one.
Does it support non-English names?
Accents are converted to ASCII out of the box. For non-Latin scripts, install emailguesser[translit], which transliterates Cyrillic, Greek, Arabic and CJK.
Can I add my own patterns, nicknames or domains?
Yes. Edit emailguesser/patterns.py, emailguesser/nicknames.py or DEFAULT_DOMAINS in emailguesser/domains.py.
Responsible use
EmailGuesser is meant for OSINT research, authorised security testing, outreach that follows the law, and personal use. Do not use it for harassment, stalking, spam or any unlawful activity. You are responsible for complying with privacy, anti-spam and data-protection laws (such as GDPR and CAN-SPAM) where you operate.
Development and tests
git clone https://github.com/OSINTVerseHQ/EmailGuesser.git
cd EmailGuesser
pip install -e ".[dev]"
ruff check emailguesser tests
ruff format --check emailguesser tests
python -m pytest
emailguesser/
normalize.py name, username and domain cleaning (+ transliteration hook)
nicknames.py bundled nickname table
tokens.py date parsing and name/date tokens
patterns.py pattern table and scores
domains.py default/regional domains and location parsing
known_format.py parse a known-email reference
fields.py input-field aliases
validate.py local-part validation
generator.py core engine and public generate() API
output.py json / jsonl / txt / csv rendering
cli.py command-line interface
tests/ pytest suite + calibration harness
Contributing
Issues and pull requests are welcome. Good first contributions: new patterns for naming conventions you have seen in the wild (use the "new pattern" issue template), nicknames, better scores backed by data, and extra tests. Please run ruff check, ruff format --check and python -m pytest before opening a pull request.
License and attribution
EmailGuesser is released under the MIT License. You are free to use, copy, modify and redistribute it, including commercially, as long as you keep the copyright notice and license text with your copy.
If you use EmailGuesser in a project, report or product, please credit it:
Email candidates generated with EmailGuesser by OSINTverse.
GitHub's Cite this repository button uses CITATION.cff.
Credits
Pattern ideas were inspired by seintpl/NAMINT (MIT License).
Keywords: email permutator, email generator, email guesser, email finder, email format finder, email pattern generator, email combinations, email permutations, OSINT tool, username to email, name to email, find email by name, Python OSINT, reconnaissance, penetration testing, red team, JSON, CSV.
Metadata
Release files for emailguesser 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| emailguesser-0.3.0.tar.gz | 51.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| emailguesser-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 92.4 kB
Release files / emailguesser-0.3.0.tar.gz
| Download URL | emailguesser-0.3.0.tar.gz |
|---|---|
| Size | 51.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4d19507019886a5d0cf5710a6ea0a0ee11ad6a3dc2928c21be31cd5e3e3a6675
|
|
BLAKE2b-256 checksum How to use checksums |
751baafb274b5aeaf2dad2c0dbabd77a8f15f2270a6c8ff9690adbb099be6e59
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 18, 2026.
Transparency logRelease files / emailguesser-0.3.0-py3-none-any.whl
| Download URL | emailguesser-0.3.0-py3-none-any.whl |
|---|---|
| Size | 41.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b05a02a70687cd3d66ffd227a6deb125c4c582061a4b0224facdce948908c12d
|
|
BLAKE2b-256 checksum How to use checksums |
d99c6236b8082b6ecd3e6676543da2d3a68ff1441256f0c489e8c1e562024bc6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 18, 2026.
Transparency log