Browser automation through WebDriver is the most common technique bots use to impersonate real users. Knowing exactly what signals expose a WebDriver-controlled browser — and how reliable those signals are — is the foundation of any serious bot detection strategy.
What WebDriver Signals Actually Reveal
When a browser is launched via WebDriver (Selenium, Playwright, Puppeteer, or similar), it leaves a set of observable artifacts that detection systems can interrogate. These are not bugs in the automation tools; they are structural side-effects of how the WebDriver protocol instruments the browser engine.
The most consistently detected signals include:
navigator.webdriverproperty – Browsers controlled via the WebDriver protocol set this boolean totrueby default. It is the single most cited signal in bot detection literature, though modern headless browsers increasingly attempt to patch it.- CDP (Chrome DevTools Protocol) attachment markers – When Playwright or Puppeteer attaches to a browser over CDP, certain runtime objects and event listeners appear in the JavaScript heap that are absent in organic sessions.
- Plugin and MIME-type arrays – A headless Chrome instance typically exposes zero plugins. Real desktop Chrome on any major OS exposes at least several.
- Rendering timing inconsistencies – Hardware-accelerated rendering produces measurably different canvas and WebGL fingerprint outputs versus software-rendered headless environments.
- Event sequencing anomalies – Human mouse movement generates dozens of
mousemoveevents between amousedownandmouseup. Script-driven clicks often produce exactly one or none. - Missing or malformed browser features – Properties like
window.chrome, speech synthesis voices, or theNotificationAPI are either absent or stub objects in many headless configurations.
None of these signals is individually decisive. Robust detection scores them in aggregate — something more sophisticated than a single if (navigator.webdriver) check.

How Evasion Attempts Change the Detection Landscape
Understanding evasion is essential for defenders: if you only test your protection against naive bots, you will be unprepared for the tooling that most real attackers use.
Tools like undetected-chromedriver, Playwright-stealth, and various CDP-level patches attempt to neutralize the obvious signals above. They patch navigator.webdriver, inject realistic plugin arrays, and spoof window.chrome. Against a detector that relies solely on those static property checks, these tools work.
This is why detection has shifted toward behavioral and consistency-based analysis:
Behavioral Signals
- Mouse trajectory entropy (real paths curve; scripted paths are often linear or grid-snapped)
- Scroll acceleration and deceleration curves
- Inter-keystroke timing distribution
- Focus/blur patterns during form completion
Consistency Signals
- Does the reported GPU in the WebGL renderer match the reported OS and browser version?
- Does the
Accept-Languageheader match the JavaScriptnavigator.language? - Does the screen resolution, color depth, and device pixel ratio form a plausible combination for any real device?
Inconsistencies here are hard to spoof exhaustively because the attacker must maintain a coherent fiction across dozens of independent measurement channels simultaneously.
Comparing Detection Approaches Across Common Providers
Different CAPTCHA and bot-defense services weight these signals differently.
| Provider | Primary Signal Type | Invisible-First | First-Party Data |
|---|---|---|---|
| Google reCAPTCHA | Behavioral + Google account history | Yes (v3) | No (cross-site profile) |
| hCaptcha | Visual challenge + behavioral | Partial | No |
| Cloudflare Turnstile | Browser integrity + TLS fingerprint | Yes | Partially (tied to Cloudflare network) |
| CaptchaLa | Behavioral + device fingerprint | Yes | Yes — no cross-site tracking |
The first-party data distinction matters for compliance (GDPR, CCPA) and for avoiding false positives that arise when a user's Google or Cloudflare reputation is low for reasons unrelated to your site.
Implementing Server-Side Validation Correctly
Client-side detection is only half the job. A bot that passes a challenge can replay the resulting token; your server must validate it before trusting the action.
A minimal server-side validation call to CaptchaLa looks like this:
// Node.js example — run this on your server, never in the browser
const response = await fetch('https://apiv1.captcha.la/v1/validate', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-App-Key': process.env.CAPTCHALA_APP_KEY, // keep secret
'X-App-Secret': process.env.CAPTCHALA_APP_SECRET // keep secret
},
body: JSON.stringify({
pass_token: req.body.captchaToken, // token from the client widget
client_ip: req.ip // forwarded real IP, not proxy IP
})
});
const result = await response.json();
// result.success === true means the challenge was genuinely solved
if (!result.success) {
return res.status(403).json({ error: 'Bot check failed' });
}Two things to get right here: always pass the real client_ip (not a load balancer IP), and always validate server-side even if you already checked on the client. Skipping server validation is the most common integration mistake.
Full integration details, including SDKs for PHP (captchala-php), Go (captchala-go), and mobile platforms (iOS via CocoaPods Captchala 1.0.2, Android via Maven la.captcha:captchala:1.0.2, Flutter via pub.dev captchala 1.3.2), are in the docs.

Choosing the Right Detection Threshold
Bot detection always involves a tradeoff between false negatives (bots that pass) and false positives (real users blocked). Where you set that threshold should be driven by the value and risk of the protected action:
- Low-stakes pages (newsletter subscription, search) — tolerate more false negatives; minimize friction for real users.
- Medium-stakes actions (account creation, password reset) — challenge on behavioral anomalies; pass clean sessions silently.
- High-stakes actions (checkout, API key generation, large transfers) — require explicit challenge completion regardless of behavioral score; log for audit.
A server-token flow (POST to https://apiv1.captcha.la/v1/server/challenge/issue) lets you trigger challenges server-side when your own application logic raises a risk flag, independent of what happened on the client. This is useful for step-up authentication scenarios.
Where to Go Next
If you want to test detection against your own registration or login flow, CaptchaLa has a free tier covering 1,000 validations per month — enough to evaluate real-world detection quality without committing a budget. When you're ready to scale, pricing starts at 50K validations per month on the Pro plan. The docs cover every SDK and the full API reference, including the loader script at https://cdn.captcha-cdn.net/captchala-loader.js for quick front-end integration.