Stealth Mode
Stealth mode is the collection of patches applied to an automated browser to make its JavaScript-visible signals match those of a real, human-driven one, hiding the navigator.webdriver flag, populating empty plugin and language arrays, normalizing WebGL renderer strings, and smoothing over canvas output. It closes the gaps that detection scripts probe for in the browser environment.
The important scoping point: stealth mode operates entirely at the JavaScript layer. It cannot change your TLS handshake, and it cannot change your IP's reputation. A stealth-patched browser running from a flagged datacenter IP is still a flagged datacenter IP, and one using a scripting library's TLS stack still fails a JA3 check before a single line of JavaScript executes. Stealth works alongside IP and TLS-layer changes, not instead of them.
What Stealth Mode Patches
Most stealth implementations target the same well-known set of leaks that detection scripts check first:
navigator.webdriver: set totrueby default in automation-launched browsers, and the single most-checked signal. Stealth patches redefine the property to returnundefined.- Plugins and MIME types: a real Chrome install reports a populated
navigator.pluginsarray; a bare headless instance often reports an empty one. - Languages:
navigator.languagescan come back empty or inconsistent with theAccept-Languageheader actually being sent. - WebGL vendor and renderer: a headless browser without GPU access commonly reports a software renderer (e.g. SwiftShader) rather than a plausible consumer GPU.
window.chrome: present in real Chrome, historically missing or incomplete in headless instances.- Permissions API behavior: the
Notification.permissionvalue and the result ofnavigator.permissions.query()can disagree in automated environments in a way they never do for a real user.
Stealth Tooling by Framework
| Framework | Common stealth approach |
|---|---|
| Puppeteer | puppeteer-extra with the stealth plugin, which applies the patches above as a set of independently toggleable evasion modules |
| Playwright | Community stealth packages and manual addInitScript() patches applied before page load |
| Selenium | undetected-chromedriver, which patches the ChromeDriver binary itself rather than injecting JavaScript after launch |
MrScraper's guide to undetected-chromedriver walks through the Selenium path in Python; the broader browser automation best practices post covers where each framework fits.
What Stealth Mode Can't Fix
This is where most implementations overpromise. Stealth patches run inside the page's JavaScript context, so anything evaluated outside that context is untouched:
- TLS fingerprint: the TLS handshake happens before any HTTP request or JavaScript execution. A stealth plugin cannot change your JA3/JA4 signature.
- IP reputation: a datacenter ASN is visible at the network layer regardless of what the browser reports about itself.
- Behavioral signals: mouse movement, scroll velocity, and dwell time are observed, not declared. Stealth patches don't generate human-like interaction.
- Detection-script drift: anti-bot vendors update their probes continuously. A stealth patch written against last quarter's checks can quietly stop working, and an inconsistently patched browser (one flag fixed, three left) often scores worse than an unpatched one, because the mismatch itself is a signal. That last point is the real constraint: detection scripts increasingly check whether a profile is internally coherent, not just whether individual flags are set correctly. Patching in isolation creates new inconsistencies to find.
For the fuller picture of how these layers stack, see avoid bot detection when scraping and can web scraping be detected.
Related terms
Crawl Depth
Learn what crawl depth means and how to set the max crawl depth for both SEO audits and web scraping jobs.
Read more →CSS Selector
A CSS selector targets HTML elements by class, ID, or attributes in web scraping. Compare CSS selector vs XPath performance and essential scraper syntax.
Read more →Proxy Authentication
Proxy authentication verifies client access via user:password credentials or IP whitelisting before routing requests to prevent 407 unauthorized proxy errors.
Read more →Web Unblocker
Extract data automatically, browse undetected, and beat anti-bot systems — all in one powerful tool.
Get started freeCommunity
Head over to our community where you can engage with us and our community directly.
Questions? Ask our team via live chat, join us on our official Slack community. We're always happy to help.
Join our Slack Community