Two visitors load the same page on what looks like the same browser. One is a stock MacBook, the other a virtual machine running a headless build. Their user agents match. Their screen sizes match. But when each browser runs a short audio signal through the Web Audio API and reads back the numbers, the outputs differ in the sixth decimal place. That tiny divergence is an audio fingerprint, and it survives things that break easier signals.
Audio fingerprinting exploits a simple fact: rendering sound is math, and the math is not identical everywhere. The same oscillator and compressor, fed the same input, produce subtly different floating-point results depending on the browser build, the operating system audio stack, and sometimes the CPU. This article explains the mechanism, what it does and does not tell you, and how to treat it as one input among many.
The AudioContext pipeline
The technique does not record a microphone. It generates a signal in software and reads the processed output back as an array of numbers. The canonical approach uses an OfflineAudioContext, which renders as fast as the CPU allows instead of in real time and never touches the speakers.
A typical pipeline looks like this:
const ctx = new OfflineAudioContext(1, 44100, 44100);
const oscillator = ctx.createOscillator();
oscillator.type = "triangle";
oscillator.frequency.value = 10000;
const compressor = ctx.createDynamicsCompressor();
compressor.threshold.value = -50;
compressor.knee.value = 40;
compressor.ratio.value = 12;
compressor.attack.value = 0;
compressor.release.value = 0.25;
oscillator.connect(compressor);
compressor.connect(ctx.destination);
oscillator.start(0);
ctx.startRendering().then((buffer) => {
const samples = buffer.getChannelData(0);
// Reduce the samples to a compact, stable value.
let acc = 0;
for (let i = 4500; i < 5000; i++) acc += Math.abs(samples[i]);
const fingerprint = acc.toString();
});
The DynamicsCompressor node is doing the heavy lifting. It is a nonlinear processor, so tiny differences in how each platform implements its curve get amplified across thousands of samples. Summing a slice of the output collapses all of that into a single reproducible number.
Why the numbers diverge
The output varies because the audio rendering path is not standardized down to the last bit. Several layers contribute:
- Browser engine. Chromium, Gecko, and WebKit each ship their own Web Audio implementation with different rounding and buffering behavior.
- Operating system. The OS audio framework and its resampling routines differ across Windows, macOS, Linux, Android, and iOS.
- CPU and math libraries. Floating-point instruction ordering and SIMD paths can nudge the least significant bits.
- Build flags. Two Chromium builds compiled with different optimization settings can diverge, which is part of why some emulated or repackaged browsers stand out.
The result is not high entropy. On its own an audio fingerprint distinguishes device classes and configurations, not individuals. That is exactly why it belongs in a broader model rather than being used alone. If you want the wider picture of how many attributes combine, see browser fingerprinting entropy explained and the what is device fingerprinting primer.
Where it fits among other signals
Audio sits alongside the other rendering-based signals. Each probes a different subsystem and fails in different ways, so together they cover for one another.
| Signal | Subsystem probed | Rough stability | Blocked by |
|---|---|---|---|
| Audio | Web Audio math + OS audio stack | High | Noise injection, disabled context |
| Canvas | 2D raster + font rasterizer | High | Canvas randomization |
| WebGL | GPU + driver | Medium-high | Parameter masking |
| Fonts | Installed font set | Medium | Font enumeration limits |
The practical value of audio is that it does not depend on the GPU. A machine with GPU acceleration disabled, or a headless environment with a software renderer, may produce a bland or absent WebGL fingerprint but still yields a clean audio value. That complementary coverage is the point.
Turning instability into a signal
A subtle but important use of audio fingerprinting is detecting tampering rather than identity. Anti-detect and privacy browsers frequently randomize AudioContext output to defeat tracking. That defense produces its own tell:
- The value changes across two consecutive renders in the same session, which real hardware never does.
- The value is statistically flat or lands on suspiciously round numbers, suggesting a stub rather than a real pipeline.
- The
OfflineAudioContextconstructor is missing or throws, while other modern APIs are present.
Any of these is worth a reason code. A stable, plausible audio fingerprint is a mild positive signal; an unstable or synthetic one is a stronger negative signal. For how that feeds into scoring, see suspect score explained and the broader treatment in detecting anti-detect browsers.
To keep the raw value useful, follow a few implementation rules:
- Render on an
OfflineAudioContextso timing jitter from the main thread never enters the result. - Quantize the summed output to a fixed number of decimal places before hashing, so imperceptible run-to-run noise on legitimate devices does not fragment your identifier.
- Capture the fingerprint once and cache it per session; re-rendering repeatedly wastes CPU and gives an anti-detect browser more surface to vary.
Privacy and consent
Audio fingerprinting is a passive read of device characteristics, so the same legal analysis that applies to other fingerprinting applies here. Under GDPR and similar regimes, reading or storing device characteristics for identification generally requires a lawful basis, and for many use cases that means consent or a legitimate-interest assessment. A self-hosted deployment keeps the raw audio buffer and derived value on infrastructure you control, which simplifies data-residency questions. See is device fingerprinting legal and privacy-preserving fraud detection for the details, and the device fingerprinting pillar for where audio fits in the overall stack.
Frequently asked questions
Does audio fingerprinting play a sound the user can hear?
No. The Web Audio API can render a signal to a buffer without connecting it to the speakers, so the computation is completely silent and requires no user gesture in most browsers.
Is an audio fingerprint unique to one device?
Not on its own. It typically yields a few thousand to a few tens of thousands of distinct values, so it is a contributing attribute rather than a standalone identifier.
Can audio fingerprinting be blocked?
Yes. Some privacy browsers add noise to AudioContext output or disable the offline context, which changes the value or makes it unstable. A good system treats that instability as its own signal.
Audio fingerprinting is not a silver bullet, and no single rendering signal should be. Its strength is coverage: it works when the GPU path is unavailable, it is cheap and silent to compute, and its failure modes are informative. Combined with canvas, WebGL, fonts, and network signals, it helps produce a confidence score that holds up when individual attributes are spoofed. Explore how the signals combine in the playground or wire it up with the SDKs.
Run it yourself
Prynt is open-source, self-hostable device intelligence — visitor IDs, bot & fraud Smart Signals, and behavioral biometrics you own end to end.