From clocks to hardware signatures
Math tests and pixel hashes tell you about the software stack; timing tells you about the hardware underneath it. A script runs a fixed GPU draw or a WASM SIMD kernel (a CPU-heavy compute task) and measures how long it actually takes on the clock. A real discrete GPU finishes a shader far faster than Chrome's SwiftShader software renderer (which fakes graphics work on the CPU when no GPU is present), and a real CPU's cache hierarchy produces a Prime+Probe latency curve - a known timing pattern from cache attacks - that an emulated environment does not. Academic side-channel work (cache attacks, GPU timing) showed these measurements can even infer what other tabs or processes are doing - which is why browsers coarsened performance.now() and gated SharedArrayBuffer behind cross-origin isolation after Spectre (a 2018 CPU vulnerability that abused precise timers).
Why headless browsers fail timing checks
Headless browsers on GPU-less servers have no graphics chip, so they fall back to software rendering - drawing on the CPU instead. A draw that takes ~2 ms on a real GPU might take 50–200 ms in SwiftShader - a giant, obvious tell. Anti-bots that pair a canvas probe with a timing probe can catch a replayed canvas hash (a saved-and-reused image fingerprint): the pixels look real but the render took software-renderer time. The same logic flags WASM workloads that run at emulated speed. There is no JavaScript fix; you need real (or GPU-accelerated) hardware to produce real timings.
Why timing is hard to fake — and what works
Timing side-channels are powerful precisely because they read the real hardware underneath the browser. Even with performance.now() resolution deliberately coarsened to defend against Spectre, the relative cost of operations - cache hits versus misses, JIT warm-up (the moment the engine compiles hot JavaScript to fast machine code), GPU draw timing - reflects the actual CPU and memory you are running on. You cannot convincingly fake those ratios from JavaScript, because the code you add to fake them also takes measurable time.
So the practical answer is to run on hardware whose timing profile matches the identity you present, rather than to spoof clocks. A datacentre VM running headless Chrome behind a residential User-Agent has a timing signature that does not match a real consumer laptop. Residential and real-device infrastructure - the kind a managed web scraping API runs behind - produces genuine timing characteristics instead of trying to forge them.
