Add stealth mode for Chrome headless to evade bot detection

Implements comprehensive anti-detection measures:
- Override navigator.webdriver to return undefined
- Inject fake chrome.runtime, chrome.loadTimes, chrome.csi objects
- Add realistic plugins and mimeTypes arrays
- Patch permissions API to hide automation
- Set realistic navigator properties (languages, hardwareConcurrency, deviceMemory)
- Remove ChromeDriver-specific window properties (cdc_*)
- Patch Function.prototype.toString to hide modifications
- Add Chrome flags: --disable-blink-features=AutomationControlled
- Set realistic user-agent without HeadlessChrome identifier
- Exclude 'enable-automation' switch

Tested against bot detection sites:
- bot.sannysoft.com: All major tests pass
- Search engines: Works with DuckDuckGo, Yahoo, Brave, Startpage
- Still detected by: Google reCAPTCHA, Cloudflare Turnstile, Bing
This commit is contained in:
Dhanji R. Prasanna
2026-01-10 20:34:14 +11:00
parent 7da21d7e81
commit 60aeb67c56
5 changed files with 183 additions and 5 deletions

View File

@@ -119,8 +119,16 @@ async fn start_safari_driver<W: UiWriter>(ctx: &ToolContext<'_, W>) -> Result<St
async fn start_chrome_driver<W: UiWriter>(ctx: &ToolContext<'_, W>) -> Result<String> {
let port = ctx.config.webdriver.chrome_port;
// Use configured chromedriver binary or fall back to 'chromedriver' in PATH
let chromedriver_cmd = ctx
.config
.webdriver
.chromedriver_binary
.as_deref()
.unwrap_or("chromedriver");
// Start chromedriver process
let driver_result = tokio::process::Command::new("chromedriver")
let driver_result = tokio::process::Command::new(chromedriver_cmd)
.arg(format!("--port={}", port))
.stdout(std::process::Stdio::null())
.stderr(std::process::Stdio::null())