selenium 4默认被识别因navigator.webdriver恒为true且暴露cdc_变量等指纹;需启动时加--disable-blink-features=automationcontrolled参数,并在driver创建后、访问页面前立即执行cdp命令覆盖webdriver属性。

为什么Selenium 4默认会被检测出是WebDriver?
网站通过 navigator.webdriver 这个只读属性判断是否为自动化环境,Selenium 4 默认会将其设为 true,且暴露大量 WebDriver 特征(如 cdc_ 开头的浏览器指纹、driver.execute_cdp_cmd 的响应头等)。即使你改了 User-Agent,只要这个属性存在或值为 true,多数反爬站点(如 Cloudflare、Akamai、知乎登录页)就会直接拦截。
如何用 Selenium 4 启动时禁用 webdriver 属性?
关键不是“隐藏”,而是“从源头移除”——Selenium 4 不再支持旧版 ChromeOptions.add_experimental_option('excludeSwitches', ['enable-automation']) 的完整效果,必须配合 CDP 命令 + 启动参数双管齐下:
- 启动时加
--disable-blink-features=AutomationControlled参数,抑制部分自动化特征注入 - 在
driver = webdriver.Chrome(...)创建后、访问任何页面前,立即执行:driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', { 'source': 'Object.defineProperty(navigator, "webdriver", {get: () => undefined})' }) - 不要在页面加载后再执行该 CDP 命令,否则已触发的 JS 检测可能早已完成
还有哪些容易被忽略的 WebDriver 暴露点?
仅处理 navigator.webdriver 远不够。以下几处常被遗漏,且现代检测脚本会组合校验:
调用 Cutout.Pro 视觉处理 API 进行背景移除、人像抠图和照片增强,支持文件上传与图片 URL 输入。
-
chrome.runtime存在:Selenium 启动的 Chrome 默认不带扩展,但某些版本会意外暴露该对象。可在 CDP 注入中补一句:delete window.chrome; delete window.navigator.chrome; -
cdc_变量残留:老版本 Selenium 注入的远程调试变量名以cdc_开头,Selenium 4 已默认禁用,但若你手动加了--remote-debugging-port或用了非标准驱动,仍可能泄露。检查driver.get_log('browser')是否含相关错误 - WebGL 和 Canvas 指纹异常:无头模式或 Docker 环境下,
canvas.toDataURL()返回空或固定值,可被识别。避免无头模式,或用真实 GPU 环境运行
实际运行时要注意的兼容性细节
Selenium 4.11+ 对 CDP 支持更稳定,但不同 Chrome 版本对 addScriptToEvaluateOnNewDocument 的执行时机有差异:
- Chrome 115+ 要求 CDP 命令在
driver.get()前调用,否则无效 - 若用
undetected-chromedriver v3,它内部已封装上述逻辑,但会覆盖你自定义的ChromeOptions,建议只用原生 Selenium + 手动 CDP 注入,可控性更强 - 不要依赖
options.add_argument('--headless=new'):新版 headless 仍暴露大量特征,真要无头请用 Xvfb + 普通 Chrome,或接受更高风险
最麻烦的不是代码写不对,而是检测逻辑藏在第三方 JS SDK 里(比如 Sentry、FullStory),它们会在页面任意时刻读取 navigator 属性链——所以 CDP 注入必须早于任何脚本执行,且不能漏掉 Object.defineProperty 的 setter 拦截(虽然多数检测只读 getter)。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










