# Browser fingerprint detectors list: our 49

> Our browser fingerprint detectors list: 49 public test pages in five groups, 40 read by a script and 9 kept as reference because they print no verdict.

Source: https://mosaicbrowser.com/blog/forty-nine-detectors

## 49 browser fingerprint detectors, and how we read them

Our browser fingerprint detectors list: 49 public test pages in five groups, 40 read by a script and 9 kept as reference because they print no verdict.

![49: 49 detectors, five groups, one list](https://mosaicbrowser.com/covers/forty-nine-detectors.webp)

Our browser fingerprint detectors list has 49 public pages on it, in five groups: 12 consistency checks, 11 live commercial gates, 10 leak tests, 8 uniqueness tests and 8 automation tests. A script reads the verdict on 40 of them. The other 9 print values and no verdict, so we keep them as reference pages and read them by eye.

All 49 rows are one TypeScript array, `DETECTION_TESTS` in `src/shared/detection-tests.ts`. The Check detectors menu on a profile row reads it. So do `GET /detection-tests` and the MCP tool `list_detection_tests`, and so does the batch runner we use before a release. With one list, the window, the API and our reports cannot disagree about what "tested" meant.

## The browser fingerprint detectors list, in five groups

| Group | Count | Detectors |
| --- | --- | --- |
| Consistency | 12 | Pixelscan, IPHey, BrowserScan, Whoer.net, Fingerprint-Scan, JA3/JA4 echo, BrowserLeaks JavaScript, Client Hints, WebGPU, Features, TLS and HTTP/2 |
| Live gates | 11 | Cloudflare Bot Fight, Cloudflare Turnstile demo, reCAPTCHA v3 score, hCaptcha demo, DataDome demo, Akamai Bot Manager, F5 / Shape, Kasada, Imperva / Incapsula, HUMAN / PerimeterX, Qrator |
| Leaks | 10 | BrowserLeaks WebRTC, IP, DNS, Geolocation and Proxy, ipleak.net, DNS Leak Test (extended), diafygi WebRTC IPs, Cloudflare trace, a header echo |
| Uniqueness | 8 | CreepJS, AmIUnique, EFF Cover Your Tracks, FingerprintJS demo, deviceinfo.me, BrowserLeaks Canvas, WebGL and Fonts |
| Automation | 8 | bot.sannysoft.com, Rebrowser bot detector, Incolumitas BotOrNot, deviceandbrowserinfo, BrowserScan bot detection, CreepJS proxy detection, prototype tampering and worker realms |

We never add the five groups into one score, because they fail for unrelated reasons. AmIUnique, in the uniqueness group, wants to know whether it has seen this device before. Rebrowser, in automation, looks for traces a driving program leaves, such as the DevTools `Runtime` domain switched on. BrowserLeaks WebRTC is a leak test: it gathers the addresses WebRTC can find and expects no public one except the proxy's exit. The eleven live gates have no score at all, since Akamai or Kasada either serves the page or puts a challenge in front of it. A profile can be green on all eight automation pages and red on every consistency page, and that would be two bugs with two different fixes.

The app shows Consistency first. Its blurb says these pages were built to catch anti-detect browsers specifically, and when one fails it names the contradiction: a timezone against the exit, or a GPU that does not belong with the screen. The values those pages compare are described in [what a browser fingerprint is](https://mosaicbrowser.com/glossary/browser-fingerprint).

Mosaic is a desktop app

Email yourself the link and open it on your computer.

[How it works: Machines that exist](https://mosaicbrowser.com/features/real-fingerprints)

## Automatic, reference, and the word we removed

`verdict` is the field that decides whether the runner owes a page a reader. Set to `automatic`, it says Pixelscan or IPHey draws an answer and `run-detection-tests.mjs` has a function to read it. Set to `reference`, it says there is no answer to read. deviceinfo.me is the plainest example. It lists sixty browser properties under headings, behind a consent dialog, and never says which one is wrong, so there is nothing for code to read.

A third value, `manual`, once covered two different things: "we have not written the reader yet" and "there is nothing to read". A tally of manual rows mixed work we owed with work that could never exist, so we gave the second its own word and then wrote the readers we owed. On 21 October 2026 the file has 40 `automatic` rows, 9 `reference` rows and no `manual` ones.

The nine reference pages are AmIUnique, deviceinfo.me, BrowserLeaks Fonts, Geolocation, Features, TLS and HTTP/2, the Turnstile demo and the hCaptcha demo. Each prints a hash or a table. The screenshot is the deliverable.

## Rules the runner follows

The runner keeps four rules, and we broke each of them before we wrote it down.

1. A test that did not run is never a pass. A site that serves nothing is `unreachable`. Pixelscan loading with no headline the reader can find is `unread`.
2. Read the verdict the page draws, not a word in its prose. Pixelscan's green card says "No masking detected", which contains "masking detected".
3. Run it more than once. IPHey gave an unmodified Google Chrome 100, 100, 70 and 0 on one afternoon, so rounds that disagree are reported as `flaky`.
4. Write down the exit. Whoer and BrowserScan compare the IP's country with the timezone and language, so a run without the proxy grades a different pairing.

Each run also checks the catalogue against the runner. A row marked `automatic` with no reader behind it is printed as a fault in our list, under its id, not as a result about the profile. Before that check, `docs/DETECTION.md` printed "34 automatic" while three of the 34 had no code that could read them.

## Rows we deleted

Third-party test pages move and retire. When one stops answering, we find out where the test went before concluding anything. Three examples:

- `fpscanner` pointed at a page that had become its author's homepage. His projects page sends visitors to deviceandbrowserinfo and Fingerprint-Scan instead, and both were already on the list.
- `datadome-bots` served the same homepage, with an HTTP 200. A 200 is never `unreachable`, and a challenge reader looking at a page with no challenge on it scores a pass. A retired demo would have reported a clean run on every profile, the kind of result nobody goes back to check, so we deleted the row.
- Pixelscan moved its scan from the front page to `/fingerprint-check`. The old address showed a marketing page with no verdict for sixty seconds, in an untouched Chrome too.

We also found a row the runner had silently stopped running. It read the list with a regular expression, and when Pixelscan's entry grew a long comment between two fields, the pattern skipped it: 53 tests declared, 52 parsed. The runner now compiles the file the app ships instead of pattern-matching it.

## Why the list matters to the engine

Several of these pages compare what the page reads with what a worker or an iframe reads. A value changed by a script in the page and not in the worker is worse than the real value, because the disagreement is the signal. That is why Mosaic changes fingerprint values in C++ inside its own Chromium, as told in [why we built our own Chromium](https://mosaicbrowser.com/blog/why-we-built-our-own-chromium). The program driving a browser can give it away too, which is the [Runtime.enable story](https://mosaicbrowser.com/blog/runtime-enable-detection), and the hardware records profiles are drawn from are on [real fingerprints](https://mosaicbrowser.com/features/real-fingerprints).

![A profile's row menu in Mosaic, with Check detectors next to the leak test](https://mosaicbrowser.com/shots/pinned-profiles.png)
*Check detectors opens any of the 49 in that profile*

## Questions

### Which browser fingerprint detectors should I test first?

Pixelscan, IPHey and BrowserScan, from the consistency group. When one of them fails it names the values that disagree, such as a timezone against the exit's country, and that pair is something you can fix. CreepJS or AmIUnique can only tell you how rare the browser looks.

### Why are some detectors marked reference instead of automatic?

Nine pages, such as deviceinfo.me and AmIUnique, print values without a verdict. A script has nothing to read on them, and inventing a pass mark over someone else's table would be guessing.

### What happens when a detector site is down?

Our runner records it as unreachable, never as a pass. A test that did not run tells you nothing about the profile.

### Do the 49 detectors cover what real sites run?

No public page can. They are demos and research tools. A platform's own bot defence is private and may score the same browser differently.

## Related

[Why we built our own Chromium instead of injecting JavaScript](https://mosaicbrowser.com/blog/why-we-built-our-own-chromium): Mosaic changes fingerprint values in C++ inside its own engine. Three measured differences between Chrome and plain Chromium explain why that matters.

[Runtime.enable flips a detector, so we don't call it](https://mosaicbrowser.com/blog/runtime-enable-detection): Runtime.enable detection, measured: one DevTools command turned a clean Mosaic profile into isBot=true on deviceandbrowserinfo. We removed all five calls.

[Browser fingerprint: what a site can read about your machine](https://mosaicbrowser.com/glossary/browser-fingerprint): A browser fingerprint is the set of values a site reads about your browser and computer, which together recognize you without cookies. What goes into one.

[Machines that exist: fingerprints drawn from real hardware](https://mosaicbrowser.com/features/real-fingerprints): Mosaic draws each profile's GPU, screen, CPU, memory and fonts from one real device, so the parts of a fingerprint agree with each other and with the host.



[A retired bot test can still answer 200 and look like a pass](https://mosaicbrowser.com/blog/dead-detector-returns-200): Antoine Vastel's fp-scanner demo now serves his homepage with HTTP 200, which a challenge reader scores as a pass. His tests moved; here is where.

[Why navigator.webdriver is true, and why false proves little](https://mosaicbrowser.com/blog/why-navigator-webdriver-true): navigator.webdriver is true because automation set it on purpose. We measured a debug-attached Chrome reading true and still scoring 100 on IPHey.

[fingerprint-scan.com bot score: 0 before anything was measured](https://mosaicbrowser.com/blog/bot-score-before-measuring): fingerprint-scan.com shows Bot score 0/100 while its hash still reads collecting. Read the score only after the hash exists, and expect 15, not 0.

## Mosaic, on your own computer

The browser this blog is about: its own Chromium, fingerprints from real machines and a proxy exit per profile. Free holds 3 profiles. Pro is $49 a month for any number.

Mosaic is a desktop app

Email yourself the link and open it on your computer.
