Skip to content
All fingerprint checksClocks & ledgers

wall-clock and monotonic time advance at the same rate

Check id wallclock-vs-monotonic-rate

What an ordinary browser yields

Over three windows, the two clocks agree on elapsed time to well within a tolerance derived from their own measured ticks.

What a detector infers

A browser owns two clocks and they are not the same clock. Date.now() is wall time: it can be wrong, it can be corrected, it can jump. performance.now() is monotonic from navigation: it cannot go backwards, but it stops when the machine sleeps. What they must agree on is RATE — over any interval, both must report the same number of milliseconds elapsed, because they are measuring the same physics. DataDome's VM captures Date.now() minus navigationStart into one register and performance.now() into another one instruction later, and ships both raw: it never needs to trust either clock, only to subtract them. This check deliberately uses the rate form rather than the anchor form (timeOrigin plus now() reconstructing Date.now()), which two of the audit's other checks already cover. The anchor is latched from the wall clock at navigation, so a single NTP correction after the page loads poisons it permanently and no amount of re-sampling recovers; the rate form is immune to a fixed offset by construction and answers the strictly different question. Two things keep it honest. It takes the best of three windows, because performance.now() rides the platform's monotonic counter and that counter stops across suspend — close a laptop lid mid-audit and one window shows hours of skew, while a clock ticking at the wrong rate corrupts all three. And its tolerance is derived from each clock's own measured granularity rather than a constant, which is what lets Tor Browser and Firefox with resistFingerprinting — both clamping to 100ms — pass, and what makes it widen automatically for a timer-precision preference whose value we could never tabulate.

How to resolve it

A fake-timer shim, a clock offset applied to sell a timezone, or a coarsened now() meant to blunt timing attacks all hook one time source and leave the other telling the truth. Note the severity: this is a warning rather than a contradiction, because suspending the machine mid-measurement is a legitimate cause — which is exactly why the check takes the best of three windows before it says anything at all.

How automation gets caught, layer by layer

Read in the wild by

DataDome

Captures wall time and monotonic time ONE INSTRUCTION APART and ships both raw, so its server can subtract them. It never has to trust either clock — only that they agree.

out.txt 21636-21666 (addr 0x159ba-0x15a63): reg580 = Date.now() - performance.timing.navigationStart, reg581 = performance.now() immediately after; both registers shipped independently

xKiian/datadome-vm — DataDome bytecode VM disassembly

PerimeterX / HUMAN

Its strict backend validates relationships that exist only ACROSS the ev1/ev2/ev3 event sequence — fields that must stay constant, and clocks that must advance monotonically. A payload correct in every single snapshot is still rejected if its clocks do not reconcile across events.

gotchas.md #19: CONSTANT fields must be identical in every event; MONOTONIC fields (performance.now timers, counters, timestamps) must strictly increase across ev1 -> ev2 -> ev3

warterbili/PerimeterX_RE — ev1/ev2 field maps

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 wallclock-vs-monotonic-rate belongs to.