WebGL fingerprint: why SwiftShader is a bot signal

What a WebGL fingerprint reveals about the graphics card, why SwiftShader rendering is a bot signal, and why a spoofed renderer string contradicts its own pixels.

Davide Grasböck · Founder, Scalebrowser

Published Oct 19, 2026 · 5 min read

Short answer

A WebGL fingerprint names the graphics card through two strings and shows how it draws through the pixels a page reads back, so a spoofed renderer string contradicts its own pixels. A browser without a graphics card draws in software, through SwiftShader or llvmpipe, and Kernel's own documentation calls that "a strong bot signal". A real GPU in a cloud browser is priced to match: Kernel charges 2.88 USD an hour for one, 48 times its headless rate, and only on plans from 200 USD a month.
2.88 USD, an hour for a real GPU, beside a graphics card with two fans

Most server-side browsers have no graphics card, and WebGL tells every page so in one line. The usual fix is to overwrite the renderer string with the name of a real card, which turns an honest server into a machine that cannot exist: the string says one card while the pixels come from another path entirely. This guide covers what WebGL reveals, why drawing in software is read as a bot, and why the only renderer string that holds up is the one the machine really has.

What does a WebGL fingerprint contain?

A WebGL fingerprint contains everything a page can learn about the graphics stack through the WebGL API, from the name of the card to the exact pixels it produces. The Khronos WEBGL_debug_renderer_info extension exists because implementations "might mask the RENDERER and VENDOR strings of the underlying graphics driver for privacy reasons", and it exposes them anyway "in a guaranteed manner for debugging purposes". A fingerprinting script reads five kinds of value.

  • Vendor: the unmasked vendor string, constant 0x9245, which names the maker of the card or the software that stands in for it.
  • Renderer: the unmasked renderer string, constant 0x9246, which names the model and the graphics interface the browser drives it through.
  • Parameters: limits such as the largest texture and viewport the card accepts, and the precision of its shaders.
  • Extensions: the list of WebGL extensions the driver supports, which differs between vendors and driver versions.
  • Readback pixels: a scene drawn off screen, read back with readPixels and hashed, which reflects how the hardware and driver actually rasterise.

The first four are claims the browser makes. The fifth is evidence the hardware produces, and a checker compares the two.

Why is software rendering a bot signal?

Software rendering is a bot signal because its pixels match no consumer graphics card, and Chrome is phasing out the fallback that used to put ordinary visitors on it. SwiftShader is Google's "high-performance CPU-based implementation of the Vulkan 1.3 graphics API", which Chrome used for WebGL on machines without a usable GPU. llvmpipe is the Linux counterpart, Mesa's "software rasterizer that uses LLVM", and it is what a server without a graphics card draws with. Both put their own name into the renderer string, and both produce pixels no consumer card produces.

Chrome is closing the ordinary path to SwiftShader. Its platform status entry marks the automatic fallback as deprecated, with Chrome 139 on desktop as the milestone, after which "WebGL context creation will fail instead of falling back to SwiftShader"; SwiftShader stays available as an opt-in for testing. A browser that renders WebGL through SwiftShader is therefore a machine without a usable GPU or a browser started with that opt-in, and headless test setups are the usual case of both. Reddit's own detection code, which we ran verbatim in September 2026, sorts the WebGL renderer into exactly three classes: swiftshader, llvmpipe and other.

A cloud browser vendor says the same about its own product. Kernel's bot detection documentation states that "Software-rendered browsers produce pixel hashes that don't match any real consumer GPU, which is a strong bot signal on sites with rendering-based fingerprinting", and sells a browser with a real GPU as the answer.

Kernel browserPrice per secondPrice per hourAgainst headlessPlans
Headless0.0000166667 USD0.06 USD1xall
Headful0.0001333336 USD0.48 USD8xall
Headful with GPU acceleration0.0008000016 USD2.88 USD48xStart-Up (200 USD a month) and Enterprise
Source: Kernel pricing and GPU acceleration documentation, per-second rates converted to hours, read 27 September 2026

An agent that runs 8 hours a day on the GPU tier costs 23.04 USD a day at that rate, against 0.48 USD headless. No other line on Kernel's price list multiplies the rate as much as the graphics card does.

What does a spoofed renderer string contradict?

A spoofed renderer string contradicts the pixels, because the string is text the browser returns while the pixels come from whatever really drew the scene. The Puppeteer stealth plugin shows the pattern in its webgl.vendor evasion: it answers "Intel Inc." and "Intel Iris OpenGL Engine" by default, and its own comment notes that the headless default it replaces is "Google SwiftShader". Every installation that keeps the default claims the same Intel card over software-rendered pixels.

We measured how much of the drawing path shows up in the pixels. On 3 July 2026 our engine drew the standard fingerprint canvas on one Windows machine in 12 variants and hashed each result.

What changedVariantsCanvas hash
font hinting, LCD text, subpixel positioning, colour profile, display scale8identical to the baseline in 8 of 8
a different font for the same text3a new hash in 3 of 3
software rendering instead of the graphics card1a new hash
Source: Scalebrowser engine, standard fingerprint canvas, one Windows machine with a graphics card, 12 variants, 3 July 2026

Eight rendering settings left the hash untouched; the drawing hardware changed it. A checker that reads the renderer string and the readback hash therefore holds two independent answers about the same card, and a string that names hardware the pixels did not come from fails that comparison in one step. That is the reasoning behind every surface in fingerprint surfaces: values that describe the machine have to come from the machine.

Scalebrowser follows that rule for the graphics card. It takes the card from the machine when a profile is created and again at every start, refuses to start a profile whose identity names another vendor's card, and refuses to start on a machine that renders without one. Two profiles on the same machine therefore report the same card, which is the honest cost of the rule; the coherence page explains why that trade is made.

Scalebrowser

Scalebrowser gives each agent its own isolated browser with a persistent identity, on your own machine, so a run stays signed in, handles the captcha and finishes without anyone watching it.

See how Scalebrowser does it

How does this fit into the four layers?

The WebGL fingerprint belongs to the second of the detection layers of a browser, the JavaScript fingerprint, and a software renderer found there adds to a score that the connection, the control plane and the input feed as well. How a user agent that names the wrong Chrome version shows is covered in user agent spoofing.

Run it on your own machine

Seven days to try it with your own agents on your own sites. Starting the trial needs a card.

Written by

Davide Grasböck

Founder, Scalebrowser

Builds Scalebrowser, the browser layer for AI agents that runs on your own machine. Measures every change a web page could observe against a real browser before it ships, and writes up the ones that turned out wrong.

All articles by Davide Grasböck