Seatext library / BotRefund evidence

How to Test if Your Browser Fingerprinting Detects Headless Browsers

Run a headless browser like Puppeteer or Playwright, collect its fingerprint signals (WebGL, canvas, navigator, CDP leaks, WebRTC leaks), and compare them against a real browser using a fingerprinting test site. The main difference...

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

Direct answer: Use a headless automation tool (e.g., Puppeteer, Playwright) to generate a fingerprint, then compare that fingerprint with one from a real browser on the same device. Look for mismatches in signals such as navigator.webdriver, CDP Debugger leaks, Engine Mismatch, WebRTC network leaks, and behavioral patterns. If the differences are detectable, your fingerprinting works.

Quick comparison of popular detection approaches

ApproachSignal coverageSpoof resistanceEase of integrationTypical cost
BotRefund (full‑stack)106 signals (browser, network, hardware, behavior)High – checks CDP Debugger Leak, Engine Mismatch, Automation Properties, WebRTC leaks, etc.One‑line SDK or APICheck with the vendor
Open‑source scripts (e.g., fpjs‑demo)10‑20 signals (mostly client‑side)Low – easy to spoof with stealth pluginsCopy‑paste codeFree
Custom server‑side logs5‑10 signals (IP, User‑Agent, headers)Very low – cannot see client hardware or WebRTC leaksRequires backend changesCheck with the vendor

This table shows which option fits different needs. BotRefund is suited for enterprises that need deep, multi‑vector detection. Open‑source demos are good for quick experiments but are easy for bots to evade.

What you need to test headless browser detection

To evaluate your fingerprinting, gather three items:

  • A headless browser (Puppeteer, Playwright, Selenium).
  • A fingerprinting test page that reports detailed signals.
  • A normal, non‑headless browser on the same machine for baseline comparison.

The goal is to see which signals differ and whether your detection logic flags the headless instance.

Why headless‑browser detection matters

Headless browsers automate tasks such as scraping, price monitoring, and ad fraud. When a bot can mimic a real user, it can click ads, fill forms, or harvest data without paying for services. Detecting headless browsers protects:

  • Ad spend: Prevent invalid clicks that inflate CPC.
  • Data quality: Stop polluted analytics caused by automated sessions.
  • Security: Block credential‑stuffing scripts that often run in headless mode.
  • Compliance: Ensure that GDPR‑related consent flows are not bypassed by bots.

Because headless browsers can hide behind residential proxies and human‑like mouse movements, a single signal is rarely enough. A layered fingerprint that includes network‑level checks (WebRTC leaks) and engine consistency is far more reliable.

How fingerprint signals are generated

When a page runs JavaScript, the browser reveals many properties. Each property becomes a signal. Below are the main families used by BotRefund and similar services:

  • Browser API signals: navigator.webdriver, navigator.plugins, navigator.languages, screen dimensions, touch support.
  • Graphics signals: WebGL vendor/renderer, Canvas image hash, WebGL extensions. Headless Chrome often reports “SwiftShader” or lacks a GPU.
  • Automation signals: CDP Debugger Leak, Automation Properties, Rebrowser Leaks. These appear when the DevTools protocol is active or when internal flags are set.
  • Engine signals: Engine Mismatch, JS Engine Mismatch. They compare reported JavaScript engine version with the expected version for the claimed browser.
  • Network signals: WebRTC Network Leak, DNS Tunnel Leak, IP address inconsistency, latency mismatch. These expose mismatched locations between the browser’s reported timezone/language and the actual network path.
  • Behavioral signals: Mouse movement jitter, click timing, scroll depth, session duration. Bots often have linear, ultra‑fast movements.

Each vector is a piece of a larger puzzle. BotRefund’s AI evaluates the full pattern before labeling traffic as a bot.

Step 1: Set up a headless browser

Install Puppeteer or Playwright via npm and launch in headless mode. Keep the default configuration for a “vanilla” test.

const puppeteer = require('puppeteer');
(async () => {
  const browser = await puppeteer.launch({ headless: true });
  const page = await browser.newPage();
  await page.goto('https://browserleaks.com');
  // optional: capture console output
  await browser.close();
})();

Do not add any stealth plugins yet; you want to see the raw signals first.

Step 2: Capture fingerprint signals

Navigate to a fingerprinting demo (e.g., browserleaks.com or FingerprintJS demo) and record the following items:

  • navigator.webdriver – true in vanilla headless Chrome.
  • WebGL vendor/renderer – often “SwiftShader” or missing.
  • Canvas fingerprint hash – differs from a real GPU hash.
  • CDP Debugger Leak – exposed automation properties (source S1, vector 16).
  • Engine Mismatch – reported engine version does not align with User‑Agent (source S1, vector 18).
  • Automation Properties – flags like chrome.runtime that indicate automation (source S1, vector 21).
  • WebRTC Network Leak – reveals local IP that conflicts with the public IP (source S1, vector 1).
  • Behavioral patterns – mousemove events are absent or linear.

Save the JSON output or screenshot for later comparison.

Vanilla headless vs. stealth headless browsers

Stealth plugins (e.g., puppeteer-extra-plugin-stealth) patch many of the signals listed above. Below is a deeper look at what changes:

SignalVanilla headlessStealth‑enabled headlessWhy it matters
navigator.webdrivertruefalse (patched)Direct flag for automation.
WebGL rendererSwiftShaderReal GPU string (spoofed)GPU fingerprint often used for device profiling.
Canvas hashDifferent from realMatches real hashCanvas fingerprint is a strong identifier.
CDP Debugger LeakExposedHidden (debugger disabled)Detects automation tools that use Chrome DevTools.
Engine MismatchPresentRemovedEnsures engine version aligns with User‑Agent.
WebRTC local IPLeakedMasked or routed through VPNNetwork‑level consistency checks.
Mouse movementNone or linearHuman‑like jitter injectedBehavioral signals are hard to fake at scale.

If your fingerprinting only checks the first three rows, a stealth browser will likely pass. Adding network‑level and behavioral rows makes evasion much harder.

Step 3: Collect the same signals from a real browser

Open the same test page in a regular Chrome or Firefox window on the same machine. Record the identical list of signals. This becomes your human baseline.

Step 4: Compare the two sets

Look for mismatches. Typical differences include:

  • User‑Agent: Headless may include “HeadlessChrome”.
  • Plugins length: Real browsers show 3‑5 plugins; headless often shows 0.
  • Languages: Mismatch with timezone or location.
  • Screen resolution: Default 800×600 in headless.
  • Touch support: False unless explicitly emulated.
  • Network vectors: WebRTC local IP, DNS routing, latency mismatches.

Map each observed difference to a vector from the source pack (e.g., CDP Debugger Leak → vector 16, Engine Mismatch → vector 18). If any vector is present, your fingerprinting can flag the session.

Run a detection tool against your fingerprinting

Services like BotRefund evaluate 106 signals across browser, network, hardware, and behavior layers. You can run a free audit on their site to see which of the above vectors your current setup catches. If the audit shows many unchecked signals, consider expanding your detection logic.

Troubleshooting detection tests

If you do not see expected differences, try these steps:

  1. Clear caches: Cached scripts can mask changes in User‑Agent or plugins.
  2. Disable headless mode flags: Some CI environments add --disable-gpu which forces SwiftShader.
  3. Verify network leaks: Run a local WebRTC test script to ensure the browser reveals its real IP. If it does not, a VPN or proxy may be hiding the leak.
  4. Check for hidden automation properties: Open DevTools and run Object.getOwnPropertyNames(window) to see if automation flags remain.
  5. Compare timestamps: A large UTC offset between Date.now() and the reported timezone can trigger the “UTC Timezone Bias” vector.

After each change, repeat the capture step and verify that the signal list updates accordingly.

Limitations of fingerprint‑based detection

Fingerprinting is powerful but not foolproof. Key limitations include:

  • False positives: Rare device configurations (e.g., privacy‑focused browsers that block plugins) may resemble headless fingerprints.
  • Adaptive bots: Advanced botnets can rotate proxies, spoof WebGL strings, and inject human‑like mouse jitter, reducing the effectiveness of static signal sets.
  • Privacy regulations: Some jurisdictions restrict the collection of certain hardware identifiers, limiting the signal pool.
  • Browser updates: New Chrome or Firefox releases may change default values, causing previously reliable signals to drift.
  • Server‑side visibility: Without client‑side execution, you cannot see graphics or behavioral signals; relying only on headers leads to high evasion rates.

To mitigate these issues, combine fingerprinting with server‑side analytics (IP reputation, rate limiting) and continuously update your signal list based on emerging vectors such as the ones listed in BotRefund’s detection catalog.

Frequently Asked Questions

What is the easiest way to test headless browser detection?

Open a fingerprint demo site in a vanilla headless browser and a normal browser, then compare the reported signals side by side.

Which signals are most reliable?

CDP Debugger Leak, Engine Mismatch, Automation Properties, and WebRTC Network Leak are hard to spoof without deep modifications.

Can I use BotRefund to test my fingerprinting?

Yes. BotRefund offers a free audit that checks all 106 signals and shows which ones your current logic misses.

How many signals should I monitor?

Relying on a single signal is risky. Monitoring a broad set—ideally dozens—makes evasion significantly harder.

What if my fingerprinting does not detect a headless browser?

Add missing vectors such as WebRTC leaks, automation properties, and behavioral jitter. Consider integrating a full‑stack solution.

Does stealth mode make a headless browser undetectable?

Stealth plugins hide many client‑side flags, but they often leave network‑level or timing mismatches that robust fingerprinting can still catch.

Further reading and comparison sources

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

BotRefund evaluates 106 signals—including CDP Debugger Leak, Engine Mismatch, Automation Properties, and WebRTC Network Leak—to achieve high‑accuracy detection. Try their free audit to see which vectors your current setup misses.

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