Browser fingerprinting¶
Cookies can be cleared. IP addresses can be hidden behind a VPN. But the browser describes itself to every page it loads. A fingerprinting script, running silently when a page loads, assembles a profile from the properties of the browser and device: the screen dimensions, the installed fonts, the GPU and its driver, the time zone, whether cookies are enabled, the exact version of the rendering engine. Each value is unremarkable on its own. Combined, they can form a distinctive fingerprint good enough to recognise a browser across visits. What gets recognised is the browser environment, and the step from there to a person is a separate one.
The browser introduces itself¶
The script runs in the browser as ordinary JavaScript. No permissions are requested. No download occurs. Some of these properties the browser exposes directly, others can be inferred from how it renders, and the script collects whatever it can observe and combines the results.
collect from browser environment:
user-agent string → browser name, version, OS
screen resolution → width × height in pixels
colour depth → bits per pixel
time zone offset → inferred location
hardware thread count → number of CPU cores
cookie and JS settings → privacy configuration
installed fonts:
for each font in candidate list:
render a string using that font
measure the pixel width of the rendered output
if width differs from default → font is installed
GPU fingerprint:
draw a specific shape using WebGL
read back the pixel values
hash the result → reflects GPU vendor and driver version
combine all collected values
hash the combination → fingerprint string
The font detection step works on differences in rendered text. A script can test a list of candidate fonts, measure
the dimensions each one produces, and sometimes infer which are installed without any font list being handed over,
though a browser supporting the
Local Font Access API can be asked directly.
The WebGL step reads the graphics environment. Rendered output varies with browser, GPU and driver, and
WEBGL_debug_renderer_info exposes the
vendor and renderer strings outright where the browser permits it. Firefox disables that extension under
privacy.resistFingerprinting.
The fingerprint goes to the tracking service and is stored. On a return visit, from any site using the same service, another fingerprint is taken and compared against what was seen before. If enough of the values match, the service treats the browser as the same one. The user has not logged in, has not accepted cookies, and may be behind a different IP address. They are still recognised.
Four quiet attributes¶
greenhouse-attacks fingerprint.py scores a browser against the population AmIUnique publishes from its visitors, 5,525,150 fingerprints collected by a research group at Lille, as the statistics stood on 18 September 2026. What follows is not a measurement of a whole browser fingerprint. It asks how much distinguishing information four published attributes hold on their own.
The measure is surprisal, the cost in bits of naming a value: one bit for a value half the population shares, about ten for a value only one browser in a thousand has. Where attributes are independent, their bits can be added.
Only four attributes are published, and they are the quiet ones:
Attribute |
Distinct values |
Entropy |
|---|---|---|
browser |
121 |
2.02 bits |
operating system |
55 |
2.10 bits |
language |
455 |
2.15 bits |
time zone |
999 |
3.68 bits |
Three browsers scored on those four:
Bits |
Alone among |
|
|---|---|---|
Chrome, Windows, English, UTC+0 |
5.04 |
33 |
Firefox, Linux, Dutch, UTC+1 |
13.40 |
10,809 |
Vivaldi, BSD, Frisian, UTC+1 |
42.17 |
4.9 trillion |
The first row takes the commonest value of each of the four attributes, Chrome at 48.4%, Windows at 44.8%, English at 66.0% and UTC+0 at 21.3%, and that browser is already alone in a group of thirty-three. The second swaps Firefox for Chrome and Dutch for English, and the figure climbs to one in ten thousand. In this population the Dutch value costs 6.75 bits where the English value costs 0.60.
The calculation assumes the four attributes are independent. They are not: browser and operating system travel together. The third row is where the assumption breaks: 42 bits describes a population six hundred times the world’s. The first two rows give a number. The third gives only a direction.
The calculation also leaves out what real fingerprinting leans on, canvas rendering, installed fonts and WebGL among them, because this population publishes none of them. Every figure above therefore describes four attributes and not the identifying power of a browser fingerprint.
None of it is a name, none of it was deliberately supplied as an identifier, and ordinary browsing gives the person no sign that these values are being assembled and sent.
Reading is access¶
Browser fingerprinting is widely used in advertising, fraud detection, and analytics. Its value is its persistence: it survives the privacy measures people commonly take. A person who clears their cookies, uses private browsing, and changes their IP address still presents the same fingerprint if they have not changed their browser, device, or configuration.
Storing nothing is what made the legal position a question. Article 5(3) of the ePrivacy Directive asks for consent before gaining access to information held in a person’s own equipment, and fingerprinting gains access without leaving anything behind. The Article 29 Working Party addressed it in Opinion 9/2014, and the EDPB’s Guidelines 2/2023 read Article 5(3) as reaching techniques that write nothing, on the basis that the act it governs can be the gaining of access to information in the terminal equipment.
In a 2010 sample, the Electronic Frontier Foundation’s Panopticlick study found 83.6% of the browsers it tested to be unique, at 18.8 bits apiece. That figure is sixteen years old. Its successor, Cover Your Tracks, and the independent AmIUnique test a browser against their own current populations.
Looking like everybody else¶
Two defences are available against any given fingerprinting vector, and the Tor Project’s
design document sets them against each other: make
every user of a browser version behave as uniformly as possible, or randomise so that each visit yields a different
fingerprint. Tor Browser chose uniformity, on the grounds that randomisation is difficult to evaluate. Firefox’s
privacy.resistFingerprinting standardises or withholds many of the same values. Using a common browser on a common operating system, without unusual fonts or extensions, works the same way, since more people share that configuration.
Browser extensions are the other route. They block many fingerprinting scripts from running at all, though which extension is available now depends on the browser. Chrome cleared the last Manifest V2 extensions out of its store on 31 August 2026, and uBlock Origin was among them. Its Manifest V3 implementation, uBlock Origin Lite, is a separate extension from the same project. uBO Lite is entirely declarative, an architecture that cannot support dynamic filtering or generic cosmetic filtering. Firefox is unaffected and still runs the full version.
The most comprehensive defence here is the Tor Browser, which aims to put its users into one large common fingerprint.
Last reviewed: 2026-09-19.