The OfflineAudioContext fingerprint is a number your browser computes without making a sound. A script wires a 10 kHz triangle wave into a dynamics compressor, renders about a tenth of a second of it into memory, and adds up 500 of the samples. What comes out depends on how this build of the browser does floating-point maths on this CPU and operating system. Run it twice on one laptop and you get the same digits; run it on a different kind of machine and the last few change.
The OfflineAudioContext fingerprint, step by step
The version most pages run comes from the open-source FingerprintJS library, which credits an earlier project, cozylife's audio-fingerprint. Stripped down, the classic form is about a dozen lines:
const ctx = new OfflineAudioContext(1, 5000, 44100)
const osc = ctx.createOscillator()
osc.type = 'triangle'
osc.frequency.value = 10000
const comp = ctx.createDynamicsCompressor()
comp.threshold.value = -50
comp.knee.value = 40
comp.ratio.value = 12
comp.attack.value = 0
comp.release.value = 0.25
osc.connect(comp); comp.connect(ctx.destination)
osc.start(0)
const data = (await ctx.startRendering()).getChannelData(0)
let sum = 0
for (let i = 4500; i < 5000; i++) sum += Math.abs(data[i])
5,000 frames at 44,100 Hz is about 113 milliseconds, on one channel, and none of it goes to the speaker. The sum at the end is a float with a long tail of digits. Two Chromes on two identical laptops print the same one. Move to another chip family or operating system and the last few digits move with it. Newer FingerprintJS releases changed the graph; the principle did not change.
Why offline? An OfflineAudioContext renders into an AudioBuffer as fast as the CPU can go and never opens an audio device. The Web Audio API specification defines it for producing audio for later rather than for now. Nothing asks permission and nothing plays, and the render is over in a few milliseconds.
Every profile is drawn from one real computer, not from separate listsIn Mosaic: Machines that exist. GPU, screen, CPU and fonts from one real device. Free holds 3 profiles. Pro is $49 a month for any number.
Mosaic is a desktop app
Email yourself the link and open it on your computer.
How it works: Machines that exist
Why the compressor is there
Take the compressor out and the trick mostly stops working: a triangle wave is simple arithmetic, and Chrome on a Mac and Chrome on a Windows PC compute it to nearly the same bits. With the compressor in, every sample goes through a gain curve, a log, an exponent and an envelope that smooths the gain over time. Those are computed by whatever maths library and vector instructions this build was compiled with. The spec describes the curve. It does not dictate how a build for ARM and a build for x86 round the last bit of a 32-bit float, and it does not try.
The errors are tiny, but the envelope carries each one into the next sample. By sample 4,500 they have had a tenth of a second to pile up, so the script reads the tail of the buffer and skips the start.
Where it was first measured in the wild
Steven Englehardt and Arvind Narayanan's 2016 paper, "Online Tracking: A 1-million-site Measurement and Analysis", crawled the top million sites and found scripts reading audio this way. They saw two setups. One fed an oscillator into an AnalyserNode and hashed the frequency data. The other is the one above in outline: an oscillator through a compressor inside an OfflineAudioContext, the output summed and hashed.
They also built a test page and collected the values. Across 18,500 devices they saw 713 distinct fingerprints, about 5.4 bits of entropy. That is far from unique. It means the audio sum puts you in one of several hundred buckets, and the bucket says roughly what kind of machine and browser you are.
Why sites read it so widely
It takes a few milliseconds, no prompt appears, and the value survives a cookie wipe, a private window and a new tab. Five bits is not much on its own and a site does not need more from it. What it wants is a value that stays put between visits and agrees with everything else the browser has said.
The second part is where it bites. Say a browser's WebGL renderer string names an Apple chip, and its audio sum is the one an x86 Windows build produces. Those two cannot both be true, and a site only has to collect the reference sum for each platform once to notice. The same logic makes a canvas hash useful, which is why what a canvas hash reveals reads so much like this page. The full list of values a page can read beside it is in our browser fingerprint glossary entry.
What a defence has to get right
Say you want two profiles on one Mac to have different audio sums. A script will render the graph twice in a row, and again after a restart, and it expects the same samples every time. Meanwhile profile two must come out different from profile one, and only in the last digits, where real hardware differs, never by an order of magnitude.
Most blockers fail the first test. They add random noise on every read, so a script that renders twice and compares sees two answers from one machine, which no real device gives. Patching AudioBuffer.prototype.getChannelData in JavaScript fails it too, by another route: a worker or a fresh iframe reads the buffer through a copy of the function the patch never touched, and the page can also check whether a native function has been swapped out. We wrote up that whole class of failure in why we change fingerprints in C++, not JavaScript.
What Mosaic does with it
Tesseract Chrome, Mosaic's engine, makes the change inside Blink's own offline_audio_context.cc, in C++. When a profile creates an offline context, the engine shifts the rate the render runs at by less than a hundredth of a hertz, by an amount computed from that profile's seed. Every page, frame and worker in the profile sees the same shift, the same graph gives the same sum on every read and every launch, and a second profile on the same computer gives a different one. Our comparison script, run against Google's unpatched Chrome for Testing of the same major on the same Mac, printed canvas stable, audio stable on its noise line.
The seed also survives a hardware repair. When Mosaic redraws a profile's machine to fix a mismatched GPU or screen, the canvas and audio identities are kept, because those are what a site already recognises the profile by. How the rest of a profile's hardware is drawn from real machines is on the real fingerprints page.






