Category: Hardware / Audio Processing
1. Description
Audio fingerprinting uses the Web Audio API to measure how a device's audio hardware and software stack process sound. The AudioContext, OscillatorNode, and DynamicsCompressorNode produce output that varies by:
- Audio driver implementation (ALSA, PulseAudio, PipeWire, CoreAudio, WASAPI)
- Hardware DAC/ADC characteristics
- Sample rate conversion algorithms
- Dynamics compression behavior (threshold, knee, ratio curves)
- Audio buffer handling and latency
- FFT implementation differences
2. Vectors
2.1 DynamicsCompressor Fingerprinting
const ctx = new AudioContext()
const osc = ctx.createOscillator()
const compressor = ctx.createDynamicsCompressor()
compressor.threshold.value = -50
compressor.knee.value = 40
compressor.ratio.value = 12
osc.frequency.value = 1000
osc.type = 'sawtooth'
osc.connect(compressor)
const dest = ctx.createAnalyser()
compressor.connect(dest)
const buffer = new Float32Array(dest.fftSize)
dest.getFloatFrequencyData(buffer)
const hash = md5(buffer)
Entropy: ~8-12 bits
Stability: High across sessions, moderate across browser updates
2.2 AudioContext Base Latency
const ctx = new AudioContext()
const latency = ctx.baseLatency
Entropy: ~4-6 bits
Stability: Very High hardware-dependent
2.3 Additional Audio Signals
| Signal |
Description |
Entropy |
sampleRate |
Audio context sample rate (44100, 48000, etc.) |
~1-2 bits |
maxChannelCount |
Max audio channels supported |
~1-2 bits |
| Channel count mode |
'explicit' vs 'clamped-max' vs 'max' |
~1-2 bits |
| FFT size variations |
Different FFT implementations |
~2-3 bits |
3. Attacker's Strengths
| Strength |
Explanation |
| Hardware-locked |
Audio fingerprint is determined by audio hardware and drivers |
| No permission required |
AudioContext can be created without user consent |
| Fast |
Fingerprint generation takes ~50-100ms |
| Background |
Does not play audible sound |
| Passive user |
User cannot tell it's happening |
4. Attacker's Weaknesses
| Weakness |
Explanation |
| Blockable |
AudioContext can be disabled (Firefox resistFingerprinting blocks it entirely) |
| Browser-dependent |
Same hardware + different browsers can produce different outputs |
| Driver updates change it |
Audio driver updates can invalidate stored fingerprints |
| Noise floor changes |
Background noise affects DynamicsCompressor output |
| Lower entropy than GPU |
~8-12 bits vs ~20+ bits for WebGL |
5. Detection of Tampering
| Technique |
How It Works |
| Flattened output detection |
All values returning -100dB is not natural |
| Cross-read comparison |
Read audio buffer twice, compare for injected noise patterns |
| Base latency check |
Unusual latency values suggest override |
| Sample rate consistency |
Contradicts other signals (rare sample rate + common browser) |
6. Mitigations for Obscura
6.1 What Obscura Can Do
| Mitigation |
Effectiveness |
Detectability |
Implementation |
| Block AudioContext entirely |
High |
Medium |
JS: AudioContext undefined |
| Flatten compressor output |
Medium |
High |
Override getFloatFrequencyData |
| Block audio base latency |
Low |
Medium |
Override baseLatency getter |
| Round sample rate |
Low |
Low |
Override sampleRate getter |
6.2 What Obscura Cannot Do
| Cannot |
Why |
| Change real audio processing |
Audio processing is local hardware |
| Spoof DynamicsCompressor output |
Output depends on physical audio DSP |
| Normalize across users |
Different hardware different processing |
| Remove timing side channels |
Audio timing is measurable even with blocked API |
6.3 Recommended Approach
1. Block AudioContext entirely (high value, low cost)
2. Accept residual risk (audio alone is ~8-12 bits, insufficient alone)
7. Research References
- Acar, G. et al. (2014). "The Web Never Forgets: Persistent Tracking Mechanisms in the Wild." CCS 2014.
- Englehardt, S. & Narayanan, A. (2016). "Online Tracking: A 1-million-site Measurement and Analysis." CCS 2016.
- FingerprintJS (2026). Source code:
src/sources/audio.ts.