How Browser Fingerprinting Actually Works
Delete your cookies, open a private window, switch on a VPN, and most websites can still recognize your browser. They do it by fingerprinting: reading dozens of small characteristics your browser exposes through JavaScript APIs and HTTP headers, then combining them into a signature that is surprisingly close to unique. No identifier is stored on your machine, which is exactly why clearing storage does nothing about it.
Fingerprinting is not inherently sinister. Banks use it to spot stolen sessions, and sites use it to filter abusive bots. But the same mechanism links your activity across sites and across cookie wipes, and it is the reason naive privacy tools fall short. Anyone who manages multiple browser identities professionally, for client work, testing, or research, needs to understand how it actually works.
This post walks through the main fingerprinting surfaces, explains entropy and linkability, shows why badly executed spoofing makes a browser more distinctive rather than less, and ends with how Oculr approaches the problem.
What is a browser fingerprint?
A browser fingerprint is the combination of attributes a website can observe about your browser and device. Individually the attributes are mundane: a screen resolution, a timezone, a list of fonts, a GPU model string. Combined, they form a signature that often distinguishes one browser out of millions. The fingerprint is computed fresh on every visit from what your browser reports, so there is nothing to delete and it works in private windows.
Collection happens two ways. Passive fingerprinting reads what your browser sends anyway: HTTP headers, the user agent, TLS handshake characteristics. Active fingerprinting runs JavaScript that deliberately probes the machine, rendering hidden graphics, timing operations, measuring text. Sites deploy both for fraud prevention, bot filtering, and analytics, and the same techniques power cross-site tracking. Understanding the surfaces involved is the starting point for managing them.
Which signals make up a fingerprint?
Dozens of APIs leak identifying detail, but a handful of surfaces do most of the work in real-world fingerprinting scripts. Each one reflects a different layer of your stack: the browser build, the operating system, the graphics hardware, and the audio pipeline all leave distinct marks.
- User agent and client hints: browser brand, version, and OS, now split between the legacy UA string and structured sec-ch-ua client hint metadata. Scripts cross-check the two.
- Canvas: the page draws text and shapes to an invisible canvas and hashes the pixels. Output varies with GPU, drivers, fonts, and anti-aliasing.
- WebGL: the UNMASKED_VENDOR and UNMASKED_RENDERER strings name your actual GPU, and rendered-scene hashes vary by hardware just like canvas.
- AudioContext: an audio signal is processed offline and the result hashed. Floating-point differences across hardware and OS audio stacks make it identifying.
- Fonts: scripts infer installed fonts by measuring rendered text dimensions. The font set is a strong operating system signal.
- WebRTC: connection negotiation can expose local and public IP addresses, sometimes bypassing the proxy path entirely.
- Client rects: sub-pixel measurements of element bounding boxes vary with the rendering stack, giving another hardware-flavored signal.
What makes a fingerprint identifying?
The useful mental model is entropy, measured in bits. Each attribute narrows down who you could be: knowing your timezone might contribute a few bits, your GPU string a few more, your font list more still. Identifying one browser among billions takes only about 33 bits in total, and studies of real traffic have repeatedly found that the combined surfaces clear that bar for a large share of browsers. No single attribute gives you away; the combination does.
The second ingredient is stability, sometimes called linkability. A fingerprint only tracks you if it reads the same way tomorrow as it does today. That is what lets a site connect your visits after you clear cookies: storage changed, but the signature did not. It also explains a counterintuitive trap: a browser whose values jump randomly on every visit is not anonymous, it is conspicuous, because real devices do not behave that way.
Why is naive spoofing itself a signal?
The obvious fix, overriding a few values with JavaScript, tends to backfire because fingerprinting scripts check for agreement between surfaces, not just individual values. A user agent claiming Windows alongside navigator.platform reporting a Mac, an Apple GPU string, and a macOS font list is a contradiction no real device produces. Detection systems weight these inconsistencies heavily, and for legitimate users the result is concrete: more CAPTCHAs, degraded sessions, and test results that no longer reflect what real users see.
The patching mechanism is detectable too. Spoofing extensions replace native getters like navigator.userAgent with JavaScript functions, but calling Function.prototype.toString on a patched getter returns its source code, where a genuine built-in returns a native code marker. Automation frameworks layered on top inject their own telltale globals. And randomizing values each session produces combinations that sit outside real-device distributions. A spoofed identity has to be coherent, plausible, and stable, which is much harder than overwriting fields.
What does a consistent identity require?
Pulling the threads together, a browser identity holds up only when every layer tells the same story. The reported OS, GPU strings, fonts, screen, and client hints must belong to one plausible device. The values must come from one canonical definition so surfaces cannot drift apart, and they must be implemented deep enough that the getters delivering them look like the browser's own. The identity must stay stable for a given profile across launches, and the network side, meaning IP location, timezone, language, and geolocation, has to match, including after navigations and new tabs where sloppy implementations silently drop their overrides.
How does Oculr approach fingerprinting?
Oculr builds fingerprint control into the browser engine itself, in native C++, rather than layering JavaScript patches on top. Detection-relevant getters return the same native code signatures as stock Chrome. Every spoofed value derives from a single per-profile definition, so the user agent, client hints, screen, GPU strings, fonts, timezone, locale, and geolocation cannot contradict each other, and fingerprints are deterministic per profile: the same profile presents the same identity every launch.
On the consistency-over-time problem, runtime settings for timezone, language, and location re-apply automatically on every new tab and reload, and every release is regression-tested against public fingerprint test suites and real-device baselines. One honest caveat applies to the whole category: detection systems change weekly, so no vendor can truthfully guarantee outcomes. What you can evaluate is the engineering approach, and engine-level implementation is the most defensible one available.
