Skip to content
Back to blog
fingerprintingwebglgpu

WebGL and GPU fingerprinting

How WebGL exposes your graphics vendor, renderer and rendering quirks, and why GPU signals must stay consistent with the rest of a profile.

VTVeilBrowser Team3 min
WebGL and GPU fingerprinting

TL;DR

WebGL reveals your GPU vendor and renderer strings plus subtle rendering differences. These are highly identifying and must agree with the profile's OS and canvas. Emulate a believable GPU consistently, and do not leak the host's real one.

WebGL gives web pages access to hardware-accelerated graphics. In doing so, it exposes a lot about the machine underneath.

Two GPUs producing different renders and fingerprints

The signals WebGL exposes

  • Vendor and renderer strings: via the WEBGL_debug_renderer_info extension, e.g. ANGLE (NVIDIA GeForce RTX 4070 ...). These are extremely identifying.
  • Supported extensions and parameters: max texture size, precision, and dozens of capability values that vary by GPU and driver.
  • Rendering output: like canvas, rendering a scene and hashing the pixels yields a device-specific value.
webgl-probe.js
const gl = document.createElement("canvas").getContext("webgl");
const info = gl.getExtension("WEBGL_debug_renderer_info");
const vendor = gl.getParameter(info.UNMASKED_VENDOR_WEBGL);
const renderer = gl.getParameter(info.UNMASKED_RENDERER_WEBGL);

Why it is tricky to spoof

The GPU signal is not one value; it is a whole cluster that must be self-consistent:

  • The renderer string must match a plausible vendor.
  • Reported parameters must match what that GPU actually supports.
  • The rendered pixels must be consistent with the claimed GPU and the OS.
  • All of it must agree with the canvas, user-agent and platform.

Faking just the renderer string while the parameters and pixels betray a different GPU is worse than not faking at all.

Consistency across the profile

A believable profile presents one coherent machine. In VeilBrowser the GPU story is part of the browser build you select, so by default the vendor string, the WebGL parameters and the rendered pixels agree with each other and with the profile's platform. That coherence is the point. The renderer criterion steers selection when you need a GPU class, matching against the unmasked renderer string, and launch arguments are there for advanced cases that need a value pinned explicitly. In headless and GUI modes the signals stay identical, which matters for automation. See fingerprints.

Headless pitfalls

Headless browsers often fall back to a software renderer (like SwiftShader), which is a well-known automation tell. A profile that claims a consumer GPU but renders with a software backend is easy to flag. Consistent GPU emulation avoids that mismatch.

FAQ

Try it

Launch profiles with consistent, believable GPU signals across headless and GUI. Get started or read the connect guide.

Related posts