Canvas and WebGL Fingerprinting: How It Works and Why Random Noise Gives You Away
Random canvas noise looks like it hides you, but without a consistent seed it becomes its own signature — more identifiable than not masking anything at all. This piece explains how canvas and WebGL fingerprinting actually work and why coherence beats randomness.
Canvas noise is the most recommended setting in this niche and one of the most misunderstood. Turned on without a stable seed, it does not hide a device — it publishes a new one on every page load, which is a thing no real computer does. Here is how canvas and WebGL fingerprinting actually work, and why coherence beats randomness on a work account.
What canvas and WebGL fingerprinting actually measure
Neither technique reads anything about you. Both ask the browser to draw something and then look at exactly how it came out. The premise is that identical drawing instructions produce subtly different pixels on different machines, because the result passes through a specific GPU, a specific driver version, a specific font rasteriser and a specific compositing path in the operating system. Same instructions, different hardware, different pixels.
What makes this valuable to a tracker is not uniqueness alone — it is stability. A cookie can be deleted; a canvas hash cannot, because it is not stored anywhere. It is recomputed from your machine every time it is asked for, and on an untouched computer it comes back identical for years. That combination, moderately unique and extremely stable, is why canvas has survived every wave of cookie restrictions since it was first documented.
Both signals sit in the browser layer of the identification stack — the part that JavaScript can read, and therefore the part that JavaScript can also rewrite. That matters for the rest of this article, and it is why the network layer discussed at the end behaves so differently. Our fingerprinting guide walks through every layer if you want the full map first.
How the browser turns a drawing into an identifier
The mechanism is short enough to describe completely. A script creates a canvas element that is never shown on screen, draws a fixed payload into it — usually a line of text in a named font, sometimes with a gradient, an emoji or a curve, because those exercise the most rendering paths — and then calls a readback method: toDataURL, toBlob or getImageData. Those return the raw pixels. The script hashes them and stores the hash.
Nothing about that is exotic, which is precisely the problem for anyone trying to defend against it. There is no permission prompt, no visible artefact and no measurable delay. It also cannot simply be blocked: the same three methods are what legitimate applications use to export a chart, crop an avatar or generate a thumbnail. A browser that refused them would break a large part of the modern web.
The variation being captured is real and mostly comes from three places: how the font rasteriser draws glyph edges and anti-aliasing, how the GPU handles gradients and curve smoothing, and which fonts exist on the system at all. Two computers running the same operating system version, the same browser build and the same GPU model tend to agree. Change the driver, install a font pack, or switch from an integrated GPU to a discrete one, and the hash moves.
What WebGL adds on top
WebGL contributes two very different things, and treating them as one is the source of most confusion in this niche.
The first is the image: a 3D scene rendered and read back, hashed the same way as canvas. It is a stronger signal than 2D canvas because more of the graphics pipeline participates in producing it.
The second is the metadata: descriptive strings the API hands over for free. The two that matter are the unmasked vendor and the unmasked renderer, and the renderer in particular is remarkably talkative. A real Windows machine returns something like an ANGLE string naming the GPU model and the Direct3D backend. A Linux machine returns an OpenGL string. A Mac returns an Apple string mentioning Metal. The renderer does not merely describe a graphics card — it describes the graphics stack, and the graphics stack describes the operating system.
Does random canvas noise protect you or expose you?
It exposes you, when it is done the common way. The reasoning is worth following slowly, because the intuition points in the wrong direction.
A real user has one canvas hash. It is the same on Monday and the same in March. It survives browser updates and only moves when something material changes on the machine — a driver update, a new monitor, a font installation. A platform that has seen your account fifty times has seen that same hash fifty times, and that consistency is one of the reasons it trusts the session.
Now add per-call random noise. The hash is different on every page load. Not different in a way that hides the device — different in a way that says the device is impossible. The platform is not looking for a specific hash, it is looking at the history of hashes for this account, and an account whose device changed identity forty times this week is more interesting than one it never managed to identify at all. Randomness did not remove the signal; it replaced a boring signal with an alarming one.
There is a second failure mode, more technical and easier to prove. Noise implementations have to modify pixels, and modifying pixels in the wrong place leaves evidence. The classic case is the transparent pixel: a test creates a one-by-one canvas with alpha set to zero and reads the four channel values back. A real browser returns zero, zero, zero, zero. A naive noise routine that walks the pixel buffer and nudges the red channel returns a one in the red channel of a fully transparent pixel — a value that cannot occur naturally. We know this failure well because our own noise implementation had it, and it was caught by exactly that test before shipping. The lesson is not that our code was bad; it is that the surface area for this mistake is large, and every tool that injects noise is exposed to it.
Why noise without a consistent seed becomes a signature of its own
Consider what the platform can build from three visits. With a stable hash it records one value and moves on. With randomised noise it records three different values from the same logged-in account, on the same connection, minutes apart. That pattern is not merely suspicious; it is measurable. Distribution of change over time is a feature like any other, and a device whose rendering identity has a variance no physical hardware could produce stands out in exactly the population you were hoping to blend into.
The fix is not to abandon noise but to make it deterministic. If the noise is derived from a seed fixed per profile, the hash is different from other profiles and identical to itself across sessions — a distinct, stable, believable device. That is the difference between a disguise and a strobe light. In our implementation the seed is a thirty-two-character hexadecimal value generated once when the profile is created and stored with it, so a profile with noise enabled produces the same modified hash on every launch.
The difference between masking and being coherent
Masking asks: can the site read the real value? Coherence asks: does everything the site reads describe the same plausible machine? They are different goals, and only one of them survives contact with a modern risk system.
| Approach | What it optimises for | How it fails |
|---|---|---|
| Aggressive masking | Hiding the real value at any cost | Produces impossible or unstable values that no real device reports |
| No protection at all | Being perfectly consistent | Every profile on one machine returns the same hash, so they are all the same device |
| Coherence | A different plausible machine per profile, stable over time | Requires the whole profile to agree — user agent, WebGL, fonts, screen, timezone, TLS |
Coherence is more demanding because it constrains every value at once. Screen resolution has to be one a real display reports. Font list has to match the operating system being claimed. GPU vendor and renderer must belong to the same family — a machine has never reported an Intel vendor with an NVIDIA renderer, and any validator can check that in one line. Device memory must be one of the values the API is allowed to expose. It is more work than flipping a masking switch, and it is the only approach that gets more convincing as the detector gets better.
What Brave does, and why it is not your goal
A fair objection: Brave randomises canvas deliberately, and Brave is not naive. True — and the details make the case. Brave calls it farbling, and the randomised values are derived from a seed that is per session, per site and per storage area, so one site sees a consistent value within a session while two different sites see different values.
The design target there is unlinkability across sites for an anonymous visitor. It works for that. But it makes the browser visible as Brave, and it deliberately gives one site a new identity in the next session — the exact behaviour you do not want on an account that a single platform has known for eight months. Same technique, opposite objective. Copying the technique without the objective is how people end up with a setting that is right for a privacy browser and wrong for a work profile.
How AlterAntiX handles canvas and WebGL
Our defaults follow the argument above, and they are unusual enough in this market to be worth stating outright.
- Canvas and WebGL image noise are off by default. A new profile does not touch the drawn pixels at all. The seed is generated and stored so the option is there, but a profile only gets a modified hash when someone deliberately switches it on.
- WebGL metadata mode defaults to real. The vendor and renderer that go out are the ones the actual GPU reports. Cross-operating-system spoofing on a desktop profile is the loudest tell there is, so the safe default is not to spoof.
- Mobile profiles are the deliberate exception. An iPhone or Android profile has to override the GPU strings even in real mode, because the honest answer on a desktop host would be a desktop GPU under a phone user agent — a contradiction worse than the spoof.
- When a GPU is generated, vendor and renderer come from the same family. The generator picks the renderer from the list matching the vendor it already chose, so an Intel vendor never ships with an NVIDIA renderer.
- Noise, when enabled, is seeded per profile and stable. Same profile, same modified hash, launch after launch — and transparent pixels are skipped, so the transparent-pixel test still returns what a real browser returns.
None of that makes a profile invisible, and it is not meant to. It makes each profile a different, stable, plausible machine, which is the property that actually holds up over months of use.
Run the test on yourself
Do not take any of this on trust, including from us. Open the fingerprint checker in the browser or profile you use for work and read three things.
- The canvas hash, twice. Load the page, note the value, close the profile, reopen it and load again. Same value means a stable device. A new value every time means whatever tool you are using is randomising per call.
- The WebGL vendor and renderer against your declared platform. A Windows user agent should come with a Windows graphics stack. If the renderer mentions a stack from another operating system, you have a contradiction to fix before anything else.
- The same two values across two of your profiles. If two profiles on the same machine return identical canvas hashes and identical renderer strings, they are one device wearing two names, and no amount of proxy separation changes that.
The browser layer is only half the picture. A profile can pass every canvas and WebGL check and still contradict itself one layer down, in the TLS handshake that leaves before any JavaScript runs — that is the JA3 and JA4 problem, and it is the reason we treat the two layers as one job. AlterAntiX is a free desktop download if you want to compare a profile built this way against the one you are running now.
- Canvas and WebGL identify you by how your machine draws, not by anything stored — deleting cookies does nothing to them.
- The WebGL renderer string describes the graphics stack, which describes the operating system. It is a cross-check, not just a value.
- Per-call random noise creates an instability no real device has. On a work account that is a worse signal than the hash it hid.
- Deterministic noise seeded per profile is fine. Randomness without a seed is the failure.
- Brave randomises on purpose for a different goal — unlinkability across sites, not a stable work identity.
- Verify with two loads in one profile and one load in two profiles. Stable within a profile, different between profiles.
Frequently asked questions
Is turning canvas noise on always wrong?
Not always wrong — wrong as a default. Noise protects against correlation across sites that never talk to each other, which is why privacy browsers use it. But on a work account the goal is the opposite: you want the same platform to recognise the same stable device on every visit. In that scenario a shifting hash is a signal, not a protection.
Why do two profiles on the same hardware return the same canvas hash?
Because the hash comes out of the rendered drawing, and the drawing depends on GPU, driver, operating system and font stack — not on the profile. If you want different hashes per profile without enabling noise, vary what actually changes the render: declared fonts, resolution, pixel ratio and the vendor/renderer pair, always within combinations that exist on real hardware.
Which is worse: noise on, or no protection at all?
It depends who you are hiding from. Against an ad network correlating thousands of sites, noise helps. Against a single platform keeping a history of your account, badly implemented noise is worse than nothing, because it creates an instability real users never have and can leave a detectable trace in the drawing itself.
Is spoofing the WebGL vendor and renderer safe?
Only when the string you pick is compatible with the rest of the profile. Claiming an Apple GPU on a Windows profile, or advertising an Intel vendor with an NVIDIA renderer, is a combination that has never existed on a real machine — the cross-check is trivial and the cost is high. That is why, on desktop profiles, passing the real GPU through is usually the safer choice.
How do I know my profile is stable?
Open the fingerprint checker twice in the same profile with a restart in between, and compare the canvas hash and the vendor/renderer pair. If they changed and you changed nothing, the profile is unstable. If they held and they agree with the operating system the profile declares, it is behaving the way it should.
Does AlterAntiX enable canvas noise by default?
No. New profiles are created with canvas and WebGL image noise switched off, and with WebGL mode set to real, passing the actual GPU through. Noise stays available for anyone who wants it, with a fixed per-profile seed, but it is not the default — and the reasoning is in the article.
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