Seatext library / BotRefund evidence

Why Headless Chrome Gets Blocked Even With User-Agent Spoofing

User-agent spoofing only changes one HTTP header. Modern bot detection correlates over 100 independent signals — WebGL fingerprints, canvas rendering, audio stack, navigator properties, mouse micro-movements, click timing, and navigation patterns — that headless...

Built for advertisers who need clear, refund-ready traffic evidence.

Spoofing the user-agent string changes a single HTTP header. It does not touch the browser's rendering engine, GPU driver stack, input event timing, or the dozens of JavaScript-accessible APIs that fingerprinting scripts measure. Modern detection platforms like BotRefund run 106 independent checks across browser internals, hardware capabilities, network behavior, and human interaction patterns. A headless Chrome instance — even with a perfect user-agent string — still reveals itself through WebGL texture limits, canvas hash mismatches, missing audio contexts, linear mouse paths, sub-millisecond click speeds, and navigation sequences that no human could produce.

Detection has moved far beyond the user-agent header

The user-agent string was never a reliable identity signal; it was a compatibility hint. Today it is treated as one low-weight feature among hundreds. Detection systems collect evidence from:

  • Graphics stack: WebGL renderer, vendor, extensions, texture size limits, and shader precision — all tied to the physical GPU and driver.
  • Canvas fingerprint: Sub-pixel rendering differences, font rasterization, and emoji support that vary by OS, browser version, and hardware acceleration settings.
  • Audio context: Sample rate, channel count, and latency hints that expose the underlying audio hardware and OS mixer.
  • Navigator properties: hardwareConcurrency, deviceMemory, platform, plugins, mimeTypes, and permissions that must form a coherent profile.
  • Behavioral biometrics: Mouse tremor, click pressure curves, scroll momentum, focus/blur sequences, and tab-switch timing.
  • Environmental artifacts: window.chrome object shape, navigator.webdriver flag, automation-controlled frame markers, and DevTools protocol side-effects.

Each signal alone is weak. Correlated together they produce a high-confidence classification. BotRefund's documentation notes that "accuracy comes from corroboration, not one browser tell" and that their model weighs "the complete pattern instead of trusting a raw rule" (S1, S5, S6).

WebGL and canvas expose the graphics hardware

Headless Chrome typically runs with SwiftShader (software rasterizer) or a virtual GPU. The WebGL UNMASKED_RENDERER_WEBGL extension reports the actual driver string — e.g., "Google Inc. — SwiftShader" — which immediately flags a non-physical GPU. Texture size limits (MAX_TEXTURE_SIZE, MAX_CUBE_MAP_TEXTURE_SIZE) and compressed texture formats (ASTC, ETC, DXT) also differ between real GPUs and software fallbacks. The BotRefund "WebGL Texture Constraint" check specifically looks for "a mismatch that a real browsing session does not normally create" where "virtual machines and spoofed profiles can claim one device while their graphics, fonts, audio, or processor behavior tells another story" (S1).

Canvas fingerprinting draws a hidden image — often text with specific fonts, emojis, and gradients — then hashes the pixel buffer. Headless Chrome's font rendering, anti-aliasing, and color profile differ from headed Chrome on the same OS, producing a distinct hash. Even when you inject a canvas noise library, the noise pattern itself can be detected as non-native.

AudioContext reveals the OS audio stack

The Web Audio API exposes AudioContext.sampleRate (usually 44100 or 48000), outputLatency, and the number of output channels. On headless Linux containers the sample rate often defaults to 48000 with zero latency, while real Windows/macOS devices show 44100 and non-zero latency. The AudioBufferSourceNode behavior under load also differs. Fingerprinting scripts create a silent oscillator, measure the exact sample output, and compare it to known device profiles.

Navigator properties must form a coherent device profile

A real device presents a consistent tuple: hardwareConcurrency matches CPU cores, deviceMemory matches RAM buckets, platform matches OS, devicePixelRatio matches display scaling. Headless scripts often set userAgent to Windows Chrome but leave platform as "Linux x86_64" or hardwareConcurrency at 2 while claiming a high-end desktop. The plugins and mimeTypes arrays are empty in headless mode unless explicitly populated. The permissions API returns different states for notifications, camera, and microphone. All of these are cross-checked.

Behavioral biometrics: timing, motion, and interaction sequences

Human input is noisy. Mouse paths have micro-tremor (sub-pixel jitter), variable velocity, and curved trajectories. Clicks have a press-hold-release curve of 50–150 ms. Scroll events arrive in bursts with deceleration. Headless automation typically:

  • Moves the pointer in straight lines or instant jumps (S2: "Robotic linear mouse movements", "Grid-aligned movement patterns")
  • Clicks with <1 ms down-up intervals (S2: "Superhuman input speed (<1ms)")
  • Scrolls at constant velocity without easing (S2: "Absence of humanlike mouse tremor")
  • Submits forms without focus/blur sequences or field corrections (S7: "Superhuman input speeds", "Lack of physical pointer movement")
  • Navigates pages at impossible speeds (S5: "Impossible Tab Speed" — "scripts can send clicks and scrolls, but they struggle to reproduce the varied timing, movement, and hesitation of real people")

BotRefund's "Impossible Tab Speed" and "window.open Tamper" checks specifically target these timing anomalies (S5, S6).

Headless-specific environmental artifacts

Even with --disable-blink-features=AutomationControlled, headless Chrome leaks signals:

  • navigator.webdriver may be false but window.chrome.runtime is undefined.
  • document.documentElement.getAttribute('webdriver') can be present.
  • DevTools protocol ports (default 9222) may be open on localhost.
  • Console messages from Puppeteer/Playwright internal scripts.
  • Missing window.outerWidth/outerHeight updates during resize.
  • performance.memory (non-standard) often absent or zeroed.

The "window.open Tamper" check detects when scripts override window.open or manipulate popup behavior in ways real browsers don't (S6).

Network and proxy fingerprints

Residential proxy exit nodes have distinct TCP/IP characteristics: TTL values, window scaling, timestamp options, and TLS fingerprint (JA3/JA3S). Data-center IPs — even with residential proxy labels — often show sequential IP blocks, low ASN diversity, and missing IPv6. BotRefund's homepage lists "Ghost click detection", "Honeypot trap interactions", and "Unnatural session durations" as network-adjacent behavioral signals (S2). The Meta invalid traffic guide notes "sudden placement-level spikes" and "conversions concentrated at unusual hours" as campaign-level anomalies (S3).

Why single fixes fail: the corroboration model

You can patch one signal — spoof WebGL, inject canvas noise, randomize mouse paths — but the detection model evaluates the joint probability of the entire vector. If 99 signals match a human profile and 7 do not, the visit is flagged. BotRefund explicitly states: "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" (S1, S5, S6). This means you must replicate the full covariance structure of a real device-and-human pair, not just individual marginals.

Key facts

Signal categoryWhat is measuredWhy headless failsSource
WebGL / GPURenderer string, texture limits, extensions, shader precisionSwiftShader / virtual GPU exposes non-physical driverS1
Canvas fingerprintFont rasterization, emoji rendering, color profile, anti-aliasingHeadless font stack differs from headed ChromeS1
AudioContextSample rate, output latency, channel countContainer defaults (48 kHz, zero latency) mismatch real OSS1
Navigator propertieshardwareConcurrency, deviceMemory, platform, plugins, permissionsInconsistent tuple (e.g., Windows UA + Linux platform)S1
Mouse / pointerMicro-tremor, velocity curves, path curvature, click press-hold-releaseLinear paths, instant moves, sub-ms clicksS2
Scroll / navigationMomentum, deceleration, tab-switch timing, focus sequencesConstant velocity, impossible tab speedsS2, S5
Form interactionTyping cadence, field corrections, copy-paste detection, focus orderSuperhuman input speed, no pointer movementS7
Environment artifactsnavigator.webdriver, window.chrome, DevTools port, console leaksAutomation-controlled flags, missing runtimeS6
Network / proxyTCP/IP fingerprint, TLS JA3, IP reputation, ASN diversityData-center exit nodes, sequential IPsS2, S3
Model approach106 independent checks, AI-weighted corroboration, 99% claimed accuracySingle patches insufficient; joint distribution must matchS1, S5, S6

Limitations and when this analysis does not apply

  • Basic WAF rules: Some edge firewalls still block on user-agent alone. Spoofing works there but offers no protection against modern bot detection.
  • Low-sensitivity targets: Sites without behavioral telemetry (no client-side JS) cannot measure canvas, mouse, or timing signals.
  • Legitimate automation: Testing, archiving, and accessibility tools may be blocked despite benign intent. The detection model treats them as bots because the signals are identical.
  • Privacy tools: Anti-fingerprinting extensions (CanvasBlocker, Chameleon) intentionally add noise that can itself become a detection signal.
  • Mobile vs desktop: Mobile Chrome headless has a different signal surface (touch events, accelerometer, battery API) not covered here.

Frequently asked questions

Can I pass detection by using a real browser profile with Playwright?

Using a persistent user-data-dir with a real Chrome profile (cookies, extensions, history) improves navigator consistency and plugin lists. It does not fix WebGL renderer, canvas hash, audio stack, or behavioral biometrics. The automation-controlled flags and DevTools protocol side-effects remain.

Does undetected-chromedriver or stealth plugins solve this?

They patch known leaks (navigator.webdriver, chrome.runtime, permissions API) and randomize some canvas noise. They do not virtualize a physical GPU, replicate human micro-tremor, or produce coherent timing distributions across 100+ signals. They raise the bar but do not clear it against corroboration-based models.

What about cloud browser services (Browserbase, Browserless, ScrapingBee)?

These run real Chrome on real hardware (often with GPUs), so WebGL and canvas signals match. They still need behavioral orchestration — human-like mouse, scroll, typing, and think-time — which is your responsibility. The IP reputation of their exit nodes is also a factor.

How much engineering effort to build a truly undetectable headless setup?

Months to years. You need: GPU-pass-through or real hardware fleet, custom Chrome builds with patched fingerprint surfaces, a behavioral engine that models human timing distributions per action type, residential proxy rotation with consistent TLS fingerprints, and continuous testing against live detection endpoints. Most teams buy detection evasion as a service instead.

Will blocking headless Chrome hurt legitimate users?

False positives occur. BotRefund notes that "privacy tools, travel, corporate networks, and unusual devices can produce unexpected behavior for genuine people" and treats anomalies as evidence, not verdicts (S1, S5, S6). Sites that hard-block on a single signal will lose real users. The industry standard is challenge (CAPTCHA, proof-of-work) or silent scoring with downstream review.

What should I compare if I'm evaluating bot detection vendors?

Compare: signal breadth (browser + network + behavioral), model type (rule-based vs ML corroboration), false-positive handling (challenge vs block), evidence export for ad-platform refunds (Google Click Quality, Meta), integration effort (JS snippet vs server-side), and pricing model (per-request vs per-protected-domain). BotRefund emphasizes "forensic evidence for ad rep refunds" and "99% accuracy" via AI-weighted corroboration (S2, S9).

Can I just use the user-agent of a real device I own?

That aligns one header. The other 105 checks still fire. The user-agent is the least informative signal in the modern stack.

Further reading and comparison sources

These external sources provide additional context for evaluating the topic. Their inclusion is not an endorsement.

Learn more

Visit the website for more information.

Learn more