Skip to content
All fingerprint checksEnvironment & locale

AudioContext invariants + a deterministic offline render

Check id audio-context-coherence

What an ordinary browser yields

A standard sampleRate, a small positive baseLatency, channelCount within maxChannelCount, channelInterpretation "speakers", and two identical offline renders.

What a detector infers

The check constructs a live AudioContext and reads four invariants — sampleRate, baseLatency, the destination node's channelCount against its maxChannelCount, and channelInterpretation — then renders a fixed OfflineAudioContext graph twice and compares the two results. Each assertion has a physical basis. sampleRate is the hardware's real rate and must be one of the standard values (44100 and 48000 dominate on desktop); baseLatency is a small positive fraction of a second; a destination cannot present more channels than its own maximum, and its interpretation defaults to "speakers". The determinism test is the sharpest: the offline audio graph is a pure function of its inputs on a real engine, so two identical renders must be byte-identical, and when they differ it means the audio stack is injecting per-call noise — the same anti-fingerprinting technique the audio hash exists to expose. A detector reading an impossible sampleRate, a latency or channel layout that cannot occur, or two disagreeing renders infers a synthesised or noised audio stack. Kasada's audio_context_sample_rate, base_latency, channel_count, channel_count_mode and channel_interpretation probes plus its audio_fingerprint read exactly this surface. N/A where Web Audio is unavailable.

How to resolve it

Leave the Web Audio stack native. Do not add per-call noise to OfflineAudioContext output — it makes two identical renders disagree, which is itself the tell. Keep sampleRate and the channel layout consistent with the host's real audio device.

Anatomy of a browser fingerprint: every signal, and why they must agree

Read in the wild by

PerimeterX / HUMAN

Collects an audio fingerprint from an OfflineAudioContext(1, 44100, 44100): a 10 kHz sine oscillator through a fixed-parameter DynamicsCompressor, rendered once, with channel-0 samples 4500-4999 summed by absolute value — the raw sum and a hash of it are both sent. It reads the render output only, not the context's declared parameters.

main.min.js (iFood deployment) `zY()`: `var n=new(hS.OfflineAudioContext||hS.webkitOfflineAudioContext)(1,44100,44100);…var e=n[hQ(469)]();…e.type="sine",zZ(e.frequency,1e4,r);var h=n.createDynamicsCompressor();zZ(h.threshold,-50,r),zZ(h.knee,40,r),zZ(h.ratio,12,r),zZ(h.reduction,-20,r),zZ(h[hQ(470)],0,r),zZ(h.release,.25,r),e.connect(h),h[hQ(471)](n.destination),e.start(0),n.startRendering().then((function(n){var e=0;…for(var r=4500;r<5e3;r++){var h=n.getChannelData(0);h&&(e+=Math.abs(h[r]))}var i=e.toString(),o=i&&iR(i);t({"EX1kN1ccYQI=":i,"Dh47VEt6OW8=":o})}))` — string table decodes hQ(469)='createOscillator', hQ(470)='attack', hQ(471)='connect', hQ(472)='getChannelData'. Both values appear in captured decoded payloads: `"EX1kN1ccYQI=":"126.86972438948578"` (the raw sum) and `"Dh47VEt6OW8=":"2dce8c55c6897067fdf0c76ddf6e6d50"` (its hash). The same routine appears in other PX deployments as `wC()` (Walmart, with a literal `createOscillator()`) and `Ar()` (Total Wine) with identical compressor parameters.

Kasada

Dedicates a whole batch to the audio stack — not just the fingerprint hash but the context's own declared parameters.

audio_fingerprint, audio_context_sample_rate, audio_context_base_latency, audio_context_output_latency, audio_context_channel_count, audio_context_channel_count_mode, audio_context_channel_interpretation, audio_context_max_channel_count

Kasada ips.js teardown — the full 427-probe list

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

Nearby checks in Environment & locale

See all 23 checks in Environment & locale
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 Environment & locale 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 Environment & locale — the family audio-context-coherence belongs to.