Skip to main content

Module stealth

Module stealth 

Source
Expand description

Chromium anti-detection (stealth) overrides.

Headless Chromium is trivially identifiable from JavaScript: navigator.webdriver === true, no plugins, English-only languages, Notification.permission === 'denied', WebGL vendor reports “Google Inc. (NVIDIA)”, and so on. Modern WAFs (Cloudflare, Akamai, PerimeterX/HUMAN, DataDome) check these signals and immediately tag the visitor as a bot — no amount of “realistic mouse movement” will recover from a navigator.webdriver === true answer.

apply_stealth(page) injects a CDP Page.addScriptToEvaluateOnNewDocument that overrides each of the well-known fingerprint surfaces BEFORE any page-side script can read them. It must be called once per chromiumoxide::Page before the first goto() — not after.

What this fixes:

  • navigator.webdriver returns undefined instead of true
  • navigator.plugins reports a plausible PDF plugin list
  • navigator.languages returns ["en-US", "en"] instead of []
  • Notification.permission doesn’t lie about being denied
  • window.chrome is faked to look like a real Chrome browser
  • WebGL vendor/renderer report a normal “Intel Inc. / Intel Iris OpenGL Engine” instead of leaking the headless GPU surface
  • screen.width/height set to plausible desktop values when running with --window-size=...

What this does NOT fix:

  • User-Agent string. Your chromiumoxide::Browser config controls that — set it to a real Chrome UA, NOT HeadlessChrome/....
  • TLS fingerprint (JA3/JA4). That requires a different chromium build or a network-layer proxy. Out of scope here.
  • IP reputation. Use residential proxies if your traffic gets blocked by ASN.
  • Realistic mouse trajectories. That’s crate::behavior’s job; stealth and behavioural simulation are complementary, not alternatives — Cloudflare scores BOTH.

Production deployments should call apply_stealth(page).await? immediately after Browser::new_page("about:blank").await? and before navigating to the protected resource. See PRODUCTION.md.

Functions§

apply_stealth
Inject the stealth overrides into every new document on page. Call ONCE per Page, BEFORE any page.goto(...).