Skip to content
All fingerprint checksEngine & OS oracles

The measured JS engine matches the engine the User-Agent claims

Check id js-engine-identifier-vs-ua

What an ordinary browser yields

An ordinary browser measures an id matching the family its own UA names — e.g. id 80 = V8 on Chrome — and passes.

What a detector infers

Two values are read straight out of the JavaScript engine itself: the character length of the RangeError message thrown by `(-1).toFixed(-1)`, and the length of the Array constructor's own source text with every occurrence of its name removed. Their sum is a stable engine fingerprint — 80 identifies V8, 58 SpiderMonkey, 77 JavaScriptCore — because it comes from wording and source formatting compiled into the binary, on a surface no User-Agent string, CDP override, or `navigator.userAgentData` shim ever touches. The check then compares that measured family against the family the UA claims (Firefox/FxiOS → SpiderMonkey; Edg/Chrome/Chromium/CriOS → V8; iPhone/iPad/iPod or Safari-without-Chrome → JavaScriptCore). When the two disagree, a detector can infer that the identity presented in HTTP and JS headers was written by a layer above the engine, and that inference is reliable precisely because the engine's own error text is not part of any spoofing surface. Severity is critical. Crucially, when the measured id is not one of the three known values, or the UA names no family the check adjudicates, `pass` is null — indeterminate, not a failure, and it is excluded from the score. That branch matters: engines reword error messages between versions, so a check that failed on an unrecognised id would fire on every real browser running a future release. An honest detector distinguishes "this contradicts" from "I don't know".

How to resolve it

Make the User-Agent match the engine that is actually executing. This contradiction cannot be resolved from inside JavaScript: patching `navigator` leaves the RangeError text and Array constructor source untouched, so a Gecko or WebKit engine presenting a Chrome UA stays visible. Either run the engine the UA claims, or claim the engine you run.

What is CreepJS?

Read in the wild by

CreepJS

CreepJS — an open-source research demo rather than a production detector — runs nine deliberately broken snippets through `new Function`, collects each engine-authored `err.message`, and hashes the set into its fingerprint, filing the probe under the engine section of its source tree and treating the engine's own error wording as an engine-level signal.

src/engine/index.ts:22-32: `const errorTests = [() => new Function('alert(")')(), … () => new Function('null.bar')(), … () => new Function('(1).toString(1000)')(), … () => new Function('var x = new Array(-1)')(), …]` (nine entries), collected at line 12 via `errors.push(err.message)`; hashed in src/creep.ts:202 `hashify((consoleErrorsComputed || {}).errors)`, imported at src/creep.ts:7 as `import getConsoleErrors, { consoleErrorsHTML } from './engine'`.

Akamai

Lists error-message format as a JavaScript-environment signal, noting it "differs by engine" — which is exactly what this oracle measures.

signal_categories.md - 6. JavaScript Environment - Error messages

Edioff/akamai-analysis — signal_categories.md

DataDome

Provokes a TypeError inside a Worker and ships the message text verbatim; the wording is V8's, so the string itself names the engine.

mUMHqX = base64 "WorkerCaughtErr: Err: TypeError: Cannot read properties of null (reading '…'"

glizzykingdreko/datadome-encryption — tests/original.json

Every attribution traces to a published artifact. See the sources and their limits.

Other checks in Engine & OS oracles

Who builds this test

Clearcote is a browser built for fingerprint coherence

It is a Chromium fork, maintained by the same people who wrote this reference. It ships as a compiled browser rather than as a stealth script injected into someone else's — which is a description of how it is built, and is not an argument about how it behaves on this check.

This audit takes no position on how Clearcote scores on Engine & OS oracles checks, on this one, or anywhere else. It has no baseline corpus of other people's fingerprints to rank you against and no vendor scoreboard — nearly every check is self-referential, asking one browser the same question through two independent APIs and reporting whether both answers can be true at once. It runs identically on any browser, including ours. Run it on yours and read the result yourself.

See the other checks in Engine & OS oracles — the family js-engine-identifier-vs-ua belongs to.