Skip to main content

EmailGuesser

Email permutation generator and email address guesser for OSINT

You have a name and a domain. You need the inbox. EmailGuesser takes what you know (name, username, birth year, DOB, location, domain) and turns it into a ranked shortlist of the email addresses that person most likely uses, as JSON, CSV or plain text. It runs offline, has no dependencies, and is pure Python. It does the guessing so you only have to check the few that matter.

CI Python 3.9+ License: MIT Dependencies: none Offline Output: JSON/CSV/TXT

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 Email 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

Guessing an email by hand means typing first.last, then flast, then giving up. Online permutators hand you 200 unranked combinations and no idea where to start. Paid finders charge per lookup and send your target's name to a third party.

EmailGuesser sits between the two. People pick addresses from a small set of habits, like first.last, flast, firstlast, or a nickname plus a birth year. EmailGuesser turns those habits into a scored pattern table, applies them to what you know, and ranks the results so the most likely addresses come first.

  • Ranked, not dumped. Every candidate carries a 0 to 1 score, so you check the top handful instead of the whole list, which matters when your verification step is rate-limited.
  • Private by design. No accounts, no API keys, no network calls. The name you type never leaves your machine.
  • Learns a company's format. Know one colleague's address? Pass it with --known-email and the right pattern is ranked to the top.
  • Tuned for real behaviour. Company domains favour first.last; free-mail domains favour names with years, dates and usernames.
  • One tool, many formats. Terminal, script or Python library; JSON, JSONL, CSV or a plain address list that pipes straight into the next tool.
  • Easy to extend. Patterns, scores, nicknames and domains live in small, readable files, or in a pack you load at runtime.

Features

  • Hundreds of email format permutations from name, username, year, DOB, location and domain.
  • Builds on every login pattern from NAMINT by The SEINT, with and without number suffixes. A test checks that all of them are still generated.
  • Names handled properly: middle names and initials, multi-word and hyphenated names, apostrophes, accents (José Müller becomes jose.muller).
  • Nickname aware: Robert also tries bob, 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-email and 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, a pattern id and a category.
  • 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: you have a subject's name and employer. Build a ranked candidate list to check with the breach-lookup, account-discovery or search tools you are authorised to use.
  • Sales and recruiting outreach: stop guessing work emails one at a time. Generate the likely address from a name and company domain, or learn the format from one known colleague.
  • Penetration testing and red teaming: build realistic target lists for authorised phishing simulations and social-engineering assessments in one command.
  • Self-audit and account recovery: work out which address you signed up with years ago.

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 jq and line-based tools.
  • txt: one email address per line, highest score first.
  • csv: email,local_part,domain,pattern,category,score with 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.last ranks above lastf, which ranks above first-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-email format 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

For AI agents

EmailGuesser is built to be driven by agents as well as people. It ships a Model Context Protocol server:

pip install "emailguesser[mcp]"   # Python 3.10+
emailguesser-mcp                  # stdio server; or: python -m emailguesser.mcp

Point your MCP client at the emailguesser-mcp command. It exposes one tool, guess_emails, and the output JSON Schema as the resource emailguesser://schema.

An agent that can't use MCP can still call the CLI (--format json, or --format jsonl for batches) or the Python generate() function, and read the output contract from emailguesser --schema or schema/result.schema.json. Full guidance, including the input table and the guardrails to build in, is in AGENTS.md.

FAQ

Does EmailGuesser check whether an email address exists? No. It is offline and generation-only and never contacts a mail server.

How does it relate to NAMINT? EmailGuesser started from NAMINT's login patterns, so it owes that project a lot. NAMINT, by The SEINT, is a browser tool that turns a name into login search patterns with ready-made search links. It's the better choice when you want to search the web for a name, and you can use it right away at seintpl.github.io/NAMINT. EmailGuesser is a Python command-line tool and library focused only on email addresses. It covers every NAMINT login pattern (a test checks this) and adds ranking, nicknames, usernames, date of birth, location, known-format inference, de-duplication and JSON, CSV and 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

EmailGuesser builds on NAMINT by The SEINT (@SEINT_pl), released under the MIT License. NAMINT's login patterns are the foundation of EmailGuesser's name patterns, and tests/test_generator.py checks that every one of them is still generated. If you want search links for a name rather than email candidates, use NAMINT directly at seintpl.github.io/NAMINT.

The in-browser version runs on Pyodide.


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.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for emailguesser 0.4.0
File Size Uploaded
emailguesser-0.4.0.tar.gz 57.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for emailguesser 0.4.0
File Interpreter ABI Platform
emailguesser-0.4.0-py3-none-any.whl Python 3 none any Details

Total release size: 103.1 kB

Release files / emailguesser-0.4.0.tar.gz

Download URL emailguesser-0.4.0.tar.gz
Size 57.2 kB
Tags Source
SHA-256 checksum
How to use checksums
e9b991c0544da5587442b6351ce04714c2d406c87cb45657b26a883cbaaf3313
BLAKE2b-256 checksum
How to use checksums
3c5bbfc21010a5edf5cbe3fafebbc86defbd2a511f179d7a1d64810206d14861
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

Release files / emailguesser-0.4.0-py3-none-any.whl

Download URL emailguesser-0.4.0-py3-none-any.whl
Size 45.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
374109ca7fc46577f7ccada3ed954c6a1c6f8bcaa89540af999cceebfb2875b9
BLAKE2b-256 checksum
How to use checksums
4717b088bc8fe754d70b9a73a95591c4706c57567e679d140abc71ed99ae8949
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

Release history Release notifications | RSS feed

This release

0.4.0 This release

2 release files

0.3.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page