Canvas and WebGL Fingerprints: Why a New IP Doesn't Hide You

Blog / IP & privacy

Canvas and WebGL Fingerprints: Why a New IP Doesn't Hide You

One common reason a site can still recognize you after you change your IP is the Canvas fingerprint and the WebGL fingerprint. The page asks the browser to draw some text or a 3D scene, reads the pixels back, and hashes them. The pixels are determined by your GPU, driver, operating system and font rendering, not by your IP. So after switching routes, opening an incognito window or clearing cookies, the value usually stays the same.

This article starts with two snippets you can paste straight into the browser console so you can see your own rendering hash and GPU model. It then explains why the values are so stable, and finally compares the approaches and trade-offs of the main built-in browser protections. You can compare the results with the "hardware fingerprint" item in cdnping's IP and environment check. That part is computed locally and not uploaded.

How is a Canvas fingerprint computed?

Canvas is the browser's 2D drawing API. A page can draw text, gradients and emoji on an off-screen canvas, then call toDataURL() or getImageData() to read the pixels back.

The same string, "Hello, 你好", does not produce exactly the same pixels on different machines. The differences come from:

  • Font fallback: whether the requested font is installed, and which substitute is used if it isn't.
  • Anti-aliasing and subpixel rendering: Windows, macOS and Linux smooth text differently.
  • GPU and driver: with hardware acceleration on, some drawing is handed to the GPU, and floating-point error and blending differ slightly between GPUs and driver versions.
  • Emoji fonts: each OS ships its own emoji artwork, and they look completely different.

You can't see these differences, but the hash comes out completely different. The site doesn't care about the image itself, only the hash.

Try it yourself: see your Canvas hash in the console

Open any web page, press F12 (Cmd+Option+I on macOS) to open the console, paste the code below and press Enter. It runs locally and sends no data anywhere.

(async () => {
  const c = document.createElement('canvas');
  c.width = 280; c.height = 60;
  const ctx = c.getContext('2d');
  ctx.textBaseline = 'top';
  ctx.font = '16px Arial';
  ctx.fillStyle = '#f60';
  ctx.fillRect(100, 1, 62, 20);
  ctx.fillStyle = '#069';
  ctx.fillText('Hello, 你好 🌏 1.0', 2, 15);
  ctx.fillStyle = 'rgba(102, 204, 0, 0.7)';
  ctx.fillText('Hello, 你好 🌏 1.0', 4, 17);
  const data = new TextEncoder().encode(c.toDataURL());
  const buf = await crypto.subtle.digest('SHA-256', data);
  const hex = [...new Uint8Array(buf)].map(b => b.toString(16).padStart(2, '0')).join('');
  console.log('Canvas hash:', hex.slice(0, 16));
})();

The output is a 16-character hex string. Write it down; you'll need it when checking stability later.

Can a WebGL fingerprint read my GPU model?

Yes, and often verbatim. WebGL is the browser's 3D API. It has a debugging extension, WEBGL_debug_renderer_info, that returns the GPU vendor and model strings. Paste this into the console next:

(() => {
  const gl = document.createElement('canvas').getContext('webgl');
  if (!gl) return console.log('WebGL not available');
  const ext = gl.getExtension('WEBGL_debug_renderer_info');
  console.log('Vendor:', ext ? gl.getParameter(ext.UNMASKED_VENDOR_WEBGL) : gl.getParameter(gl.VENDOR));
  console.log('Renderer:', ext ? gl.getParameter(ext.UNMASKED_RENDERER_WEBGL) : gl.getParameter(gl.RENDERER));
  console.log('Max texture size:', gl.getParameter(gl.MAX_TEXTURE_SIZE));
  console.log('Extension count:', gl.getSupportedExtensions().length);
})();

On Chromium-based browsers on Windows, the renderer line usually looks like ANGLE (vendor, GPU model, Direct3D11 ...), with the GPU model spelled out. Firefox and Safari generalize this string to varying degrees; on Safari you typically see just "Apple GPU".

Beyond the model string, a WebGL fingerprint has two more parts:

  1. Parameters and extension list: maximum texture size, supported shader precision, the extension list and dozens of other items. Combined, they are distinctive.
  2. Rendering hash: as with Canvas, the GPU draws a lit 3D shape and the pixels are read back. This reflects differences in GPU and driver computation directly, which is why it is often called a "GPU fingerprint".

What about audio fingerprinting?

The principle is the same, with sound instead of pixels. A page uses OfflineAudioContext to generate an oscillator wave in memory, runs it through a compressor, and sums the samples. No sound is ever played. Tiny floating-point differences across CPUs, system audio stacks and browser implementations change the last few decimal places of the result.

Audio fingerprints are generally less distinctive than Canvas and WebGL, but they are independent of the other two, so using them together narrows things down further.

Why doesn't it change with a new IP, incognito mode or a restart?

Because these values are not stored anywhere. They are computed on the spot each time. As long as "who does the drawing" hasn't changed, neither has the result. This table shows which actions change it:

What you doDoes the Canvas / WebGL fingerprint change?Why
Change IP, toggle a proxyNoRendering has nothing to do with the network
Incognito window, clear cookiesNoThe fingerprint doesn't depend on local storage
Restart browser or computerNoHardware and driver are unchanged
Update GPU driverPossiblyThe rendering path changed
Major browser version upgradePossiblyGraphics backend or font rendering was adjusted
Toggle hardware accelerationUsuallySwitches between GPU and software rendering
Install or remove fontsCanvas may changeFont fallback results differ
Switch to another computer of the same modelMay be identicalSame hardware and OS give similar results

The last row shows that a Canvas fingerprint alone can't pinpoint one individual. Office PCs from the same purchase batch with the same OS image will likely share a hash. So sites usually combine it with the user agent, screen size, time zone, fonts and other signals, which are broken down in full in What is browser fingerprinting: 20+ signals sites use to recognize you without cookies, and how to check.

This also answers the question in the title: an IP is only a network-layer identity. Changing it changes where you come from, not what device you use. For what an IP itself can reveal, see What your IP address actually reveals.

A step-by-step stability check

Using the two snippets above plus the cdnping check page, verify in this order:

  1. In a normal window, run the Canvas and WebGL code and note the hash and renderer string.
  2. Open an incognito window in the same browser and repeat. In most browsers the results are identical.
  3. Quit the browser completely, reopen it and repeat.
  4. Turn off "Use hardware acceleration" in the browser settings, restart and run the code again. The hash will most likely change, and the renderer may become a software renderer such as SwiftShader. Remember to turn it back on afterward.
  5. Open /en/ip and look at the GPU and rendering information under "hardware fingerprint". Compare it with your console output.
  6. If you use a browser with fingerprint protection, refresh the same site several times, or run the code on a different site, and see whether the hash differs each time.

Step 6 tells you directly which kind of protection your browser uses.

What approaches do built-in browser protections take?

The main approaches fall into three groups. All aim to keep sites from getting a stable, unique value, but the costs differ.

Block reads: Tor Browser

When a page tries to read Canvas pixels, Tor Browser intercepts the call, returns blank data by default, and may prompt the user for permission. WebGL information is also restricted. This is the most direct approach. The cost is that features that rely on reading Canvas (online image editors, screenshot sharing, some CAPTCHAs) stop working.

Make everyone look the same: Firefox resistFingerprinting

Firefox has a privacy.resistFingerprinting option in about:config. When enabled, the idea is to make all users look alike: Canvas reads require permission, the time zone is reported as UTC, and some language and window-size values are normalized. The option originated in patches merged back into Firefox from Tor Browser. Mozilla doesn't recommend that ordinary users leave it on long term, because the wrong time zone affects calendars and the time shown on web pages, and some sites misbehave.

Newer Firefox versions also have a narrower fingerprint protection that applies in Enhanced Tracking Protection's "Strict" mode and in private windows. It adds a small amount of noise to Canvas reads and has fewer side effects than resistFingerprinting.

Randomize: Brave and Safari

Brave's Shields add slight perturbation to Canvas, WebGL and audio reads by default, varying per site and per session. A given site sees a stable value within one session, but a different site or a restarted browser sees a different one, which makes it harder to link you across sites. Safari's advanced fingerprinting protection also uses noise in private browsing.

Here is how the three compare:

ApproachExampleWhat the site seesMain cost
Block readsTor BrowserBlank or fixed placeholder valuesFeatures that depend on Canvas break
Make everyone look the sameFirefox resistFingerprintingThe same values as other users of that kindTime zone and language are altered; some sites misbehave
RandomizeBrave, Safari private browsing, Firefox Strict modeA different value per site per sessionA few detectors treat "the value keeps changing" as an anomaly

Which protection should you choose?

First decide what you're trying to achieve. If you just don't want ad networks tracking you across sites, Brave's defaults or Firefox's Strict mode are enough, and everyday features are mostly unaffected. If you need strong anonymity, Tor Browser's uniform approach is more thorough, because "everyone looks the same" is harder to tell apart than "different every time".

A few points are often overlooked:

One more note: banks, payment providers and account logins use device fingerprints for risk control, to catch account takeover and fraud. This article is about how ordinary users can understand and reduce cross-site tracking. It does not cover bypassing any platform's risk control or detection. When using such services, follow their terms of service and local laws.

How do I read the hardware fingerprint result in cdnping /ip?

/en/ip has two checks, "hardware fingerprint" and "time zone, language and fonts", that look at the same kind of device signals as the console code in this article. Fingerprints are computed locally in your browser and not uploaded; when you generate a watermarked result image, you can choose to hide the IP.

Put the console output next to the check page result and read it like this:

  • The renderer string contains a specific GPU model: the browser isn't masking this item, so it is quite distinctive.
  • The renderer shows a generic name or a software renderer: the browser generalizes it, or hardware acceleration is off.
  • The Canvas result changes after a refresh: the browser is randomizing.
  • The Canvas result is empty or the read fails: the browser is blocking reads.

For what each check means, read it alongside How to read the browser environment check: all 13 items explained. The check methodology and data handling are described on the methodology page.

Related articles

Keep reading