Where the flag comes from
The WebDriver standard - the W3C rulebook for how software remote-controls a browser - requires a conforming automation session to set navigator.webdriver to true, so that pages can tell they are being driven. Chrome sets it when launched with the --enable-automation switch or controlled via the DevTools Protocol; Firefox sets it under Marionette (Firefox's automation engine); every mainstream automation framework triggers it by default. On a normal human browser session it is false.
That makes it a perfect first-pass filter: one line, if (navigator.webdriver) flag(), catches every scraper that has not specifically dealt with it - which is a surprising number, because many tutorials never mention it.
Why naive hiding gets caught anyway
The obvious fix is to overwrite the property: Object.defineProperty(navigator, "webdriver", { get: () => false }). This makes the value read false, but it introduces new, detectable artifacts (telltale leftovers of the tampering):
- The getter - the small function that runs when the value is read - is now ordinary JavaScript.
Object.getOwnPropertyDescriptor(navigator, "webdriver").get.toString()returns the patch source instead of"[native code]"(the marker browsers show for built-in functions) - caught by Function.toString() inspection. - On real Chrome,
webdriverlives onNavigator.prototype(the shared blueprint all navigator objects inherit from), not as an own-property of thenavigatorinstance. Defining it on the instance changes where it appears in the prototype chain - itself a tell. - If the patch runs after page scripts, there is a race where the real value is briefly observable.
So spoofing the value with JavaScript trades one obvious signal for a subtler one. The clean fix is to launch the browser so the flag is never set - excluding the enable-automation switch - or to patch at the engine level so the property reads false natively.
Necessary but not sufficient
The most important thing to understand about navigator.webdriver is its place in the detection stack: it is the floor, not the ceiling. Passing it means you are not in the bottom tier of trivially-detectable bots. It tells a vendor nothing reassuring - real users pass it too - so failing it is fatal but passing it earns you nothing. Serious anti-bot systems (Kasada, DataDome, Akamai) treat it as a checkbox and move on to TLS fingerprints (clues from the https handshake), canvas/WebGL/audio coherence (whether those graphics and sound APIs all describe the same machine), behaviour, and the harder probes.
This is why tooling that only hides navigator.webdriver (some minimal patching scripts) still gets blocked everywhere that matters. The flag is the first gate; the real contest is the coherent fingerprint behind it. Engine-level browsers launch with the flag genuinely absent and harden the rest.
