AlterAntiX
Back to blog
Technical14 min read

How Websites Identify You: the Complete Browser Fingerprinting Guide

Sites don’t need a cookie to identify you: the browser hands over dozens of signals on its own — canvas, WebGL, fonts, audio, WebRTC and the TLS handshake. This guide walks through every layer and shows, with a live test, what your browser is exposing right now.

Sites don't need a cookie to identify you. The browser hands over dozens of signals on its own — headers, canvas, WebGL, audio, fonts, WebRTC and the TLS handshake — and together they form something stable enough to recognise the same machine across sessions, across sites and across a cleared cookie jar. This guide walks through every layer and shows you how to read what yours is exposing right now.

What a browser fingerprint is, in one sentence

A browser fingerprint is the combination of everything a website can measure about your browser and device without storing anything on your machine and without asking your permission. No single value identifies you. The combination frequently does.

The classic way to think about it is entropy. Knowing you use Chrome narrows the world down barely at all — most people do. Knowing your timezone narrows it a little more. Knowing your exact screen resolution, your list of installed fonts, your GPU renderer string and the precise output of a canvas drawing operation narrows it enormously. Around 33 bits of entropy is enough to single out one person among everyone alive, and a rich fingerprint gets uncomfortably close to that on its own.

This is not a theory. The EFF's Panopticlick study in 2010 collected fingerprints from hundreds of thousands of volunteers and found that the large majority were unique within the sample — and that was before canvas, WebGL, audio and Client Hints existed as signals. The technique has only gotten sharper since.

Fingerprinting vs cookies: the difference that matters
A cookie is something the site gives you and can be deleted. A fingerprint is something your browser emits and cannot be deleted, because it is not stored anywhere — it is recomputed on every visit from the properties of your machine. Clearing your cookies does nothing to it. That is precisely why it became the tracking method of choice, and why it is the layer that matters if you are keeping accounts apart.

How do sites identify you without using a cookie?

Mechanically, it is unglamorous. A script runs on page load, reads a list of properties, performs a handful of measurements, hashes the result and sends it to a server. The server compares that hash — or the individual components — against what it has seen before. If it matches an existing record, you are the same visitor. If it partially matches, you are probably the same visitor with a changed detail.

The interesting part is what happens on the server side, and it is where most explanations stop too early. Serious detection systems do not just ask "have I seen this fingerprint before?". They ask three further questions:

  • Is this fingerprint internally consistent? Does the platform reported by the user agent match the platform implied by the GPU string, the font list and the audio stack?
  • Is it consistent with the network? Does the timezone match the country of the exit IP? Does the language?
  • Is it consistent over time?Did this account's device signature change three times this week while the login stayed the same?

Those three questions are why crude masking backfires. A contradiction is a much louder signal than an unusual value, because unusual values happen naturally all the time — people do own rare GPUs and install odd fonts — while contradictions essentially do not.

What follows is the stack, layer by layer, from the cheapest signal to read to the one that is hardest to control. Each layer ends with what to look at in your own result.

Layer 1 — HTTP headers and the user agent

Before any script runs, your browser has already introduced itself. Every request carries headers: User-Agent, Accept, Accept-Language, Accept-Encoding, and on modern Chromium a set of Client Hints such as Sec-CH-UA, Sec-CH-UA-Platform and Sec-CH-UA-Mobile.

The user agent string used to be the whole story. It is not any more — Chrome deliberately froze and reduced it, so the string tells you less than it once did and the detail moved into Client Hints. A site that wants more can request the high-entropy hints (full version list, architecture, platform version, model, bitness) and get a much sharper picture than the frozen string offers.

Two things about this layer are routinely missed. First, the order of headers is itself a signal: different browser engines emit them in different sequences, and an HTTP client that sends them in an unusual order stands out even if every individual value is plausible. Second, Client Hints and the user agent are read from different places, which means they can disagree — and a Sec-CH-UA claiming Chrome 133 alongside a navigator.userAgent claiming Chrome 120 is a free, unambiguous tampering signal.

Check it yourself
Open the fingerprint checkerand look at the user agent block. Compare the version in the UA string with the brand list in the Client Hints section. They should describe the same browser on the same platform. If you have ever "spoofed your user agent" with an extension, this is where it shows.

Layer 2 — Canvas and WebGL

This is where fingerprinting stops reading declared values and starts measuring your hardware.

Canvas fingerprinting works by asking the browser to draw something — usually a line of text with a specific font, plus a couple of shapes and gradients — into an off-screen canvas, then reading the pixels back with toDataURL() or getImageData(). The image looks identical to a human. At the byte level it is not: font rasterisation, anti-aliasing, sub-pixel rounding and the GPU's own rendering path all vary between machines. Hash those bytes and you get a value that is stable for a given hardware-plus-driver combination and different across combinations. The technique was formally described in 2012 and has been in production tracking use ever since.

WebGL fingerprinting takes two forms. The direct one asks WebGL for its identity: through the WEBGL_debug_renderer_info extension a page can read the unmasked vendor and renderer strings, which on a Windows machine look something like an ANGLE description naming the actual graphics card and the Direct3D backend. Browsers have been progressively restricting that extension, but on Chromium desktop it remains commonly readable. The indirect form renders a 3D scene and hashes the output, exactly like canvas but with more surface area, plus the list of supported extensions and the values of parameters like maximum texture size.

For a profile-isolation tool, this layer is the hardest to fake convincingly, because the value has to be different per profile and plausible as real hardware and stable across sessions of the same profile. Get any of those three wrong and the masking is worse than nothing. We go deep into why random noise backfires here.

Check it yourself
In the fingerprint checker, note your canvas hash and your WebGL renderer string. Reload the page. The hash should be identical— a hash that changes on every reload is not privacy, it is a signature that says "this browser randomises canvas". Then check that the renderer string matches the operating system your user agent claims.

Layer 3 — Audio and installed fonts

Two quieter signals that behave like canvas, with different physics.

Audio fingerprinting uses the Web Audio API. A script builds a short processing graph — typically an oscillator feeding a dynamics compressor — renders it offline without ever playing a sound, and reads back the resulting floating-point samples. Different audio stacks, different CPU floating-point behaviour and different browser builds produce microscopically different numbers. Sum or hash them and you have another stable identifier, one the user never hears or sees.

Font enumeration is older and still effective, because the set of typefaces installed on a computer is surprisingly personal. It reflects your operating system version, your language pack, the office suite you installed, the design tools you use, the printer driver that shipped fonts along with it. Historically a script would render a test string in a candidate font with a known fallback and compare the rendered width and height; today it can also use document.fonts.check() for the same conclusion with less code. Run that against a few hundred candidate names and you have a list that is often close to unique.

The consistency trap here is specific and common: a profile claiming to be macOS while reporting a font list full of Windows-only families, or claiming Brazilian Portuguese while reporting no Latin-extended coverage at all. Fonts are also where a Linux host frequently gives itself away, since Linux font sets look nothing like Windows or macOS ones.

Check it yourself
Look at the font count and the sample list in your result. Ask whether that list is plausible for the operating system your profile claims to be running. This is the single check people skip most often, and it is one of the easiest for a detector to run.

Layer 4 — WebRTC and the IP leak

WebRTC exists so browsers can do real-time voice and video without a plugin. To connect two peers behind home routers it uses ICE, which gathers candidate addresses: local network interfaces, and a public address discovered by asking a STUN server "what IP do you see me coming from?".

That last part is the problem. The STUN exchange happens over UDP, directly from the browser — it does not necessarily follow the HTTP proxy you configured. So a page can open an RTCPeerConnection, generate an offer, read the ICE candidates and learn a public IP that your proxy was supposed to be hiding. No permission prompt, no visible indicator.

The picture has improved, and it is worth being precise instead of alarmist. Modern Chromium replaces local network addresses with randomised .localmDNS hostnames by default, which largely closed the "your LAN IP is exposed" hole that older articles still warn about. What did not close is the public-address path: if UDP can leave your machine directly, the srflx candidate can still reveal an address that differs from your proxy exit.

Which is why anti-detect browsers treat WebRTC as a per-profile setting rather than an on/off switch. AlterAntiX exposes five modes — block it entirely, report a faked address, report the real one, forward it through the profile's proxy, or disable UDP — because the right answer genuinely depends on the site. A platform that expects working video calls will notice WebRTC being missing; a platform that never uses it will not care. The full breakdown of the five modes is here.

Check it yourself
Run the WebRTC leak test with your proxy active. Compare the address it reports against the exit IP shown in the same result. If they differ, WebRTC is routing around your proxy — and it has been doing so on every site you visited today.

Layer 5 — TLS and JA3/JA4, the layer JavaScript cannot reach

Everything above happens after the connection is established. This layer happens before it.

The first packet of any HTTPS connection is the ClientHello. It announces the TLS versions your client supports, its ordered list of cipher suites, its extensions, the elliptic curves it accepts and the application protocols it prefers via ALPN. Those choices are made by the TLS library compiled into your browser, and they differ meaningfully between Chrome, Firefox, Safari, curl, Python's requests and the Chromium bundled inside a desktop application framework.

JA3, published by Salesforce, was the first widely adopted way to summarise that packet: concatenate the TLS version, ciphers, extensions, curves and point formats, then hash the string. JA4, from FoxIO, is the modern successor and was designed to fix JA3's weakness — Chrome started randomising the order of its TLS extensions, which changed the JA3 hash on every connection and made it useless for identifying Chrome. JA4 sorts the lists before hashing, so randomised ordering no longer breaks it, and it produces a partly human-readable string rather than an opaque hash: protocol and TLS version, whether SNI is a domain or an IP, cipher and extension counts, ALPN, and then truncated hashes of the sorted cipher and extension lists.

The consequence for anyone masking a browser is blunt. JavaScript cannot rewrite the ClientHello. No amount of canvas noise or user agent editing touches it. If your browser's TLS signature does not correspond to any real Chrome build, a detector knows something is unusual before your page has rendered a single pixel — and the operators who look at this layer (Akamai, Cloudflare, DataDome) are exactly the ones sitting in front of the platforms that matter.

The worst case is not a strange TLS. It is a contradicting one.
A profile whose user agent says Chrome 126 while its handshake matches Chrome 131 is worse off than one that made no attempt at all. Each value alone is plausible; together they are impossible, and impossibility is the cheapest thing in the world to detect. The full JA3/JA4 explanation lives here.

How these signals add up into a risk score

No platform publishes its scoring model, and anyone who tells you the exact weights is guessing. What is observable is the shape of the model, and it is consistent across vendors.

Signal typeHow hard to changeHow much it weighsTypical failure
HTTP headers / user agentTrivialLow alone, high in contradictionUA and Client Hints disagreeing
Canvas / WebGLHard to do wellHigh — near-unique per machineNoise without a stable seed
Audio / fontsMediumMedium, high in combinationFont list impossible for the claimed OS
WebRTCEasy to control per profileHigh when it leaksReal address escaping via UDP
TLS / JA3 / JA4Very hard — needs a proxy layerHigh and earlyHandshake matching no real browser
Network / IPEasy to change, hard to make coherentHighExit country disagreeing with timezone

Read the table as a whole and the pattern is obvious: the column that decides outcomes is not "how hidden is each value" but "do the values agree with each other". Four of the six typical failures are contradictions, not exposures.

There is a second dimension worth naming: stability. A fingerprint that never changes identifies a machine. A fingerprint that changes every session identifies a tool. What passes for normal is a fingerprint that stays the same for weeks and then shifts a little when the browser updates — which, incidentally, is why a profile that is regenerated from scratch every time you open it behaves nothing like a real person's computer.

And a third, which is the one most people never account for: context. The same fingerprint carries a completely different weight depending on what the account is doing. A brand-new profile with an unusual signal that immediately starts spending money is treated very differently from a two-year-old account with the same signal that has done nothing surprising. This is why the honest answer to "is this fingerprint safe?" is always "safe for what, on which account, with what history?" — and why nobody can hand you a threshold.

It also means the useful mental model is not a lock but a scale. You are not trying to be undetectable, because you cannot be. You are trying to keep the technical side of the scale quiet enough that it never becomes the thing that tips a decision.

What to do with your result

Run the checker once and you get a snapshot. Run it deliberately and you get a diagnosis. The sequence below takes about ten minutes and each step is reproducible — you can compare your numbers to the expectations stated here.

  • Baseline your normal browser. Load the fingerprint checkerin your everyday Chrome with no proxy. Save the canvas hash, WebGL renderer, font count, timezone and IP. This is what "you" looks like.
  • Reload twice. Every value should be identical across reloads. Anything that changes on its own is either randomised by an extension you forgot about, or genuinely unstable — both are worth knowing.
  • Turn on your proxy or VPN and reload. Now only the IP and possibly the reported country should have changed. If the timezone still says your home country while the IP says another, you have found the contradiction from the previous section in your own setup.
  • Run the WebRTC test with the proxy on. Here. If it reports an address that is not the proxy exit, the leak is real and current.
  • Compare two isolated profiles. If you use a profile tool, open the same checker in two different profiles simultaneously and diff the results. Canvas, WebGL, fonts, screen, timezone and IP should all differ. Anything identical across the two is a link between them.

That last step is the one that separates real isolation from cosmetic isolation, and it is the only test that actually answers the question you care about: would a site conclude that these two profiles are the same machine?

Where AlterAntiX fits

AlterAntiX generates a coherent fingerprint per profile — navigator, screen, canvas and audio noise with a stable per-profile seed, WebGL vendor and renderer, timezone-to-coordinate geolocation, Client Hints kept in step with the user agent, and WebRTC as an explicit five-mode choice. Every profile launches onto its own Fingerprint Dashboard, which reads the live browser APIs and reports what that profile is actually emitting, flagging mismatches such as a timezone that disagrees with the IP country.

And it covers the layer this guide ends on: a per-profile TLS proxy re-emits the ClientHello with real Chrome presets, with user agents deliberately pinned to the versions those presets cover, so the two never contradict each other. The Windows and Linux builds are free to download — get it here. There is no macOS build yet.

What to take away
  • A fingerprint is recomputed on every visit from your hardware and software — clearing cookies does nothing to it.
  • There are five practical layers: headers and Client Hints, canvas and WebGL, audio and fonts, WebRTC, and TLS.
  • Detectors weigh contradictions far more heavily than unusual values.
  • WebRTC can still expose a public address that your proxy was hiding, because it goes out over UDP.
  • TLS is the layer JavaScript cannot reach — and the one most tools leave untouched.
  • The only test that answers your real question is comparing two isolated profiles side by side.

Frequently asked questions

Can I block fingerprinting entirely?

Not without breaking the web. Almost every signal used for fingerprinting is a legitimate API real sites depend on: canvas draws charts, WebGL renders maps, fonts render text. Blocking them wholesale is both conspicuous and destructive. The realistic goal is a coherent, plausible fingerprint rather than an absent one.

Does clearing cookies change my fingerprint?

No. A fingerprint is recomputed from your hardware and software on every visit; it is not stored on your machine, so there is nothing to clear. That is the entire point of the technique.

Does a VPN change my fingerprint?

It changes exactly one component: the IP address and therefore the apparent country. Canvas, WebGL, fonts, audio, screen, timezone and TLS are untouched. A VPN with an unchanged fingerprint often makes things worse, because the network now says one country and the browser says another.

Is incognito mode enough?

No. Private browsing clears local storage; it does not alter a single fingerprinting signal. You can verify that by running the checker in a normal window and an incognito window and comparing the canvas hash.

Which layer should I fix first?

Coherence. Make the timezone match the IP country, the locale match both, and the Client Hints match the user agent. Those are free to fix and are the most commonly triggered contradictions. After that, the TLS layer, because JavaScript cannot help you there.

How often does a fingerprint change on its own?

For an ordinary user, rarely — mostly when the browser or graphics driver updates, or when a font is installed. That slow drift is what normal looks like, which is why a fingerprint regenerated on every launch is itself a signal.

Fingerprint and TLS, actually aligned

AlterAntiX matches the browser fingerprint with the TLS handshake on the same Chrome version. Download and test it yourself.

Download AlterAntiX