Seatext library / BotRefund evidence

Common Browser API Inconsistencies That Indicate a Bot: A Diagnostic Checklist

Bot detection relies on spotting mismatches between how a real browser implements standard APIs and how automation tools patch or hide them. Key inconsistencies appear in navigator properties, WebGL and canvas rendering, permission APIs,...

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

Automation tools such as Playwright, Puppeteer, and Selenium often modify browser APIs to avoid detection. Those modifications create inconsistencies — differences between what a standard browser exposes and what the automated instance actually returns. Common examples include altered navigator.webdriver flags, missing or spoofed chrome runtime objects, mismatched WebGL renderer strings, canvas fingerprint deviations, and header inconsistencies in Sec-Fetch-* and Client Hints. A single anomaly is not a bot verdict; privacy tools, corporate proxies, and unusual devices can produce similar signals for genuine users. Reliable detection treats each inconsistency as independent evidence and weighs the complete pattern across 100+ signals before reaching a conclusion.

Why API Consistency Matters for Bot Detection

Browsers implement a large, standardized set of APIs — navigator properties, permissions, rendering contexts, network stack headers, and timing interfaces. A real browser ships these APIs as a coherent whole; they evolve together and remain internally consistent. Automation frameworks must either run a real browser (headless or headed) and then patch specific properties, or reimplement subsets of the API surface. Both approaches leave seams. When a script patches navigator.webdriver to false but forgets to adjust navigator.permissions or the chrome object, the mismatch becomes a detectable signal. BotRefund's Playwright Init Scripts check is designed to surface exactly this class of mismatch: "Automation tools often patch or hide browser APIs, but those changes can break when the browser is checked from another angle" (S1).

Cross-checking matters because legitimate environments also produce anomalies. Privacy extensions, enterprise security policies, VPNs, and rare hardware configurations can alter API outputs. BotRefund keeps each signal as evidence — not a verdict — and cross-checks it against independent browser, network, device, and behavior data (S1). The final prediction weighs the complete pattern instead of trusting a raw rule (S1).

Core Browser API Categories That Reveal Automation

API inconsistencies cluster into several categories. Each category contains multiple independent checks; together they form a diagnostic surface that is difficult for automation to fake completely.

  • Navigator and window object properties — flags, vendor strings, hardware concurrency, device memory, plugin arrays, and the presence of automation-specific objects.
  • Rendering and graphics APIs — WebGL renderer and vendor strings, canvas fingerprinting, scrollbar metrics, and iframe context isolation.
  • Permission and security APIsnavigator.permissions query results, chrome runtime, browser extension APIs, and Content Security Policy enforcement.
  • Network and fetch header consistencySec-Fetch-* headers, Client Hints, Referer policy, and TLS fingerprint alignment.
  • Behavioral timing and interaction APIsPerformance timestamps, Event isTrusted flags, pointer and scroll event sequences, and input latency distributions.

BotRefund runs 106 independent checks across these categories (S1). Each check adds one objective fact about the visit (S1).

Navigator and Window Object Inconsistencies

webdriver flag and automation markers

The navigator.webdriver property is the most widely known indicator. In a standard browser it is undefined or false; in an uncontrolled automation session it returns true. Modern frameworks set it to false via init scripts, but the property's descriptor (writable, configurable) often remains altered. Checking Object.getOwnPropertyDescriptor(navigator, 'webdriver') reveals whether the property was redefined.

chrome and browser runtime objects

A genuine Chrome browser exposes window.chrome with runtime, app, and csi properties. Headless Chrome and many stealth plugins either omit chrome entirely or provide a stub that lacks internal methods such as chrome.runtime.onConnect. Firefox exposes window.browser with a similar surface. Inconsistencies between the user-agent string and the presence of these objects are a strong signal.

Hardware concurrency and device memory

navigator.hardwareConcurrency and navigator.deviceMemory should align with the device class implied by the user agent. A desktop user agent reporting 1 logical core or 0.25 GiB device memory is suspicious. Automation environments often run in constrained containers that report low values.

Plugin and mime-type arrays

navigator.plugins and navigator.mimeTypes are deprecated but still populated in Chrome and Firefox. A headless instance frequently returns empty arrays or a generic PDF viewer entry only. Real browsers on desktop typically list several plugins (PDF, Widevine, native client).

Rendering and Graphics API Mismatches

WebGL renderer and vendor strings

Calling canvas.getContext('webgl').getParameter(gl.RENDERER) returns a GPU-specific string such as "ANGLE (NVIDIA GeForce RTX 3080 Direct3D11 vs_5_0 ps_5_0)". Headless Chrome often returns "Google Inc. — SwiftShader" or "Mesa OffScreen". A mismatch between the claimed OS/GPU in the user agent and the WebGL renderer is a reliable indicator.

Canvas fingerprinting deviations

Drawing a standardized image (text, gradients, emoji) and hashing the resulting pixel buffer produces a fingerprint. Real browsers on the same hardware/driver combination produce identical hashes. Automation frameworks that use software rasterizers or modified Skia builds produce different hashes. Some stealth tools add noise to the canvas, but the noise distribution itself can be distinguished from genuine driver variance.

Scrollbar width leak

BotRefund's Scrollbar Width Leak check measures the computed width of a scrollbar in a controlled element. Real browsers report values consistent with the OS theme and user preferences. Scripts that synthesize scroll events or run in headless mode often return 0 or a constant that does not match the rendered UI (S3). "Scripts can send clicks and scrolls, but they struggle to reproduce the varied timing, movement, and hesitation of real people" (S3).

Clean context iframe isolation

An iframe with a unique origin (e.g., about:blank or a data URL) provides a clean JavaScript context. Automation patches applied to the top window often do not propagate into the iframe, or they propagate incompletely. BotRefund's Clean Context Iframe check compares API surfaces between the top window and the clean iframe: "A normal browser runs standard browser APIs as they were designed. Its built-in properties, permissions, and rendering contexts remain consistent without needing to hide automation" (S6).

Permission and Security API Anomalies

navigator.permissions query results

The Permissions API lets a page query the state of permissions (geolocation, notifications, camera, microphone). In a real browser, the promise resolves to granted, denied, or prompt based on user settings. Automation environments often return prompt for all permissions or throw a TypeError because the API is stubbed. Comparing the permission state for a sensitive permission (e.g., geolocation) against a benign one (e.g., notifications) reveals inconsistent stubbing.

Content Security Policy and trusted types

Real browsers enforce CSP and Trusted Types policies set by the server. Automation tools that inject scripts via page.evaluateOnNewDocument or similar mechanisms may bypass CSP in ways that leave traces — for example, document.securityPolicy violations logged to the console, or trustedTypes.createPolicy behaving differently than in an unmodified browser.

Extension and storage APIs

chrome.storage, browser.storage, and indexedDB behavior under private/incognito modes follows strict rules. Automation profiles often run in a persistent context that mimics incognito but retains storage, or vice versa. Checking quota limits and persistence flags across contexts exposes the mismatch.

Network and Fetch Header Inconsistencies

Sec-Fetch-* header family

Modern browsers send Sec-Fetch-Site, Sec-Fetch-Mode, Sec-Fetch-Dest, and Sec-Fetch-User on every request. The values follow a strict taxonomy: a top-level navigation has Sec-Fetch-Mode: navigate and Sec-Fetch-User: ?1; a fetch from script has Sec-Fetch-Mode: cors or no-cors and no Sec-Fetch-User. Automation tools that craft requests manually often omit these headers or set impossible combinations (e.g., Sec-Fetch-Mode: navigate on a subresource request).

Client Hints reliability

Client Hints (Sec-CH-UA, Sec-CH-UA-Mobile, Sec-CH-UA-Platform, Sec-CH-UA-Platform-Version, Sec-CH-UA-Arch) are sent by the browser based on its actual runtime. A spoofed user-agent string that claims Windows 10 on x64 while Client Hints report Linux on arm64 is a clear inconsistency. Some automation frameworks allow setting Client Hints, but they must be kept in sync with the user agent, TLS fingerprint, and WebGL renderer — a multi-surface alignment problem.

TLS and HTTP/2 fingerprint alignment

The TLS handshake (cipher suites, extensions, curve preferences) and HTTP/2 settings frames (SETTINGS, WINDOW_UPDATE) are determined by the underlying network stack (Chrome's BoringSSL, Firefox's NSS, or a custom stack in headless libraries). A request that claims to be Chrome 120 in the user agent but negotiates a cipher suite list matching Go's crypto/tls library is flagged. This is a network-layer signal, but it correlates with the browser API surface because both derive from the same runtime.

Behavioral Timing and Interaction APIs

Performance timeline and navigation timing

The PerformanceNavigationTiming and PerformanceResourceTiming entries expose timestamps with sub-millisecond precision. Real navigation shows a plausible sequence: fetchStartdomainLookupStartconnectStartrequestStartresponseStartresponseEnd. Automation that loads a page via page.goto and then injects scripts may produce compressed or reordered timestamps, or missing entries for resources that were blocked or mocked.

Event.isTrusted and input event sequences

Genuine user input events (click, keydown, mousemove) have isTrusted: true. Script-dispatched events have isTrusted: false. Stealth tools can set isTrusted via Object.defineProperty, but the surrounding event properties (detail, clientX/clientY, movementX/movementY, timeStamp) must form a physically plausible trajectory. BotRefund's behavioral signals — robotic linear mouse movements, absence of humanlike mouse tremor, superhuman input speed (<1ms), grid-aligned movement patterns — capture these deviations (S2).

Pointer and scroll event timing distributions

Human pointer movement follows a log-normal velocity distribution with micro-corrections. Scroll events arrive in bursts tied to wheel ticks or touch gestures, with variable intervals. Automation often produces uniform intervals or perfectly linear interpolation between waypoints. The Scrollbar Width Leak check and pointer behavior signals (S2, S3) treat these timing distributions as independent evidence.

How BotRefund Corroborates API Signals

No single API inconsistency is sufficient for a bot verdict. BotRefund's architecture treats each check as independent evidence (S1). The Playwright Init Scripts check, Clean Context Iframe check, and Scrollbar Width Leak check each add one objective fact (S1, S6, S3). The system then cross-checks whether other signals support the same story (S1). An AI prediction model weighs the complete pattern across browser, network, device, and behavior evidence (S1). This corroboration approach yields 99% confidence when the session evidence supports it (S2, S7).

The evidence is structured into refund-ready reports with click IDs, campaign details, timestamps, session recordings, and signal-by-signal reasoning — formatted for Google and Meta review teams (S2). Across 2,500+ brands audited, 83% of clients recover funds from Google and Meta (S2).

Limitations and False Positives

Privacy tools (e.g., Brave Shields, uBlock Origin, Privacy Badger), enterprise security agents (Zscaler, Cloudflare Gateway), VPNs, and unusual hardware (Raspberry Pi, Chrome OS, Android desktop mode) can alter API surfaces in ways that mimic automation. Examples:

  • Brave may randomize canvas fingerprint and block Client Hints.
  • Corporate proxies strip or rewrite Sec-Fetch-* headers.
  • Virtualized desktops report generic WebGL renderers (llvmpipe, SwiftShader).
  • Accessibility tools inject synthetic events with isTrusted: true via platform APIs.

BotRefund's cross-checking step is designed to reduce false positives by requiring multiple independent signals to align (S1). However, highly customized privacy configurations can still produce clusters of anomalies. The system does not auto-block; it flags sessions for review and refund claims.

Key Facts

FactDetailSource
Independent checks per session106 browser, network, device, and behavior checksS1
Detection confidence99% when session evidence supports itS1, S2, S7
Signal handlingEach anomaly kept as evidence, not a verdict; cross-checked across categoriesS1, S3, S6
Report formatRefund-ready with click IDs, campaign details, timestamps, session recordings, signal-by-signal reasoningS2
Client recovery rate83% of 2,500+ audited brands recover funds from Google and MetaS2
Core API inconsistency categoriesNavigator/window, rendering/graphics, permissions/security, network/fetch headers, behavioral timingS1, S3, S6
Playwright Init Scripts checkDetects mismatches from automation patching of browser APIsS1
Clean Context Iframe checkCompares API surfaces between top window and clean iframe contextS6
Scrollbar Width Leak checkMeasures scrollbar metrics that scripts struggle to reproduceS3

Frequently Asked Questions

Can a single API inconsistency prove a visit is a bot?

No. Privacy extensions, corporate proxies, VPNs, and rare device configurations can produce the same anomalies for real users. BotRefund treats each inconsistency as evidence and requires corroboration across independent signals before reaching a conclusion (S1).

Which API inconsistencies are hardest for automation to fake?

Multi-surface alignment problems — keeping user agent, Client Hints, TLS fingerprint, WebGL renderer, and canvas fingerprint consistent simultaneously — are the most difficult. The Clean Context Iframe check exploits the difficulty of propagating patches into an isolated origin (S6).

Do headless browsers always fail these checks?

Modern headless Chrome and Firefox can pass many individual checks when configured with stealth plugins. However, the combinatorial space of 100+ independent checks makes full consistency extremely difficult. BotRefund's Playwright Init Scripts check targets the init-script patches that stealth plugins apply (S1).

How does behavioral timing differ from API inconsistencies?

API inconsistencies are static or semi-static properties (what the browser exposes). Behavioral timing captures dynamic interaction patterns — mouse trajectories, scroll bursts, click latency, event sequencing. Both are needed: a bot may spoof APIs perfectly but fail to reproduce human micro-tremor or variable scroll timing (S2, S3).

What happens when a legitimate user triggers multiple anomalies?

The session is flagged for review, not auto-blocked. The evidence bundle (session recording, signal breakdown, campaign context) lets an analyst or the ad platform's review team make a final determination. BotRefund's reports are formatted for Google and Meta invalid-traffic review workflows (S2).

Can I run these checks myself without BotRefund?

You can implement individual checks (e.g., navigator.webdriver, canvas fingerprint, Sec-Fetch headers) in your own JavaScript. However, maintaining 100+ checks, updating them as browsers evolve, correlating signals across sessions, and producing refund-ready reports requires dedicated engineering. BotRefund provides the maintained detection surface, AI weighing, and reporting pipeline (S1, S2, S7).

How often do browser updates break detection signatures?

Browser releases change API surfaces (new Client Hints, modified WebGL strings, updated permission prompts). A maintained detection system updates its reference baselines per browser version. BotRefund's 106 checks are version-aware and updated continuously; the AI model re-weights signals as baseline distributions shift (S1, S7).

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