Anti-Bot

What Is WebGL Fingerprinting?

What Is WebGL Fingerprinting? — conceptual illustration
On this page

WebGL fingerprinting reads identifying information directly from the GPU. WebGL is the browser feature that lets web pages draw 3D graphics using your graphics card, and a fingerprinting script asks it questions that real hardware answers in revealing ways. The browser exposes the graphics card vendor and renderer string (via WEBGL_debug_renderer_info), the list of supported WebGL extensions, the maximum texture size, the precision of shader operations, and - most distinctively - the pixel output of a known render operation (drawing a fixed image and comparing the exact pixels that come out). The combination is roughly tied to your hardware and survives most user-agent spoofing (faking the browser's identity string), so it keeps pointing at the same machine.

Quick facts

ReadsGPU vendor + renderer string, ~70 extension flags, render output hash
Distinct from CanvasWebGL probes the GPU directly; Canvas probes the 2D drawing pipeline
Common bot tellSwiftShader renderer (Google Inc. SwiftShader) = headless Chrome with no GPU
Block-grade signalRenderer mismatched to platform — e.g. NVIDIA on macOS, llvmpipe on Windows
DefeatsVanilla headless Chrome, default Playwright/Puppeteer

What WebGL exposes

The browser API exposes four classes of identifying data:

  1. Renderer string — the GPU's name, read via gl.getParameter(gl.RENDERER) with the WEBGL_debug_renderer_info extension. Returns strings like "ANGLE (NVIDIA, NVIDIA GeForce RTX 4070 Direct3D11 vs_5_0 ps_5_0, D3D11)" on Windows or "Apple GPU" on macOS.
  2. Extension list — about 70 named extensions (EXT_color_buffer_float, OES_texture_float_linear, etc.), the optional features your GPU and driver support. The exact set varies by GPU model and driver version.
  3. Parameter values — limits the hardware reports, such as max texture size (4K/8K/16K), max viewport dimensions, max vertex attributes, and fragment shader precision (how accurate the GPU's per-pixel maths is). Each varies by hardware tier.
  4. Rendered output — draw a known shape with a known shader (a small GPU program) and hash the pixels read back from the canvas into a short ID. Different GPUs produce subtly different floating-point rounding, anti-aliasing (edge smoothing), and gradient interpolation, so the ID is steady but machine-specific.

Why headless browsers fail WebGL the hardest

A headless browser runs with no visible window, the usual setup for automation. Headless Chrome without a GPU falls back to SwiftShader, Google's software rasterizer - a stand-in that draws graphics on the CPU instead of a real GPU. The renderer string is then "Google Inc. SwiftShader" or "Google SwiftShader" — anti-bot vendors block this string unconditionally because no real desktop user has SwiftShader as their primary GPU. The fallback chain is even worse on Linux: llvmpipe (Mesa's software rasterizer) is an instant tell.

Running headless Chrome with --use-gl=angle --use-angle=swiftshader-webgl still produces a SwiftShader renderer. The mitigations are: (1) run with xvfb (a virtual display) plus a real GPU passed through, (2) spoof WEBGL_debug_renderer_info at the CDP level (Chrome's remote-control protocol) with a believable renderer string, or (3) use a tool like Camoufox or CloakBrowser that patches the renderer at the C++ level (inside the browser engine itself).

The renderer-platform coherence trap

Spoofing the renderer string alone is insufficient. Anti-bot vendors cross-check the claimed renderer against the platform (navigator.platform, navigator.userAgent) and the GPU's expected extension list - in other words, do all the clues agree with each other? A request claiming Windows + Chrome 131 with renderer string "Apple GPU", or macOS with an NVIDIA RTX renderer, gets blocked. The renderer extension set must also match the claimed hardware — a budget integrated GPU advertising the extensions only found on enthusiast cards is a clear tell.

Camoufox's approach is to maintain a database of real (platform, GPU, renderer, extensions, parameters) tuples harvested from real users, and serve a coherent one per session, so every value matches. This is more expensive than spoofing individual values, which is why DIY hardening of WebGL almost always trips at least one cross-check.

Code example

javascript
// What an anti-bot script reads to fingerprint WebGL
function webglFingerprint() {
  const canvas = document.createElement('canvas');
  const gl = canvas.getContext('webgl');
  if (!gl) return 'no-webgl';   // already suspicious

  const debug = gl.getExtension('WEBGL_debug_renderer_info');
  const renderer = debug
    ? gl.getParameter(debug.UNMASKED_RENDERER_WEBGL)
    : gl.getParameter(gl.RENDERER);

  return {
    renderer,                                                 // 'ANGLE (NVIDIA RTX 4070 ...)' or 'SwiftShader'
    vendor: gl.getParameter(gl.VENDOR),
    extensions: gl.getSupportedExtensions().sort().join(','), // ~70 entries
    maxTexture: gl.getParameter(gl.MAX_TEXTURE_SIZE),         // 4096 / 8192 / 16384
    maxViewport: gl.getParameter(gl.MAX_VIEWPORT_DIMS).join('x')
  };
}
// SwiftShader anywhere in the renderer string is a hard block at major vendors.

Related terms

Concept map

How WebGL Fingerprinting connects

The terms most directly tied to this one. Hover a node to see its neighbours, click to preview, drag to rearrange.

0 terms · 0 connections
You are here · Anti-Bot
Building map…

Frequently asked questions

Is WebGL fingerprinting more or less reliable than Canvas fingerprinting?

More reliable for catching headless browsers — SwiftShader is an instant tell that canvas fingerprinting alone cannot catch. But it is less reliable for telling real users apart, because most people have one of a small set of common GPUs (integrated Intel, or Apple GPU on Mac), so many genuine visitors share the same value (high collision rates).

Can I just disable WebGL to avoid the fingerprint?

No — disabling WebGL is itself a strong signal. On a modern browser, calling getContext("webgl") is expected to return a working context. Returning null or throwing an error is what scrapers and Tor Browser do, so anti-bot vendors block that behavior.

What renderer string should a spoofed browser use?

A common real one that matches your claimed platform. The most-used renderers in production traffic are "ANGLE (Intel, Intel UHD Graphics ...)" on Windows, "Apple GPU" on macOS/iOS, and "Mali-G78" on mid-range Android. Pick one consistent with the User-Agent and don't change it within a session.

Last updated: 2026-05-31