Compare with another capture
Paste the JSON copied from another browser (or drop the downloaded file). Timing fields are ignored by default because they change on every run.
The vmdata vector — 24 slots, the thing to compare
This is the payload the VM assembles and ships. Each row is one slot, produced by the module linked on the right. The cards further down are the full transcriptions those values come from — useful for understanding a check, too verbose for diffing two browsers.
Module detail — full transcriptions (…)
What am I looking at?
vmdata.js is hCaptcha's api.js bundle — 550 KB of plain minified
JavaScript, not a WASM script. Its browser checks live in two layers, and every card
below is one extracted module that reproduces the original reads in the original order, with
the original guards, coercions and fallbacks.
- vmdata is one array of 24 slots. Slot i is the VM's global slot
v(112+i); slot 23 is a constant baked into the bundle. Most slots are a single probe —devicePixelRatio,screen,visualViewport, the navigation-timing duration, a DOM-shape census, the WebAssembly tamper probe, a cyrb53 hash ofwindow.hcaptcha's own method source, an AI-agent (document.modelContext) probe. Slots 4 and 8 are whole subsystems — the behavioural recorder and the form + perf scanner — serialised wholesale. - Membership was decided by measurement, not inference: change one input, collect
vmdataagain, and see which slot moves. Checks that moved no slot were archived even though they are part of the VM. - The VM reaches the browser through only 34 distinct globals, and touches no
navigator, canvas, WebGL, AudioContext, fonts, Battery or timezone at all. - partial on a card means the module's own header says its transcription is not exact, and why. varies means it was measured to change between runs, so it is excluded from the page hash.
A handful of checks are deliberately described but not fired — the asset-host probe does not issue its request, and the Sentry modules restore every global they wrap. Nothing here leaves the page: no capture is sent anywhere.
Special values that JSON cannot carry are written as «undefined»,
«NaN», «function name», and so on. Each card's source link
opens the exact module that produced it.