Seatext library / BotRefund evidence
Open-Source Tools for Testing WebGL Bot Detection Locally
BrowserLeaks, fingerprintjs2, creepJS, and custom Puppeteer scripts with WebGL readback are the main open-source tools for reproducing and testing WebGL fingerprint anomalies locally. They let you inspect renderer strings, extension lists, and texture readback...
✓ Built for advertisers who need clear, refund-ready traffic evidence.
If you need to test WebGL bot detection on your own machine, start with BrowserLeaks for a quick visual baseline, fingerprintjs2 for a programmable fingerprint snapshot, creepJS for deep canvas and WebGL stress tests, and custom Puppeteer scripts that read back texture pixels to compare against known-good distributions. Each tool exposes a different slice of the WebGL surface that detection engines like BotRefund's WebGL Texture Constraint check evaluate.
Why test WebGL bot detection locally
WebGL fingerprinting works because real GPUs and drivers produce subtle, non-deterministic rendering output that headless browsers and software renderers (like SwiftShader) struggle to replicate. Testing locally lets you see exactly what signals your browser emits before you deploy detection logic or try to harden an automation pipeline. It also helps you understand false-positive risk: privacy tools, virtual machines, and corporate proxies can create anomalies that look bot-like but come from real users.
BotRefund treats its WebGL Texture Constraint signal as one piece of evidence among 106 independent checks, not a standalone verdict. The same principle applies to local testing: a single mismatch rarely proves automation. You need to correlate WebGL anomalies with behavioral, network, and device signals to reach a reliable conclusion.
BrowserLeaks — quick visual baseline
BrowserLeaks renders a WebGL report in the browser showing the unmasked renderer, vendor, version, shading language version, and the full extension list. It also draws a fingerprint canvas and shows the resulting hash. Use it to:
- Confirm whether your browser reports a hardware GPU (e.g., "NVIDIA GeForce RTX 3080") or a software fallback ("Google SwiftShader").
- Compare extension sets across browsers and headless modes.
- Grab a screenshot of the fingerprint canvas for manual diffing.
Limitation: BrowserLeaks is a read-only page. You cannot script it or automate regression checks without wrapping it in a headless driver yourself.
fingerprintjs2 — programmable fingerprint snapshot
fingerprintjs2 (the open-source predecessor to FingerprintJS Pro) collects a broad browser fingerprint including WebGL renderer, vendor, extensions, and a canvas hash. It runs as a small script you can drop into any page or run in Node via JSDOM (though JSDOM lacks real WebGL). In practice you load it in a real browser — headless or headed — and call Fingerprint2.get() to receive a component dictionary.
Key WebGL components it surfaces:
webgl_vendorandwebgl_renderer(unmasked viaWEBGL_debug_renderer_info)webgl_extensionsarray (sorted)canvashash from a drawn fingerprint image
Use fingerprintjs2 when you need a repeatable, JSON-serializable snapshot you can store, diff, or feed into a rule engine. It does not perform texture readback or statistical analysis on its own.
creepJS — deep canvas and WebGL stress tests
creepJS goes further than fingerprintjs2 by running a battery of WebGL and Canvas API tests designed to expose inconsistencies. It checks:
- Multiple context creation paths (
webgl,webgl2,experimental-webgl) - Parameter stability across contexts (e.g.,
MAX_TEXTURE_SIZE,MAX_VERTEX_UNIFORM_VECTORS) - Extension availability and ordering
- Shader precision and floating-point behavior
- Canvas
toDataURLandgetImageDataconsistency
creepJS produces a detailed report with anomaly flags. It is especially good at catching mismatches between WebGL 1 and WebGL 2 contexts, or between reported renderer strings and actual parameter limits — a common tell when a headless browser spoofs the renderer but forgets to align the capability limits.
Custom Puppeteer scripts with WebGL readback
For the closest approximation to what a detection engine sees, write a Puppeteer (or Playwright) script that:
- Launches Chrome with
--enable-webgl --use-gl=desktop(orangle/swiftshaderto simulate software rendering). - Injects a page script that creates an offscreen framebuffer, draws a known pattern (gradient, noise, or a shader with deterministic math), calls
readPixels, and returns the raw pixel buffer. - Computes statistical moments (mean, variance, entropy) of the readback and compares them against a baseline collected from real devices.
Example skeleton:
const puppeteer = require('puppeteer');
async function captureWebGLReadback() {
const browser = await puppeteer.launch({
headless: 'new',
args: ['--enable-webgl', '--use-gl=desktop']
});
const page = await browser.newPage();
const pixels = await page.evaluate(() => {
const canvas = document.createElement('canvas');
const gl = canvas.getContext('webgl2');
// ... shader setup, draw, readPixels ...
return Array.from(pixels); // Uint8Array -> plain array for JSON
});
await browser.close();
return pixels;
}
This approach reproduces the texture constraint logic BotRefund describes: render a known pattern, read back the result, and measure variance. Real GPUs introduce driver-level noise; software renderers often produce clean, deterministic output. You can store baseline distributions per (renderer, OS, browser version) tuple and flag deviations in CI.
Setting up a local testing matrix
To get actionable data, run each tool across a matrix of environments:
| Environment | BrowserLeaks | fingerprintjs2 | creepJS | Puppeteer readback |
|---|---|---|---|---|
| Native Chrome (your laptop) | Baseline | Baseline | Baseline | Baseline distribution |
| Headless Chrome (--headless=new) | Compare renderer | Snapshot diff | Anomaly flags | Variance shift |
| Chrome + --use-gl=swiftshader | Software renderer | Spoofed vendor | Parameter mismatches | Deterministic output |
| Firefox (headed / headless) | Cross-browser | Cross-browser | Cross-browser | Separate baseline |
| VM / CI runner (GitHub Actions, etc.) | CI reality check | CI snapshot | CI anomalies | CI distribution |
Record the unmasked renderer/vendor, extension list, canvas hash, and readback statistics for each cell. Over time you build a reference library that tells you whether a new browser version or OS update shifts the baseline.
Interpreting results — what counts as an anomaly
Not every difference signals a bot. Use this mental checklist:
- Renderer string mismatch: Headless Chrome often reports "Google SwiftShader" or "Mesa" instead of a hardware GPU. But a real user on a VM or remote desktop may also show a software renderer.
- Extension list gaps: Missing common extensions like
OES_texture_float,WEBGL_depth_texture, orEXT_color_buffer_floatcan indicate a stripped-down headless build. - Parameter limit inconsistencies: If the renderer claims "NVIDIA RTX 3080" but
MAX_TEXTURE_SIZEis 4096 instead of 16384, the string is spoofed. - Readback variance near zero: A texture readback with variance < 0.1 (on a 0-255 scale) across multiple frames strongly suggests software rendering. Real GPUs typically show variance > 2.0 from thermal noise and driver dithering.
- Canvas hash stability: Identical canvas hashes across sessions with different window sizes or DPR suggest a deterministic offscreen renderer.
BotRefund's approach mirrors this: "A single anomaly is not a bot verdict. Privacy tools, travel, corporate networks, and unusual devices can produce unexpected behavior for genuine people. BotRefund keeps this signal as evidence — not a verdict — and cross-checks it against independent browser, network, device, and behavior data." Apply the same standard locally.
Key facts
| Fact | Detail |
|---|---|
| WebGL Texture Constraint role | One of 106 independent checks BotRefund uses to build a reliable picture of whether a visit is human or automated |
| Signal treatment | Kept as evidence — not a verdict — and cross-checked against independent browser, network, device, and behavior data |
| Accuracy claim | 99% accuracy from AI prediction that weighs the complete pattern across all signals |
| Core principle | Accuracy comes from corroboration, not one browser tell |
| False-positive sources | Privacy tools, travel, corporate networks, unusual devices |
Limitations of local testing
- No ground truth at scale: Your laptop represents one hardware/driver combination. Detection engines evaluate millions of combinations.
- No behavioral context: Local tools cannot replicate the full session behavior (mouse tremor, scroll patterns, click timing) that BotRefund correlates with WebGL signals.
- Baseline drift: Browser updates, driver updates, and OS patches shift WebGL output. A baseline from January may be stale by March.
- Adversarial adaptation: Sophisticated bots now inject real GPU readback data captured from residential proxies. Local testing cannot detect replayed textures without server-side challenge/response.
FAQ
Can I run these tools in a CI pipeline?
Yes. BrowserLeaks and creepJS need a real browser; run them via Puppeteer/Playwright in headed mode on a CI runner with GPU access (e.g., GitHub Actions ubuntu-latest with --use-gl=swiftshader for software baseline, or self-hosted runners with real GPUs for hardware baseline). fingerprintjs2 and custom readback scripts run naturally in Puppeteer.
How often should I refresh baselines?
After every major browser release (Chrome/Edge/Firefox/Safari), GPU driver update, or OS version bump. At minimum, schedule a monthly baseline regeneration job.
What if my headless browser passes all WebGL checks?
That means the WebGL surface is well-spoofed. Move to behavioral signals: mouse trajectory entropy, click timing distribution, scroll physics, and network-level TLS/HTTP/2 fingerprinting. BotRefund uses 106 checks precisely because no single surface is sufficient.
Are there npm packages that wrap this logic?
fingerprintjs2 is on npm. creepjs can be cloned and bundled. For readback, write your own thin wrapper — the shader and statistics are domain-specific enough that a generic package adds little value.
Does BotRefund expose its WebGL baselines publicly?
No. The baselines and the AI model that weighs them are proprietary. The open-source tools above let you build your own reference library; BotRefund's value is the curated, continuously updated baseline plus the cross-signal correlation engine.
Can I use these tools to harden my own bot?Technically yes — you can iterate until your automation passes the checks. But detection engines evolve faster than public test suites. A more sustainable path is to run real browsers (headed or headless with real GPU) on residential infrastructure, which naturally produces correct WebGL output without spoofing.
Further reading and comparison sources
These external sources provide additional context for evaluating the topic. Their inclusion is not an endorsement.
How BotRefund can help
BotRefund runs the WebGL Texture Constraint check alongside 105 other independent signals — behavioral, network, device, and browser — and feeds them into an AI model that reaches 99% accuracy by weighing the complete pattern. If you want to stop guessing which anomalies matter and start recovering ad spend from bot clicks, the free bot audit installs in about a minute and shows you exactly how much of your Google and Meta budget is going to automated traffic.