WebGL renderer (software vs hardware)
A hardware renderer string. The check marks SwiftShader / llvmpipe / "Software" as a tell, but at info severity it is excluded from the score — and CPU rasterisation is legitimate on VDI/RDP, with hardware acceleration off, on blocklisted GPUs and on driverless Linux.
What a detector infers
The audit reads UNMASKED_RENDERER through the WEBGL_debug_renderer_info extension and matches it against SwiftShader, llvmpipe and Software. Those names mean the page is being rasterised on the CPU rather than a GPU, which is the default in many headless and container setups — but equally in VDI/RDP sessions, with hardware acceleration switched off, on blocklisted GPUs, and on driverless Linux.
Because CPU rasterisation is a perfectly legitimate state on its own, this check is info severity and is excluded from the score entirely. What makes a renderer string evidence is not its value but its agreement with other surfaces — a detector infers far more from a software renderer that contradicts a discrete-GPU string reported elsewhere than from a software renderer alone.
How to resolve it
Nothing to fix if the software renderer is real; it is a coherent state that many ordinary users report, and this check does not affect the score. Only act if it contradicts a GPU claimed on another surface — then make the two agree, either by giving the browser a real GPU-backed render path (canvas bridge) or by dropping the discrete-GPU string.
Read in the wild by
Commercial detector A
It collects the unmasked WebGL renderer string and its script embeds a full SwiftShader ANGLE renderer string as a literal to compare against.
Decompiled ips.js compares the collected renderer against a hardcoded software-renderer string — 2.txt:32222: r4 = _5784["gpv"]; r5 = r4 === "ANGLE (Google, Vulkan 1.3.0 (SwiftShader Device (Subzero) (0x0000C0DE)), SwiftShader driver)". The gpv value comes from func_01dfb7 (2.txt:31508), which calls getExtension("WEBGL_debug_renderer_info") then getParameter(UNMASKED_RENDERER_WEBGL). The literal is also in the ips.js __strTable at 2.txt:1. Corroborating probe labels from the teardown's 427/427 mapped probe list: gl_unmasked_renderer, webgl1_unmasked_renderer, webgl2_unmasked_renderer.
Commercial detector B
Pulls UNMASKED_RENDERER_WEBGL and UNMASKED_VENDOR_WEBGL through the WEBGL_debug_renderer_info extension and ships each as its own field.
A commercial detector collector `[internal reference] `var r=t[hQ(491)]("WEBGL_debug_renderer_info");r&&(n.unmaskedVendor=Ak(t,r.UNMASKED_VENDOR_WEBGL),n[hQ(492)]=Ak(t,r.UNMASKED_RENDERER_WEBGL))`, where the string table resolves hQ(491)='getExtension' and hQ(492)='unmaskedRenderer'. Both are emitted as their own payload fields — `e["Y1NWWSY1UWk="]=n.unmaskedVendor,e["GwtuAV1qaTY="]=n.unmaskedRenderer` — and those keys carry "Google Inc. (Intel)" and "ANGLE (Intel...)" in captured payloads (`[internal reference]). The same collection appears in `[internal reference]
CreepJS
CreepJS, a research demo rather than a production detector, regex-matches SwiftShader in the worker-scope WebGL renderer string and counts it toward its "like headless" rating.
src/headless/index.ts:89 (abrahamjuliot/creepjs, master): `hasSwiftShader: /SwiftShader/.test(workerScope?.webglRenderer),` — a key of the `likeHeadless` object, enumerated at line 162 (`Object.keys(likeHeadless)`) and scored at line 166 (`likeHeadlessRating = +((likeHeadlessKeys.filter((key) => likeHeadless[key]).length / likeHeadlessKeys.length) * 100).toFixed(0)`), rendered at line 253 as `${likeHeadlessRating}% like headless`.
Every attribution traces to a published artifact. See the sources and their limits.
Nearby checks in Render & GPU
- readPixels writes only the pixels it was asked to read
webgl-readpixels-sentinelreadPixels writes into an array the page supplies, and the WebGL specification is precise about the edges: when the requested rectangle… - A worker OffscreenCanvas encodes the pixels it reads back
offscreen-canvas-exits-agreeA canvas has more than one way out. getImageData hands pixels straight to script; convertToBlob encodes the same pixels into a file, and… - WebGPU's preferred canvas format belongs to the claimed OS
webgpu-canvas-format-vs-osnavigator.gpu.getPreferredCanvasFormat() returns the texture format the platform's compositor wants to be handed, and Chrome on Windows and… - A WebGPU device accepts every limit and feature its adapter advertises
webgpu-device-honours-adapterA WebGPU adapter advertises limits and features, and the device it creates is validated against them by Dawn, Chrome's WebGPU… - WebGPU vendor coheres with WebGL vendor
webgl-webgpu-vendorTwo independent graphics stacks in the same browser are backed by the same physical adapter: this check lowercases the WebGL UNMASKED_VENDOR… - WebGPU's architecture is the one Chrome's own table gives the GPU WebGL names
webgpu-architecture-vs-rendererGPUAdapterInfo.architecture is not free text. Chrome's WebGPU implementation derives it from the GPU's PCI device id through its own table… - WebGPU's subgroup size is the wave width of the GPU WebGL names
webgpu-subgroup-vs-rendererChrome's WebGPU implementation (Dawn) reports GPUAdapterInfo.subgroupMinSize from the driver: on Windows the Direct3D 12 backend reads… - WebGPU's features and limits fit the hardware GPU WebGL names
webgpu-features-vs-rendererOn Windows, Chrome's WebGPU runs on Direct3D 12, and Direct3D bounds what an adapter can expose: DXGI has no ASTC or ETC2 formats at all, BC…
Clearcote is a browser built for fingerprint coherence
It is a Chromium fork, maintained by the same people who wrote this reference. It ships as a compiled browser rather than as a stealth script injected into someone else's — which is a description of how it is built, and is not an argument about how it behaves on this check.
This audit takes no position on how Clearcote scores on Render & GPU checks, on this one, or anywhere else. It has no baseline corpus of other people's fingerprints to rank you against and no vendor scoreboard — nearly every check is self-referential, asking one browser the same question through two independent APIs and reporting whether both answers can be true at once. It runs identically on any browser, including ours. Run it on yours and read the result yourself.
See the other checks in Render & GPU — the family webgl-not-software belongs to.
