August 5, 2026
Email OSINT in 2026: Half the Tools You’re Using Are Lying to You
Part 1 — The account-existence oracle, why enumeration tools rot silently, and the one everybody still recommends that stopped working.

By Devansh Patel
9 min read
Part 1 — The account-existence oracle, why enumeration tools rot silently, and the one everybody still recommends that stopped working.
Last month I ran an email address through a tool that half the OSINT internet still recommends.
It came back clean. No accounts. Nothing.
I ran the same address through something else twenty seconds later and got back eleven registered platforms, an infostealer infection from 2024, and a Google account with public Maps reviews pinning the person to a three-kilometre radius in a city they had never mentioned online.
The first tool wasn't wrong because the data didn't exist. It was wrong because it hadn't been updated in years and was silently returning false negatives.
That is the most dangerous failure mode in this entire discipline, and almost nobody writing "email OSINT guide" posts mentions it. A tool that says nothing found feels like an answer. It isn't. It's an absence of an answer wearing an answer's clothes.
This is Part 1 of three. By the end of it you'll understand why an email address leaks anything at all — at the protocol level, not the tool level — and you'll have replaced the single most commonly recommended dead tool in the field.
The one line to remember:_ in OSINT, a negative result from an unmaintained tool is not evidence of absence. It's evidence of nothing at all._
The theory nobody explains
Every guide shows you commands. Almost none explain why any of it works. Understand the mechanism and you can invent techniques instead of memorising tools.
The account-existence oracle
Here is the tension that makes this entire field possible.
Every website with user accounts has a "forgot password" flow. That flow faces an impossible design decision:
- If you type an email with no account and the site says "we've sent you a reset link" — the site just lied to you. You'll sit refreshing an empty inbox. Terrible experience, floods of support tickets.
- If the site says "no account exists with that email" — helpful, honest, and it just confirmed to a complete stranger whether you have an account there.
That's it. That's the whole vulnerability class. It's called an account existence oracle, and it exists because usability and privacy pull in exactly opposite directions on this one screen.
Every email OSINT tool in existence is a collection of scraped signatures for how individual sites resolve that tension. There are four ways it leaks:
1. Explicit disclosure. The site simply tells you. "No user found with that email address." Depressingly common, even in 2026.
2. Response differential. The site claims to say the same thing either way — but the HTTP status code differs, or the body is 847 bytes for a real account and 831 for a fake one, or a Set-Cookie header appears in one case and not the other. The words are identical. The bytes are not.
3. Timing side-channel. This one is beautiful. If the account exists, the server fetches the password hash and runs a comparison — bcrypt at cost factor 12 takes roughly 250ms by design, because being slow is the entire point of a password hash. If the account doesn't exist, the server bails early and responds in 15ms.
You didn't read the response. You read the clock.
4. Registration-flow inversion. Instead of asking "do you have an account," you attempt to create one. "That email is already registered." Same oracle, opposite door — and often the one that survives after the reset flow gets hardened.
Now the practical consequence, which is the thesis of this entire series:
_Every module inside every email OSINT tool is a fingerprint of one specific endpoint's behaviour at one specific moment in time. When a site patches its login flow, the module doesn't error out. _It silently starts returning "not registered" for everyone.
This is why maintenance velocity beats module count every single time. A tool checking 40 endpoints verified last week is worth more than one checking 140 endpoints last verified in 2022. The second tool doesn't tell you it's broken. It tells you the target is clean.
Identifier stability: why pivoting works
Second piece of theory, and it governs every decision you'll make later.
Not all identifiers are equal. Rank them by how hard they are to change:
The entire craft of OSINT pivoting is this: convert low-stability identifiers into high-stability ones as fast as possible, and anchor your investigation on the stable ones.
A display name is useless as an anchor. An email is excellent — which is exactly why it's the strongest selector you can start from. An internal platform ID is permanent: the target can rename the account, change the photo, switch the handle, and that number still points at them.
Hold that thought. In Part 2 it becomes the most valuable number in Google OSINT — and the reason that section has a deadline on it.
The tool that died
Now the part that will save you from the false-negative trap.
For years, holehe was the default recommendation in every email OSINT guide. It checked 120+ sites via password-reset oracles and it was genuinely excellent. I recommended it. Everyone did.
It has not had a major update in years. Modules are broken. Platforms like X and Instagram hardened exactly the endpoints it depended on. It hits rate limits, and it returns false positives and false negatives.
Apply the theory from thirty seconds ago: an unmaintained enumeration tool doesn't fail loudly. It quietly reports that your target has no accounts. That is strictly worse than having no tool, because it manufactures confident, wrong conclusions — and you have no signal that anything went wrong.
Its own GitHub issue tracker now contains users pointing each other at the replacement.
user-scanner is the successor
user-scanner is actively maintained, community-contributed, and as of the current release covers 375+ scan vectors — roughly 150 email-integrated sites and 225 username platforms.
bash
python3 -m pip install --upgrade pip
pip install user-scannerpython3 -m pip install --upgrade pip
pip install user-scannerOr run it without installing anything permanently:
bash
nix run github:kaifcodec/user-scanner/main -- --helpnix run github:kaifcodec/user-scanner/main -- --helpCore usage:
bash
user-scanner -e target@gmail.com # email scan
user-scanner -u targethandle # username scan
user-scanner -e target@gmail.com --hudson # + infostealer log checkuser-scanner -e target@gmail.com # email scan
user-scanner -u targethandle # username scan
user-scanner -e target@gmail.com --hudson # + infostealer log checkTargeted scanning, which matters more than people realise:
bash
user-scanner -u targethandle -c dev # developer platforms only
user-scanner -u targethandle -m github # single module
user-scanner -ef emails.txt # bulk from file
user-scanner -uf usernames.txtuser-scanner -u targethandle -c dev # developer platforms only
user-scanner -u targethandle -m github # single module
user-scanner -ef emails.txt # bulk from file
user-scanner -uf usernames.txtThe features that actually differentiate it:
- Permutation generation — automatically builds username variations to catch alternate and secondary accounts
- Proxy rotation with pre-scan health checks — a real OPSEC feature, not a convenience one
- JSON, CSV, and PDF export — pipeline-friendly
- Auto-update prompts via PyPI — the modules stay current, which is the entire point
That --hudson flag queries infostealer malware logs. It's the single biggest shift in email OSINT since breach databases, and it gets the whole first half of Part 2.
The mistake that burns investigations
Before you point any of this at a live target, one thing.
Some enumeration modules work by triggering a real password-reset or verification email to the target's inbox.
Sit with that for a second. You are conducting a discreet investigation, and your tooling just sent your subject a notification saying someone tried to access their account.
Good tooling flags these. user-scanner maintains an internal category for exactly this reason. Before a full scan against a live, sensitive target:
- Test against an address you control first and check whether anything actually arrives
- Scan by category (
-c) rather than firing every module at once - Understand that "quiet" is a property of the current module implementation, not a permanent guarantee
The fastest way to burn an investigation is to run a noisy tool against a target who's paying attention.
This is also why every serious practitioner runs from a dedicated browser profile, a sock puppet account, and a separate IP. Your investigation has a footprint too. Full OPSEC framework is in Part 3.
What Part 1 buys you
Three things, and they're worth more than any tool list:
- You know why enumeration works — the oracle, the four leak channels, the timing side-channel. You can now reason about a site you've never seen.
- You know why tools rot silently, and you'll never again treat a clean result from an unverified tool as a finding.
- You've replaced the dead tool everyone still recommends.
Try this before you close the tab
Ninety seconds. Genuinely:
bash
pip install user-scanner
user-scanner -e YOUR_OWN_EMAIL@gmail.com --hudsonpip install user-scanner
user-scanner -e YOUR_OWN_EMAIL@gmail.com --hudsonRun it against your own address.
Most people find accounts they created a decade ago and completely forgot existed. A surprising number find themselves sitting in an infostealer log from a machine they were certain was clean.
Drop your count in the responses — how many platforms came back registered? Any stealer log hits? I read and reply to every one, and the numbers people report shape what I dig into next.
Coming in Part 2: the 21-digit number Google assigns every account, why it's the most valuable identifier in Google OSINT, why it's quietly disappearing — and the infostealer log ecosystem that has replaced breach data as the deepest source in the field. Including how a five-star review of a dental clinic locates someone more precisely than their entire Instagram.
Follow so it lands in your inbox.
If this saved you from a false negative — or from recommending a dead tool to someone — a clap helps more people find it. Highlight the part that surprised you most; I use highlights to decide what to go deeper on.
Everything here is for authorised security research, defensive footprint assessment, and education. Run it on yourself. Run it on assets you're permitted to test. The full legal framework — including India's DPDP Act and why its "publicly available data" exemption is narrower than most people assume — is covered in Part 3.
Bonus — the half nobody should read this and forget
Everything above is a mirror. Every technique I've shown you to find your own forgotten accounts is the same technique used to take over someone else's. Same oracle. Same four leak channels. Same clock. The only difference is intent — and intent doesn't change a single byte on the wire.
Here's the chain the dangerous version runs. Learn it cold, because at some point it gets run against your email too.
Phase 1 — Enumerate. Quietly, at scale, against every platform the target is likely to use. The attacker doesn't need the fancy tool. They need one endpoint, one script, and patience. The timing side-channel from earlier, weaponized, is about fifteen lines:
# Educational demo — point this at endpoints you own, not people you don't.
# pip install requests first if you haven't got it.
import requests, time, statistics
# Educational demo — point this at endpoints you own, not people you don't.
# pip install requests first if you haven't got it.
import requests, time, statistics
def probe(base_url, email, n=20):
times = []
for _ in range(n):
t0 = time.perf_counter()
requests.post(base_url, json={"email": email, "password": "wrong-password-xyz"}, timeout=10)
times.append((time.perf_counter() - t0) * 1000)
return statistics.median(times)
base = "https://your-test-target.example/login"
for email in ["exists@example.com", "nope@example.com"]:
print(f"{email}: {probe(base, email):.1f} ms")# Educational demo — point this at endpoints you own, not people you don't.
# pip install requests first if you haven't got it.
import requests, time, statistics
# Educational demo — point this at endpoints you own, not people you don't.
# pip install requests first if you haven't got it.
import requests, time, statistics
def probe(base_url, email, n=20):
times = []
for _ in range(n):
t0 = time.perf_counter()
requests.post(base_url, json={"email": email, "password": "wrong-password-xyz"}, timeout=10)
times.append((time.perf_counter() - t0) * 1000)
return statistics.median(times)
base = "https://your-test-target.example/login"
for email in ["exists@example.com", "nope@example.com"]:
print(f"{email}: {probe(base, email):.1f} ms")Median, not mean — one slow request ruins an average, and attackers know that too. If the endpoint runs bcrypt against the stored hash for existing users and bails early for everyone else, the two columns don't overlap. You don't need the response. You need the clock.
Phase 2 — Credential stuffing. This is where the stealer-log ecosystem from Part 2 enters the chain. The attacker buys a filtered log — email, password, cookies, autofill — for the price of a coffee, and feeds the passwords into every platform Phase 1 confirmed. They don't need a breach database. The victim's own browser was the breach.
Phase 3 — The reset flow, inverted. Passwords fail everywhere? Fine. The oracle's opposite door becomes a door into the account. Every reset flow that answers differently for existing accounts — every verification email that lands in an inbox the attacker already controls because the target reuses one address everywhere — is a takeover in progress.
The part people get wrong: MFA. The most dangerous technical fact in this entire series: a stolen session cookie does not care about your two-factor authentication. MFA proves you at login. The session cookie the server issues afterwards is just a bearer token — steal it, replay it, and the server believes the login already happened. That's why stealer logs are the deepest source in the field. They don't just contain passwords. They contain the entire authenticated state: cookies, tokens, wallet seeds.
This is also why enumeration is dangerous even when the password never breaks. Knowing someone is on a specific platform makes a phishing email dramatically more credible — the attacker references a platform the target actually uses, a dentist the target actually reviewed. The target's own data is the pretext.
The defence, in one breath: rate-limit every auth endpoint; return identical responses in identical time for existing and non-existing accounts; hash-and-compare a dummy value when the user doesn't exist — that alone kills the timing channel; monitor for enumeration bursts; and never treat a "clean" result from your own tooling as a verdict.