| Component name | audio |
|---|---|
| In the visitorId | yes |
| structuredId group | audio |
| Hashing | always a digest (first 128 bits of SHA-256) |
| Excluded under | Brave (brave_farbling) |
| Inner timeout | 1000 ms |
| Added in | signalsVersion 1 |
WhiskerJS asks the browser to compute a short test tone and pass it through a sound compressor, all in memory, without playing anything. The exact numbers that come out depend on how the browser, the operating system and the processor do floating-point maths, so they differ slightly between devices. WhiskerJS keeps only a short code (a digest) of the end of the sound.
What it reads
audio creates an OfflineAudioContext (or the older webkitOfflineAudioContext) with 1 channel, 5000 frames at 44100 Hz. Inside it:
- an oscillator with type
triangleat 10000 Hz; - a dynamics compressor with threshold -50, knee 40, ratio 12, attack 0 and release 0.25;
- oscillator to compressor to the context’s destination.
It starts the oscillator, renders the buffer with startRendering(), takes channel 0 and keeps the last 500 samples as 32-bit floats. Those 2000 bytes are hashed.
How the technique works
An offline audio context computes sound as fast as it can into memory instead of sending it to speakers. The triangle wave is a simple, known input; the compressor applies non-linear gain changes that exercise the audio engine’s maths. Small differences in how engines implement these nodes, and in the CPU’s floating-point behaviour, show up in the last digits of the samples. If all 500 samples are zero, the render produced silence (a sign of blocking), and the component is reported blocked / silent instead of hashing zeros.
Why it helps
The audio stack differs between browser engines (Chromium, Gecko, WebKit), their versions, operating systems and CPU families, while the same setup usually produces exactly the same samples. It is the only member of the audio group of the structuredId, so a change in that part points straight at the audio stack.
Stability
It can change with a browser update that touches the Web Audio implementation, an operating system update, or a change of CPU architecture. WhiskerJS renders it once only: unlike canvas and webgl_image, there is no double render, so a browser or extension that randomises audio reads every time would give a new digest on every run and change the visitorId. Browsers known to do this on purpose are handled through the exclusion table instead.
Browser support and what blocks it
okin all current browsers with Web Audio: Chrome, Edge, Firefox, Safari and mobile browsers.- Brave:
excluded/brave_farbling. - Not excluded under Firefox resistFingerprinting.
blocked/silentwhen a blocker makes the render return only zeros.
Privacy
The output is a computed test tone, not a recording: no microphone, no playback, no audio device. It reveals how the device computes audio and leaves only as a 32-character digest. No permission, no prompt, no request.
How WhiskerJS handles noise and failures
| Status | ruleId | When |
|---|---|---|
ok |
none | rendered; value is a digest |
unavailable |
no_api |
no OfflineAudioContext |
blocked |
no_buffer |
the render gave no buffer |
blocked |
short_buffer |
fewer than 5000 samples |
blocked |
silent |
the last 500 samples were all zero |
blocked |
security_error, threw |
creating or rendering the context threw or rejected |
unavailable |
no_digest |
no Web Crypto |
excluded |
brave_farbling, caller_excluded |
exclusion table or your list |
timed_out |
timeout, aborted |
1000 ms inner timeout, budget, abort |
Example value
From a headless Chromium test browser in a container:
"audio": { "status": "ok", "value": "40febf1c331d3bd4c550bd46ce0e1813", "hashed": true }
Questions and answers
Does the audio signal play a sound or use the microphone?
No. The sound is rendered offline into a buffer in memory. No audio device is opened, nothing is played and the microphone is never touched.
Why is audio excluded in Brave?
Brave adds per-site, per-session noise to audio reads. Reading it would only make the id change, so the exclusion table skips it and reports brave_farbling.
Is audio checked for noise like canvas?
No. audio is rendered once and has no double render. A browser that adds random noise to every audio read would change the digest from run to run, which is why such browsers belong in the exclusion table.