Skip to content
All fingerprint checksClocks & ledgers

every surface that reports when this document started agrees

Check id navigation-origin-consensus

What an ordinary browser yields

Every reachable surface — timeOrigin, the legacy timing milestones, the modern navigation entry, and chrome.loadTimes/csi where they exist — agrees about when this document started.

What a detector infers

One document has one navigation start, and Chrome exposes it through four different doors: performance.timeOrigin, the legacy performance.timing milestones, the modern PerformanceNavigationTiming entry, and the long-deprecated chrome.loadTimes() and chrome.csi(). There is one navigation timing record behind all of them, so they must agree. DataDome demonstrably holds several at once — its VM anchors its whole clock section on performance.timing.navigationStart, while the main tag independently reads the modern entry (it ships nextHopProtocol and entryType, which exist only there) and separately enumerates window.chrome's own keys to confirm loadTimes and csi are present and reachable. What makes this worth a check is what it asks that its neighbours do not. Headless patches famously re-add window.chrome.loadTimes to look like real Chrome, and a check that asks whether it exists, or whether it stringifies as native, is satisfied by a stub — this audit ships two such checks and both are honest about their limits. This one asks the stub what time the document started, and then makes three other doors check the answer. That is a question a stub can only answer correctly by doing the real work of tracking the navigation. Every arm is gated independently and contributes only if reachable, so a Chromium fork with no csi, a browser with no navigation entry, and a future Chrome that has finally removed the deprecated surfaces all degrade one arm at a time rather than failing. Two guards matter: a milestone reading 0 is the spec's did-not-happen sentinel rather than time zero, and treating it as a value flags a stock Chrome outright; and the tolerance is derived from the measured granularity of Date.now() rather than a constant, because Firefox with resistFingerprinting quantises the legacy and modern sides independently and a fixed tolerance would open a gap on a stock Tor Browser.

How to resolve it

Restore the value, not just the function. Chrome answers this question identically through four doors because one navigation timing record sits behind them; tooling hooks the door it has heard of, and the older or newer twin keeps telling the truth. Severity is a warning rather than a contradiction because Chromium forks and Android WebView ship window.chrome too, and a fork that reimplements loadTimes on a different time base is an honest browser.

How is a headless browser detected?

Read in the wild by

DataDome

Holds several of these doors at once: its VM anchors its whole clock section on the Level-1 navigationStart, while the main tag independently reads the Level-2 navigation entry and separately enumerates window.chrome's own keys to confirm loadTimes and csi are present and reachable.

out.txt 21645 (addr 0x15a00) GET_PROP_IMM "navigationStart"; payload uKVCRV="http/1.1" (nextHopProtocol) and SYMmJy="navigation" (entryType) exist only on PerformanceNavigationTiming; O1xeSh=",loadTimes,csi,app" enumerates window.chrome

glizzykingdreko/datadome-encryption — a real 232-field captured payload

Akamai

Devotes a whole signal category to timing — navigation timing, resource timing, first paint, DOM-ready — collected per session.

analysis/signal_categories.md, section 5 "Timing Signals": Navigation timing (performance.timing entries), DOM ready timing

Edioff/akamai-analysis — Bot Manager v2 signal inventory

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

Other checks in Clocks & ledgers

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 Clocks & ledgers 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 Clocks & ledgers — the family navigation-origin-consensus belongs to.