Audio fingerprinting is a method to uncover & track users without cookies, even in incognito browsers. We found it on 20 major sites, after pulling on a thread about an AliExpress tab breaking someone’s Bluetooth headphones.
A name is registered in a normal window, then the same URL is opened in a fresh incognito window: no cookies, empty localStorage, no login — and the page still names the visitor, because both windows produce the same device hash.
The whole demo is two files: a page that measures your device, and a server that keeps a map from those measurements to a name. There is no cookie, no account, no client-side storage of any kind.
public/fingerprint.js
collects signals any page can read without asking:
audio OfflineAudioContext: a ~10 kHz tone through a DynamicsCompressor,
rendered into a buffer (never to a speaker), samples summed.
Your CPU and audio stack round the maths their own way.
webgl unmasked GPU vendor + renderer string
screen resolution, colour depth
device CPU core count, platform, timezone
canvas how your machine rasterises one line of text (precise, but
browser-specific — so it is kept in a separate hash)
hardware id = sha256( audio ## webgl ## screen/device )
full id = sha256( audio ## webgl ## screen/device ## canvas )
soft id = sha256( webgl ## device, minus screen size )
hardware id → survives a new profile, incognito, often a different browser
full id → more unique, but changes between browser engines
soft id → last resort for Safari Private Browsing (see below); coarse
enough that whole groups of identical devices share one
Deliberately excluded: devicePixelRatio. It changes with page
zoom, and zoom is per-profile, so it would break recognition for anyone who had zoomed in.
api/fp.js
stores hash → { name, badge }. The badge is the honest part: the emoji and colour
are rolled at random the first time the server sees a device and then kept in that
record. They are not computed from the hash, so two browsers cannot arrive at the same badge
by coincidence:
normal window incognito window ───────────── ──────────────── hash 5f1c9a… ──► hash 5f1c9a… same device, same hash server rolls 🦦 server looks up 🦦 the badge only matches because stores it + "Jared" returns "Jared" the server recognized the hash
Location is read off the IP address every request carries anyway — no
navigator.geolocation call, so there is no prompt to decline. City-level, often
wrong by a metro area, and never stored.
Since Safari 17, iOS and macOS Safari run advanced tracking and fingerprinting protection — on by default in Private Browsing, optional everywhere else. It does not block the APIs used here; it makes their answers unreliable (WebKit’s writeup):
audio samples every sample multiplied by 1 ± 0.001 of fresh random noise canvas pixels per-pixel noise, salted per session and per site screen.width/ replaced by the window’s innerWidth / innerHeight, which .height differs between tabs and shifts as the URL bar collapses
So the hardware and full ids change on every single page
load in a private tab — not just between tabs. There is nothing precise left to match on,
which is why this demo now falls back to the coarse soft id. That one is honest
about what it is: it identifies a kind of device (same GPU strings, same core count,
same platform, same timezone), not a device, so the page labels such a match “a guess”, and
the server refuses to use a coarse key at all once two different people share it. Every
browser sends that coarse id, not just Safari — Safari is only where it is the last thing
standing — so a “guess” anywhere can name the wrong person.
Honest limits: this maps a name you typed to a device hash — it doesn’t discover your real identity out of thin air (a real tracker does that by linking the fingerprint to an account or an ad-network profile). Matching across two different browser engines is unreliable, especially on machines using software rendering. And no microphone is involved anywhere: the audio never leaves the browser’s own pipeline.
From a single instrumented run of 20 major shopping sites (Firefox + Chromium, August 2026). Bot-detection scripts branch per session and region, so treat this as “observed at least once,” not a permanent property of each site.
| Behavior | Sites |
|---|---|
| Held a live audio path open to the speakers (zero volume, never closed — this is what broke the original reporter’s Bluetooth) | aliexpress.com, ebay.com |
| Ran the one-shot offline audio hash | temu.com, shein.com, shopee.com, dhgate.com, banggood.com, walmart.com, ebay.com |
| Shipped audio-fingerprinting code that didn’t fire during our visit | alibaba.com, lazada.com (same Alibaba script), amazon.com (via AWS WAF) |
| Other fingerprinting only (canvas, WebGL, device attributes) — no audio | taobao.com, tmall.com, wish.com |
| Nothing observed | jd.com, miniinthebox.com |
It is not a China story: US eBay held the live audio path open exactly like AliExpress, while Chinese JD.com came back clean. It’s the shared anti-fraud vendors (Alibaba’s fireyejs, HUMAN/PerimeterX, AWS WAF) that spread it — which is also what makes one fingerprint useful for linking you across unrelated sites. No site we tested touched the microphone.