How many false alarms does a typosquat detector raise? We measured ours
1 October 2026. Disclosure: this is about the typosquat check in Presend's free API, written by the people who build it.
A typosquat detector compares a package name with popular names and flags the ones that are suspiciously close: reqeusts next to requests. The hard part is not catching reqeusts. It is not flagging ms, qs or typing_extensions, because a check that cries wolf on the packages everybody uses gets switched off, and then it catches nothing.
So we stopped testing our check only on typosquats and started measuring it on the packages people actually install: the top 15,000 PyPI packages and the 17,338 packages of the npm-high-impact list.
Where we started
On 25 September, run against 25 very popular npm packages, our check flagged 12 of them. ms and qs are one edit away from ws; with a fixed edit-distance threshold, every short name is one edit away from another short name. It had only ever been tested on known typosquats, where it looked fine.
What reduced the noise
- A threshold that depends on length. Names of three characters or fewer are not compared approximately at all; 4 to 7 characters allow one edit; 8 or more allow two.
- Normalising PyPI names. PyPI treats
typing_extensions,Typing.Extensionsandtyping-extensionsas the same project (PEP 503). Comparing raw strings flagged a package against itself. - Trusting npm scopes.
@aws-sdk/client-ssois one edit from@aws-sdk/client-s3, but a scope belongs to one organisation, so a package is never flagged against a target in its own scope. - A reviewed list of legitimate neighbours. Some real packages are close to a popular name:
psycopg,niquests,preact. Each one was checked by hand (repository, age, history) before being listed: 51 on PyPI and 57 on npm today. We never remove a target to silence a warning.
Result on popular packages: from 58 flagged to 11 on PyPI and from 65 to 1 on npm. The remaining 12 were reviewed and left flagged deliberately. All 27 known typosquats in our test set are still detected.
Tests that fail when the noise comes back
The three measurement scripts fail if a popular package is flagged without having been reviewed. Any change to the list of targets or to the legitimate neighbours has to pass them, so a fix for one false alarm cannot quietly create others.
The numbers drift
On 1 October, five days after the previous run, the top 15,000 PyPI list had changed and four packages that had recently entered it were flagged: djongo (next to django), tmol (toml), orgparse (argparse) and webp (web3). All four are legitimate. For the newest one, tmol, first published on PyPI in May 2026, we did not rely on the links in its PyPI metadata, which the publisher writes: we checked that its repository, which dates from 2018, claims the PyPI name. A false-positive rate is a measurement with a date, not a property of the code, so we now re-run it every week.
What name similarity cannot catch
- Names far from every target. Only names close to a list of popular packages are checked. Before we added
electronto that list,electornwent unnoticed. - Hallucinated names. A package name that an AI model invents and that resembles no real package (slopsquatting) is not a misspelling of anything, so distance-based checks miss it. Checking that a package exists, and how old it is, is a different check.
- Intent. Distance says two names are close, not that one is malicious. It is a triage signal, not a malware scanner.
Measuring other tools the same way
The same method works on any typosquat rule. Applied to the SC6 rule of NVIDIA's SkillSpector, with its own code, it found 97 high-severity false positives on the top 15,000 PyPI packages and 26 on high-impact npm, with 13 of 27 known typosquats detected. After a native fix (PR #647, merged), the figures were 6, 0 and 27 of 27.
Try it, reproduce it
curl "https://presend.pages.dev/api/typosquat-check?ecosystem=PyPI&package=reqeusts"
The check is free through the API and the MCP server (per-minute rate limits apply). The scripts and test sets are in the public presend-source repository, and the latest numbers, with the publisher-change check, are on the measurements page.
We are also testing whether teams want these checks on every pull request and for their AI coding agents, as a paid offer. Nothing is for sale yet; if that would help your team, the waitlist is here.