Skip to main content

Browser stealth explained: audio fingerprinting

September 14, 2026
Share

Browsers can produce different results from the same silent audio calculation. Comparing those results can reveal both fingerprints and inconsistencies.

A website can make a browser generate and process a tone without playing any sound or recording a microphone. The result is a list of numbers. Small differences in the browser's audio software can make those numbers useful as a fingerprint.

Bot protection collects this signal too. A 2026 study observed audio data collection in a HUMAN Security fingerprinting script. HUMAN, formerly PerimeterX, combines fingerprinting with other methods in Bot Defender.

Changing the returned numbers can make a fingerprint less useful. It can also create inconsistencies that a page can check.

Where the differences come from

Browsers can process audio entirely in memory using OfflineAudioContext. A common fingerprinting recipe generates a tone and passes it through a compressor, which adjusts its loudness. The page then reads the resulting samples: numbers describing the wave at successive moments.

Different browser implementations can produce slightly different samples. Because this calculation runs in software, the differences do not require a different sound card.

We ran the same recipe in Chromium 141 and Firefox 142 on one Linux machine. At the same point in the output, Chromium returned about 0.08868 and Firefox about 0.07105. The computer and inputs stayed the same; changing the browser changed the result.

Chromium · same Linux machine1 kHz triangleCompressor0.060.080.104500 → 0.0886757374Firefox · same Linux machine1 kHz triangleCompressor0.060.080.104500 → 0.0710534304
0.0 / 6s
Captured in Chromium 141 and Firefox 142 on the same Linux machine, using identical audio parameters.

Many users still share a result. A 2021 study found 59 distinct compressor fingerprints among 2,093 participants. Audio can help separate browser environments, but those groups can each contain plenty of people.

What adding noise changes

An audio defense can adjust the samples before a page reads them. Where it reuses those adjustments matters: the same result might persist across repeated reads but change for another site or session.

WebKit's account of Safari's protections describes adding noise to exposed audio and later keeping it consistent for the same buffer values. Fresh random noise makes repeated reads disagree. If that noise is independent and averages to zero, repeated measurements can also help estimate the original samples.

A consistent adjustment avoids that particular problem. The browser still needs to give matching answers when the page reads the same audio another way.

How two reads reveal a mismatch

The browser stores processed audio in a buffer. A page can read it directly with getChannelData() or copy it with copyFromChannel(). Both should return the same samples once processing has finished, as long as nothing changes the buffer between reads.

Suppose a browser modification changes only the direct read. The page compares it with a copy and finds two different answers for the same sample. It can detect the inconsistency without knowing the original fingerprint or looking up a device in a database.

getChannelData()Same completed audio bufferSampleReturned value45000.08867573745010.12498194045020.162549525Only this return path is modifiedNo device database neededcopyFromChannel()Same completed audio bufferSampleReturned value45000.08867573745010.12498194045020.162549525Underlying samples unchangedSame sample, different answers
0.0 / 5s
Baseline API reads captured in Chromium. A one-sided sample change is modeled; this illustrates a CreepJS check, not a measured commercial detection rule.

The open-source test CreepJS performs this comparison. Even if each method returns a stable answer on its own, their answers need to agree with each other.

Simply scaling every sample by the same amount has another weakness: the proportions between samples stay the same, apart from rounding. A script can compare those proportions even after the individual numbers change. A historical Brave implementation used this kind of multiplier.

How Notte handles audio

Our Chromium patches adjust individual samples and share those adjustments between both reading methods. The browser applies the change once, so reading the same buffer again does not keep adding noise.

Timing matters too. Applying the adjustment before audio processing finishes can let the browser overwrite it. We apply it when the page accesses the finished output, keeping internal audio processing separate.

Notte sessions provide these browser changes alongside canvas and WebGL protections. The audio reads need to agree with each other as part of a consistent browser environment.

Browser stealth explained: audio fingerprinting | Notte