IPASIS - IP Reputation and Risk Intelligence API
Blog/Bot Detection

WebGL Fingerprinting: Detect Bots via GPU Signals

How UNMASKED_VENDOR_WEBGL and UNMASKED_RENDERER_WEBGL expose headless browsers — and why it's hard to fake.

April 24, 20268 min read

Every browser exposes GPU information through WebGL. Real browsers running on real hardware report actual GPU vendors — NVIDIA, AMD, Intel, Apple. But headless browsers running in cloud VMs and Docker containers report software renderers like Google SwiftShader or Mesa llvmpipe.

This gap is one of the most reliable bot detection signals available today. Here's how it works, why it's hard to fake, and how to implement it.

How WebGL Fingerprinting Works

The WEBGL_debug_renderer_info extension exposes two critical values:

  • UNMASKED_VENDOR_WEBGL — The GPU manufacturer (e.g., "NVIDIA Corporation", "Apple", "Google Inc. (Google)")
  • UNMASKED_RENDERER_WEBGL — The specific GPU model (e.g., "NVIDIA GeForce RTX 4090", "Apple M2", "Google SwiftShader")

These values come from the graphics driver, not the browser. That's what makes them hard to spoof.

function getGPUInfo() {
  const canvas = document.createElement('canvas');
  const gl = canvas.getContext('webgl2') || canvas.getContext('webgl');
  if (!gl) return { vendor: null, renderer: null };

  const ext = gl.getExtension('WEBGL_debug_renderer_info');
  if (!ext) return { vendor: null, renderer: null };

  return {
    vendor: gl.getParameter(ext.UNMASKED_VENDOR_WEBGL),
    renderer: gl.getParameter(ext.UNMASKED_RENDERER_WEBGL),
  };
}

What Real Browsers Report

On actual hardware, you'll see specific GPU names:

| Platform | Vendor | Renderer | |----------|--------|----------| | MacBook Pro M3 | Apple | Apple M3 Pro | | Windows + NVIDIA | Google Inc. (NVIDIA) | ANGLE (NVIDIA, NVIDIA GeForce RTX 4070...) | | Windows + AMD | Google Inc. (AMD) | ANGLE (AMD, AMD Radeon RX 7900 XTX...) | | iPhone 15 | Apple Inc. | Apple GPU | | Android (Pixel) | Qualcomm | Adreno (TM) 740 | | Linux + Intel | Intel | Mesa Intel(R) UHD Graphics 770 |

The key pattern: real GPUs have specific model numbers. No two GPU families produce identical strings.

What Bots Report

Headless Chrome in a Docker container or cloud VM has no physical GPU. The browser falls back to software rendering:

| Environment | Vendor | Renderer | |------------|--------|----------| | Headless Chrome (default) | Google Inc. (Google) | Google SwiftShader | | Puppeteer on AWS Lambda | Google Inc. (Google) | Google SwiftShader | | Chrome in Docker | Google Inc. (Google) | ANGLE (Unknown, SwiftShader...) | | Playwright on CI | Google Inc. (Google) | Google SwiftShader | | VirtualBox VM | VMware, Inc. | Chromium or llvmpipe | | Linux headless (Mesa) | Mesa | llvmpipe (LLVM 15.0.7, 256 bits) |

"Google SwiftShader" is the single most common bot fingerprint. If you see it, there's a >95% chance the request comes from an automated browser.

Detection Logic

function isLikelyBot(gpuInfo) {
  if (!gpuInfo.vendor || !gpuInfo.renderer) return true; // No WebGL = suspicious

  const renderer = gpuInfo.renderer.toLowerCase();
  const vendor = gpuInfo.vendor.toLowerCase();

  // Software renderers (no real GPU)
  const softwareRenderers = [
    'swiftshader', 'llvmpipe', 'softpipe',
    'virtualbox', 'vmware', 'parallels',
    'microsoft basic render', 'mesa',
  ];

  if (softwareRenderers.some(sr => renderer.includes(sr))) return true;

  // Vendor is "Google" but renderer isn't a real Google GPU (Tensor)
  if (vendor.includes('google') && !renderer.includes('tensor')) {
    if (renderer.includes('swiftshader') || renderer.includes('angle')) return true;
  }

  return false;
}

Why This Is Hard to Fake

Puppeteer stealth plugins can override navigator.webdriver, navigator.plugins, and dozens of other properties. But spoofing WebGL renderer output requires either:

  1. Kernel-level GPU passthrough — Attaching a physical GPU to the VM (expensive, defeats the purpose of cheap bot infrastructure)
  2. Intercepting WebGL calls at the driver level — Patching Chrome's ANGLE rendering layer (requires rebuilding Chromium from source)
  3. Running a real browser on real hardware — Which is what legitimate users already do

Most bot operators use cloud VMs at scale. Adding a GPU to each VM costs $0.50-3/hour — making large-scale bot attacks 10-50x more expensive.

Combining WebGL with Other Signals

WebGL fingerprinting alone isn't enough. Sophisticated bots may use GPU-enabled VMs. Combine it with:

  • IP intelligence — Is the IP from a datacenter or residential network? A "real GPU" from an AWS IP is still suspicious.
  • Behavioral analysis — Does the user interact like a human? Mouse movements, scroll patterns, timing.
  • TLS fingerprinting — Does the TLS client hello match the claimed browser?
  • Canvas fingerprinting — Does the canvas rendering output match what that GPU should produce?

How IPASIS Handles This

IPASIS combines WebGL signals with IP intelligence and device fingerprinting to produce a single trust score (0-100). A request from a SwiftShader browser on a datacenter IP scores very differently from a real GPU on a residential connection.

The API does this in under 20ms:

curl "https://api.ipasis.com/v1/score" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{"ip": "34.170.211.100", "signals": {"gpu_vendor": "Google Inc. (Google)", "gpu_renderer": "Google SwiftShader"}}'

Get a free API key — 1,000 requests/day, no credit card required.

Key Takeaways

  1. UNMASKED_VENDOR_WEBGL and UNMASKED_RENDERER_WEBGL are among the strongest bot detection signals available in the browser.
  2. "Google SwiftShader" = software renderer = no real GPU = likely a bot.
  3. This is hard to fake because spoofing GPU output requires expensive hardware or Chromium source modifications.
  4. Combine with IP intelligence for the best results — WebGL + IP reputation catches 95%+ of automated traffic.
  5. IPASIS scores all of this in <20ms via a single API call.