Dev.to Security 🔐 Cybersecurity 👁 0 📖 5 min read

How I got false positives in username search down to zero across 11,988 sites

If you have used Sherlock, Maigret or WhatsMyName, you have seen this. You search a username, you get a long list of accounts, and some of them are not real. A login page. A "user not found" page that still returns 200.

If you have used Sherlock, Maigret or WhatsMyName, you have seen this. You search a username, you get a long list of accounts, and some of them are not real. A login page. A "user not found" page that still returns 200. A site that sends every name to its homepage. Each one shows up in your results as a found account.

I build Helix, an open source username tool. When I combined the three big site databases into one scan (over 8,000 sites), the problem got worse in a way I could measure. I made up a username nobody has and scanned it. Helix reported 72 accounts. All 72 were false.

This post is about the check that took that number to 0, and how I measured it.

Why the databases go wrong

Every site in these databases is a rule written once: request this URL, then look for this status code or this text. Sites change. A rule that was right two years ago can match every page today.

Some sites answer "found" for any name at all. Logged out, Facebook and Instagram show the same login wall for every profile URL. Catch-all pages return 200 for anything. With thousands of sites, enough of them are broken at any moment that a made-up name collects dozens of hits. Fixing them one by one does not scale, because they break faster than anyone can fix them.

The control probe

So I stopped trusting the rule and started testing the site, live, at the moment it reports a hit.

When a site says "found" for jack, Helix immediately asks the same site for two usernames that cannot exist, using the same rule:

  1. If the site also "finds" a made-up name, it is a catch-all, and the hit is dropped.
  2. If the made-up names only get a rate limit, a bot check or a gateway error, the site has not shown it can tell real from fake. The hit is dropped as unverifiable.
  3. The hit is kept only if the real name is found again and both made-up names get the same clear "no such user" answer.

There is no per-site tuning. Each site has to prove, during your scan, that it can tell a real account from a fake one.

The fake names need the right shape

My first version used 12 random letters. Then dev.to showed me why that was not enough: it answered a path starting with a dot as if it were a profile, while random letters got a clean 404. So a username like .name passed a control that never had a dot in it.

Now the made-up names copy the shape of the real one: the same punctuation in the same places, every run of letters and digits replaced with random characters, and at least 12 random characters in total so they cannot collide with a real account.

The page must name the user

For rules that only look at the status code, or at the absence of a "not found" message, the page also has to contain the exact username. A rate limit page, a sign-in redirect or a search page listing jackie cannot pass for jack.

Measuring it

I measured it two ways.

A mock web. The repository has a benchmark that serves 6,000 fake sites from a separate process, 2% of them catch-alls that answer "found" for any name. Because the ground truth is exact, it gives real precision and recall. With the probe on: precision 1.000, recall 1.000, 0 false positives, at default concurrency and at 300.

The real internet. Generate a random username just before the run and scan it. It has no accounts, so every hit is a false positive.

  • Probe off: 72 accounts. Probe on: 0. (29 Oct 2026, the full database at the time.)
  • On my laptop over a mobile hotspot, all 8,305 sites, three runs at three concurrency settings: 0 accounts every time. Each run got a clear answer from about 7,000 sites. The fastest took 7 minutes.
  • In one of those runs, 110 sites were dropped because they "found" a username that cannot exist. Without the probe, every search would have reported those 110 accounts.
  • Helix 3.6.0 adds 3,683 Mastodon, Misskey, Lemmy and PeerTube servers, each its own website with its own users, so a full scan now covers 11,988 sites. A made-up name across all of them: 0 accounts, 10,436 clear answers, 176 seconds.

Then real names. jack returns 874 accounts. I picked 15 at random and checked each by hand against a made-up name on the same site: 14 real, 0 false, and 1 unclear (a Patreon account that had been removed but still answered 200, which is fixed now).

Saying what was not checked

A clean result only means something if you know what was checked. In that same run, 1,273 sites gave no clear answer: 367 bot checks, 265 connection errors, 237 timeouts, 139 HTTP 403s, and the 110 catch-alls above among them.

Most tools quietly count these as "not found". Helix lists them as not checked, with the reason, because "we could not reach it" and "there is no account" are different findings in an investigation.

Found does not mean it is your person

Zero false positives means every reported account exists. It does not mean the account belongs to the person you are looking for.

Search torvalds and you will find a Substack account that belongs to someone called Nicolas, an Instagram account belonging to Marco Migozzi, and a Steam profile that goes by NaraKa. All real accounts. None of them Linus.

So every account gets an identity grade, HIGH, MEDIUM or LOW, based on independent evidence: the same avatar, a link one account declares to another, a confirmation through an email address, a matching location. A username match on its own is always LOW, and when the found profiles show different names, Helix says so.

Evidence that holds up later

This part is for journalists and investigators. --record-attempt writes a sealed record of the scan: start and end times in UTC, the exact site database and its SHA-256, the outcome for every site, and a fingerprint of the whole file. --verify-evidence checks it later.

--save-pages keeps the exact page behind every reported account, hashed and timestamped. If a profile is deleted next week, you can still show what it said when you found it.

Try it

pipx install helix-osint
helix-osint -u someusername          # 56 built-in sites, a few seconds
helix-osint -u someusername --all    # all 11,988 sites
helix-osint -u someusername --tor    # through Tor

The code, the benchmark and the run records are at https://github.com/thalha-a9/helix (MIT).

If Helix ever reports an account that does not exist, please open an issue with the username and the site. That is the bug I most want to hear about.

📰 Read the original article on Dev.to Security

Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.