Anti-Bot

What Is WebAssembly Fingerprinting?

By the Scrappey Research Team

What Is WebAssembly Fingerprinting? — conceptual illustration
On this page

WebAssembly (WASM) fingerprinting is a newer anti-bot technique that identifies a browser by measuring how its actual CPU behaves, instead of trusting what the browser says about itself. It works two ways: it runs small bursts of low-level math (instructions called SIMD) and times exactly how fast the processor finishes them, and it builds a far more precise stopwatch than browsers normally allow. Both run as compiled machine code, underneath the JavaScript layer thatCamoufox, CloakBrowser, PatchRight, and similar stealth tools patch. More and more anti-bot systems now run these WASM checks, which means a stealth browser can still be caught even when all of its visible settings look perfect.

Quick facts

Two probe typesSIMD CPU timing + SharedArrayBuffer timer
Timer resolution~100,000 Hz — distinguishes ~6 µs intervals (17× finer than performance.now)
RevealsCPU microarchitecture (NEON, SSE, AVX), vector register width
Reaches belowCamoufox, CloakBrowser, PatchRight, undetected-chromedriver — all operate at the JS layer, not WASM
StatusLive in DataDome scoring, Chrome marked the leak Won't Fix (crbug 40057687)

WASM SIMD probes the CPU itself

Most code on a web page is JavaScript: the browser reads it and runs it line by line. WebAssembly (WASM) is different. It is pre-compiled code that runs almost as fast as a native app, and it can use SIMD instructions — single commands that do the same piece of math on several numbers at once (the kind of work a CPU does for video or graphics). An anti-bot ships a tiny WASM module that runs these instructions in a fixed pattern and times them very precisely.

Why does timing reveal anything? Because different processors finish the exact same work in slightly different ways. Those measurements expose details like how wide the chip's math registers are and which instruction families it supports — NEON on Apple and other ARM chips, SSE on older Intel/AMD, AVX on modern x86 — plus tiny quirks unique to each CPU model. It is a bit like recognising a car from the precise sound of its engine instead of the badge on the front.

Here is the key point for scraping: stealth browsers change what the browser reports about itself, but WASM SIMD measures the real silicon. A genuine Mac with an M2 chip cannot be dressed up to look like an Intel laptop, because the timing fingerprint comes from the chip, not the browser. Source: Anthony Manikhouth, DataDome detection engineer, blog.azerpas.com, May 2026.

SharedArrayBuffer = 17× timer precision

To fingerprint by timing, an anti-bot first needs an accurate stopwatch — and browsers deliberately make their normal one blurry. On ordinary pages Chrome rounds performance.now() to the nearest 100 microseconds, so that hostile sites cannot use ultra-precise timing to spy on the CPU (a family of attacks known as Spectre).

WASM quietly undoes that blur. A single line — new WebAssembly.Memory({shared:true}).buffer — creates a block of shared memory that a background thread (a Web Worker) can count upward as fast as it can using Atomics.add. Reading that counter acts as a stopwatch ticking about 100,000 times a second: fine enough to tell apart events roughly 6 microseconds apart, about 17× sharper than the timer Chrome means to hand out. (A microsecond is a millionth of a second.)

With a stopwatch that precise, an anti-bot can measure tiny timing differences in things like canvas drawing, JavaScript execution and animation frames — and those differ between real human machines and bots at the sub-millisecond level. This was reported to Chrome as bug 40057687 and marked Won't Fix. Source: Manuel, brokenbrowser.com.

The hyphenation-dictionary probe

The third WASM trick has nothing to do with the CPU. It checks which hyphenation dictionaries the browser ships — the rules that decide where a long word is allowed to break at the end of a line. The three main browser engines bundle slightly different ones: Blink (the engine inside Chrome), Gecko (inside Firefox) and WebKit (inside Safari). A WASM probe feeds in a known phrase, watches where the browser splits it, and from that works out the real engine underneath — even if the User-Agent string (the line of text a browser sends to identify itself) claims something else.

This catches a specific class of scraper: Camoufox claiming to be Chrome. Camoufox is Firefox under the hood, so its Intl hyphenation matches Gecko. A request with a Chrome User-Agent but Gecko hyphenation is unmistakably a Firefox-based stealth tool. Akamai's sensor.js and DataDome's WASM challenge both include this check.

The defence is the same as for the other WASM probes — patch the engine below the JS layer, or use a tool whose hyphenation matches its claimed UA. There is no JS-level workaround.

What this means for browser automation

The decade-long focus on JavaScript-layer browser configuration has hit a ceiling, because this round of fingerprinting happens below the JavaScript layer. A few practical observations: WASM probing is expensive to deploy, so it is concentrated on the most heavily defended sites (the machine-learning systems run by the largest anti-bot vendors). On those targets, a browser running below-the-JS-layer configuration may still differ from real consumer hardware. Over time, the closest match to a real browser will come from real consumer hardware on real ISP networks rather than cloud-hosted browser instances.

Code example

javascript
// What an anti-bot ships in a WASM module to time-fingerprint the CPU.
// Stealth browsers cannot patch this because the work happens natively.

const sab = new WebAssembly.Memory({ shared: true }).buffer;
const view = new Int32Array(sab);

// Spin a worker that increments view[0] as fast as possible
new Worker(URL.createObjectURL(new Blob([`
  const view = new Int32Array(self.sab);
  while (true) Atomics.add(view, 0, 1);
`])));

// Read it ~100,000 times per second — a 17× higher-resolution timer
// than performance.now() on non-isolated pages.
const before = Atomics.load(view, 0);
// ... do a SIMD op ...
const elapsed = Atomics.load(view, 0) - before;

Related terms

Concept map

How WASM Fingerprinting connects

The terms most directly tied to this one. Hover a node to see its neighbours, click to preview, drag to rearrange.

0 terms · 0 connections
You are here · Anti-Bot
Building map…

Frequently asked questions

Can I patch WASM SIMD timing?

Not from the browser layer. WASM SIMD runs natively against your CPU — patching it would mean intercepting at the OS or hypervisor level, which breaks the browser. The only workable mitigation is hardware diversity: real machines produce different SIMD fingerprints naturally.

Do all anti-bots use WASM fingerprinting?

Not yet universally. DataDome is the documented adopter to date. Cloudflare, Akamai, and PerimeterX are believed to be experimenting. Adoption is concentrated on the highest-value targets first, because the WASM probe adds payload size and execution time.

Will Chrome ever fix the SharedArrayBuffer timer?

The Chrome team marked it Won't Fix in crbug 40057687. The trade-off is between blocking timing attacks (which would break legitimate use cases) and the privacy implications of finer timing. The leak is now considered a permanent feature of the platform.

Does Camoufox handle this?

Camoufox patches Firefox's JS-visible APIs at the C++ level. It does not modify the WebAssembly execution layer or SIMD timing output. The same is true for CloakBrowser, PatchRight, and every other stealth tool documented in 2026. This is a layer none of them touch yet.

Why are WASM-based probes so much harder to spoof than JS-based ones?

Normal anti-bot tricks read JavaScript values that a stealth tool can quietly overwrite. WASM is different: it runs as pre-compiled code the page brought with it, so there are no JavaScript functions to swap out or fake. The probe simply reads the result of running real CPU instructions — and the only way to change that result is to alter the browser engine itself.

Last updated: 2026-05-31 · Facts last verified: 2026-06-16