Detect browser automation by combining independent request, browser, and
session evidence, then checking it against the action you protect.
navigator.webdriver === true reports WebDriver control; false does not
prove a human visitor. Neither result establishes abuse.
Start with the decision your team needs to make: stop repeated extraction, protect an interactive workflow, or preserve approved monitoring. Choose one route and record both suspicious activity and legitimate completions before enabling enforcement. Blocking more sessions is not success if the intended users can no longer finish that workflow.
For a vendor evaluation, use the bot management checklist to compare evidence availability, false-positive handling, and rollback. For content extraction, the scraping and AI crawler use case connects these checks to resource policy.
Start with navigator.webdriver
navigator.webdriver is the web platform's standard automation disclosure.
The W3C WebDriver specification
says the property returns true when the browser's WebDriver-active flag is
set. The spec describes it as a way for a cooperating browser to tell a page
that WebDriver controls it.
You can inspect it with one expression:
const webdriverDeclared = navigator.webdriver === true;
Interpret the result narrowly:
truemeans this browser reports that it is under WebDriver control;falsedoes not prove that a human controls the browser;- either result says nothing about whether the activity is approved or abusive.
A positive value can come from your own regression tests, uptime monitoring, or another legitimate automated workflow. Automation can also use a different control path or alter browser-visible state. Keep the raw value as one named observation. Do not turn it into a universal block rule.
Build a layered evidence model
Use layers that fail differently. Each layer should record an observation, its source, and its confidence rather than writing a final verdict into the field.
| Signal layer | What it observes | Common evasion or drift | False-positive risk | Pair it with |
|---|---|---|---|---|
| Declared identity | User agent, Client Hints, language, referrer, crawler token | Headers can be copied, removed, or made internally inconsistent | Privacy tools, embedded browsers, unusual clients | Connection, environment, published crawler verification |
| Connection and protocol | Source path, TLS handshake, negotiated protocol, HTTP/2 behavior | Proxies and impersonation libraries change what the server sees | CDN changes, browser updates, shared networks | Declared identity, session continuity, traffic history |
| Browser environment | Exposed APIs, viewport, platform, locale, time zone, feature support | Profiles and injected scripts can modify values | Enterprise policy, extensions, accessibility tools, privacy protections | Declared identity, control artifacts, repeated observations |
| Automation and control artifacts | WebDriver disclosure, injected globals, execution contexts, protocol side effects | Framework and browser changes remove or reshape artifacts | Developer tools, QA harnesses, monitoring, extensions | Environment, session behavior, approved-tool inventory |
| Session behavior | Navigation order, resource graph, interaction sequence, dwell and input timing | Automation can wait, replay, or drive browser input APIs | Power users, assistive technology, prefetching, poor networks | Route risk, first-party session, traffic history |
| Traffic history | Repetition across sessions, accounts, networks, routes, and time windows | Distributed clients rotate identifiers and pace work | NAT, shared offices, viral traffic, scheduled jobs | Strong first-party identity, per-route budgets, current session evidence |
Collect only the fields needed to answer a specific abuse question. A public page, a login form, and an account export need different evidence and response thresholds.
Declared identity
Headers and browser properties are still useful. They establish what the client claims to be and give later layers something concrete to check. Store the claim separately from any inferred identity.
For a named crawler, compare the exact token with the operator's current verification method. Do not treat a plausible browser user agent as verified browser identity. The same rule applies to language, platform, and device claims: an inconsistency can add evidence, but an unusual combination is not a verdict.
Connection and protocol
Connection metadata is observed outside page JavaScript. Useful fields can include the TLS fingerprint, negotiated application protocol, source path, and HTTP version. Collection must happen at the boundary that sees the visitor's connection. A CDN that terminates TLS may expose different metadata to the origin.
HTTP/2 starts with a connection preface followed by a SETTINGS frame from
each endpoint. RFC 9113
defines the frame and its parameters. Implementations can choose different
valid settings, and those choices can change. Record the raw observation and
client version before labeling a value as browser-like or library-like. Avoid
copying exact browser values from an undated fingerprint list into a permanent
rule.
TLS has the same boundary. A JA3 or JA4 value can help expose a disagreement with the declared client, but it can be shared, changed, or imitated. TLS fingerprinting explained covers the collection and normalization details.
Browser environment
Page JavaScript can inspect a browser's reported environment. Start with coarse, explainable fields that support an actual consistency check. This minimal sample can be run on a staging page or in the browser console:
const sample = {
schemaVersion: 1,
observedAt: new Date().toISOString(),
userAgent: navigator.userAgent,
webdriver: navigator.webdriver,
languages: Array.from(navigator.languages).slice(0, 8),
platform: navigator.userAgentData?.platform ?? navigator.platform,
hardwareConcurrency: navigator.hardwareConcurrency ?? null,
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
viewport: { width: innerWidth, height: innerHeight },
coarsePointer: matchMedia("(pointer: coarse)").matches,
};
console.log(JSON.stringify(sample, null, 2));
The output is a lab record, not a score. A narrow viewport on a desktop user agent can be a resized window. A surprising time zone can be travel or a privacy setting. Missing features can come from browser policy. Compare fields with one another and with later sessions before assigning risk.
Canvas, audio, font, and graphics probes expand the fingerprinting surface and the privacy burden. Do not add them merely because they are available. Document the purpose, retention, access, and deletion policy for every field you keep.
Automation and control artifacts
Browser-control protocols can create observable state, but the details are version-specific. The Chrome DevTools Protocol lets tools instrument and inspect Chromium through commands and events. Its documentation also warns that the tip-of-tree protocol changes frequently and does not guarantee backward compatibility.
The CDP Runtime domain supports evaluation and remote objects. Runtime domain documentation
Frameworks expose higher-level operations on top of browser control channels.
For example, Playwright's evaluation documentation separates the test
process from the page's JavaScript environment and shows how page.evaluate()
runs code in the page.
Treat any artifact tied to serialization, an injected property, an execution context, or a framework naming convention as a dated detector. Give it a browser version, tool version, fixture, expected result, and expiry date. When the fixture stops reproducing the artifact, retire the detector instead of assuming the automation disappeared.
Some tools exist to remove these artifacts. Playwright Stealth patches values that page JavaScript can read, while Camoufox changes them inside a modified Firefox build. Keep both kinds in your fixtures.
Session behavior
Behavior is a sequence, not a claim about how humans move. Useful observations include which resources were requested, whether navigation follows reachable links, the order of actions, repeated failures, and the time between meaningful steps.
Avoid rules such as “straight mouse movement means bot” or “fast typing means bot.” Browsers expose input APIs to automation, and frameworks can control timing. Selenium's Actions API provides virtualized pointer, keyboard, and wheel input with configurable pauses. Playwright's input documentation includes clicks, sequential key presses, delays, and programmatic event dispatch.
Legitimate readers also use keyboards, assistive technology, password managers, translation tools, and unusual navigation patterns. Prefer signals tied to the protected workflow: impossible state transitions, repeated high-cost actions, missing prerequisites, or a pace that violates an explicit route budget.
Traffic history
History can show patterns that a single page view cannot: repeated account creation, synchronized retrieval, identifier churn, or the same action spread across many sessions. It also creates the greatest risk of linking unrelated people.
Set a bounded window and a documented grouping key. Distinguish account, first-party session, source network, device evidence, and inferred cluster. Keep an “insufficient history” state. A shared IP address is not a shared actor, and a new visitor is not suspicious because the system has never seen them.
Run a controlled browser-automation lab
Test every detector against browsers and tools you approve for the lab. The first run should use default configurations; add one variation at a time only after the baseline is recorded.
Use this fixture:
- Create a staging page with one article link, one text field, and one submit button. Do not use production accounts or reader data.
- Log the HTTP request, available connection metadata, the environment sample above, and four server-recognized actions: open, follow link, enter text, submit.
- Run 10 clean sessions with a manually operated browser, 10 with current Playwright, and 10 with current Selenium. Use the same browser engine, operating system, network, viewport, and staging route.
- Use a fresh browser profile or context for each session. Randomize the order of the three client groups so time-dependent infrastructure changes do not affect only one group.
- Record observations without blocking. Repeat on another operating system before drawing a rule from an environment field.
The manual run is a comparison case, not “ground truth” for every legitimate reader. Playwright uses browser contexts as isolated profiles in its test model, as documented in its test guide. Selenium WebDriver is a remote-control interface for browser sessions, as described in the WebDriver documentation.
Keep one row per group and configuration:
| Field | Manual browser | Playwright default | Selenium default |
|---|---|---|---|
| Test date and owner | Record | Record | Record |
| Browser, tool, OS versions | Record browser and OS | Record browser, Playwright, and OS | Record browser, driver, Selenium, and OS |
| Configuration and launch arguments | Record | Record | Record |
| Sessions completed / attempted | /10 | /10 | /10 |
navigator.webdriver results | Record counts by value | Record counts by value | Record counts by value |
| Connection and environment differences | Link raw observations | Link raw observations | Link raw observations |
| Four-action sequence completed | Record counts | Record counts | Record counts |
| Candidate signal and exceptions | Record | Record | Record |
| Limitation and retest date | Record | Record | Record |
Do not publish a percentage from 10 sessions as an accuracy rate. The lab finds reproducible differences and broken assumptions. Production validation needs a larger, representative sample with reviewed labels and a measured cost for false positives and false negatives.
Turn observations into decisions
Keep classification separate from response. A useful decision record contains:
- the protected route and action;
- observations from each available layer;
- the confidence and reason for the classification;
- the selected response;
- the rule and model version;
- the fallback when evidence is missing;
- the expiry or review date.
Start new signals in observation mode. Compare them with known QA traffic, approved monitoring, reader sessions, and confirmed abuse. A detector that only works against the default configuration in the lab should remain a weak signal.
Choose the response by risk:
| Situation | Possible response | Guardrail |
|---|---|---|
| Low-risk public article, weak or conflicting evidence | Allow and observe | Do not interrupt the reader for one anomaly |
| Interactive route, several independent concerns | Step up with a bounded challenge or re-authentication | Prevent loops and provide an accessible fallback |
| Expensive action exceeds an explicit account or session budget | Rate-limit that action | Use a strong key and return a documented retry path |
| Restricted action lacks authorization | Deny in the application | Automation classification never replaces authorization |
| High-confidence abusive sequence with reviewed evidence | Block the scoped action or session | Log the reason and keep a fast rollback |
Monitor challenge completion, reader errors, action success, response codes, and rule reasons after rollout. Break results down by route and client cohort. If a browser update changes a signal, move the affected rule back to observation until the lab is repeated.
For non-browser crawlers, choose controls that fit the client instead of
forcing a browser detector onto it. How to block AI crawlers covers robots.txt, verified-client
rules, rate limits, authorization, and rollout safety.
If this lab is part of a vendor evaluation, run the same traffic sample through the checklist above so identity, reader impact, integration, and rollback are tested together.
Before evaluating Centinel on this workflow, review the integration options. Ask which observations are available, where the decision runs, how missing evidence is handled, and how a rule is rolled back. Do not assume a browser probe protects a direct API request or that every connection fingerprint describes the visitor's connection to your origin.
If your team needs to establish which automated traffic reaches the affected pages before choosing controls, request a site audit.
What gets past your existing CDN?
You have a detection checklist. Now test your current protection. Request a free site audit: we run real scraping tools against your site, review the results, and email you the report. Your existing CDN stays in place.
