深入理解浏览器自动化协议:从 CDP 到 BiDi,框架对比与反检测分析

张开发
2026/4/10 10:03:18 15 分钟阅读

分享文章

深入理解浏览器自动化协议:从 CDP 到 BiDi,框架对比与反检测分析
本文从浏览器自动化的底层原理出发梳理 WebDriver Classic、CDP、WebDriver BiDi 三代协议的演进脉络对比主流自动化框架的技术差异并深入分析各方案的反检测特征与局限性。一、浏览器自动化的底层基础在聊协议之前先搞清楚浏览器到底是什么。每个浏览器内核由两个核心引擎组成浏览器JS 引擎渲染引擎Chromium (Chrome/Edge)V8BlinkFirefoxSpiderMonkeyGeckoWebKit (Safari)JavaScriptCoreWebCore所有浏览器自动化框架的本质就是把外部指令传递给这两个引擎去执行。JS 引擎负责执行脚本逻辑渲染引擎负责页面布局、样式计算、DOM 操作等。区别只在于指令怎么传进去二、三代通信协议的演进2.1 第一代WebDriver Classic — HTTP 单向通信这是 Selenium 采用的方式也是最早被 W3C 标准化的浏览器自动化协议。通信链路你的代码 → HTTP 请求 → WebDriver 进程(chromedriver/geckodriver) → 浏览器内部接口 → 引擎每个浏览器厂商都需要开发一个独立的 WebDriver 进程作为中间适配层chromedriver— Google 开发适配 Chromiumgeckodriver— Mozilla 开发适配 Firefoxsafaridriver— Apple 开发适配 Safari这些 driver 的作用就是接收标准化的 HTTP 指令翻译成各自浏览器能理解的内部调用。优点跨浏览器通用W3C 标准。缺点HTTP 是请求-响应模式只能单向通信——你发指令浏览器回结果浏览器不能主动通知你需要额外下载和管理 driver 进程速度相对慢每个操作都是一次完整的 HTTP 请求-响应2.2 第二代CDP — WebSocket 双向通信CDPChrome DevTools Protocol是 Google 为 Chromium 设计的私有调试协议。你按 F12 打开的 DevTools 面板底层就是通过 CDP 和浏览器通信的。Playwright 和 Puppeteer 都直接使用 CDP 协议。通信链路你的代码 → WebSocket → CDP 协议 → Chromium → V8 Blink这里要澄清一个常见的混淆WebSocket 和 CDP 不是二选一的关系而是两个层面的东西。WebSocket— 传输通道怎么传类比 TCPCDP— 协议内容传什么类比 HTTPCDP 跑在 WebSocket 上就像 HTTP 跑在 TCP 上一样。所以Playwright 通过 WebSocket 通信和Playwright 用 CDP 协议说的是同一件事的两个层面。优点双向实时通信——浏览器可以主动推送事件给你比如页面加载完成、网络请求发生没有中间 driver 进程直连浏览器速度快缺点CDP 是 Google 的私有协议只有 Chromium 系浏览器原生支持Firefox 和 WebKit 不原生支持 CDPPlaywright 为了支持 Firefox 做了大量 hack 适配2.3 第三代WebDriver BiDi — 统一的双向标准这就是本文的重点。核心矛盾WebDriver Classic (HTTP) → 跨浏览器通用但只能单向通信 CDP (WebSocket) → 双向实时但只有 Chromium 支持既要双向实时又要跨浏览器通用——这就是 WebDriver BiDi 要解决的问题。BiDi 不是某个人或某家公司发明的而是 Google、Mozilla、Apple 等浏览器厂商在 W3C 框架下共同推进的新标准。官方全名叫WebDriver BiDi本质上是 W3C WebDriver 标准的 2.0 演进版本。通信链路你的代码 → WebSocket → BiDi 协议 → 浏览器内置的 BiDi 模块 → 翻译成内部私有协议 → 引擎关键架构变化BiDi 的适配层是内置在浏览器里的不是一个外部独立进程。Selenium 方式 代码 → HTTP → chromedriver(独立进程) → 浏览器 需要下载和管理 driver 进程 BiDi 方式 代码 → WebSocket → 直连浏览器(内置 BiDi 实现) → 引擎 不需要额外的 driver 进程2.4 三代协议总结特性WebDriver ClassicCDPWebDriver BiDi归属W3C 标准Google 私有W3C 标准通信方式HTTP 单向WebSocket 双向WebSocket 双向中间进程需要外部 driver不需要不需要浏览器支持所有浏览器仅 Chromium所有浏览器逐步实现中速度慢快快三、各浏览器的私有调试协议一个容易被忽略的事实是每个浏览器都有自己的调试协议不只是 Chromium 有。Chromium → CDP (Chrome DevTools Protocol) → 公开、文档完善、生态庞大 Firefox → RDP (Remote Debug Protocol) → 存在但文档少、生态小 WebKit → Web Inspector Protocol → 基本只给 Safari 自己用所以不是其他浏览器没有双向通信能力而是各搞各的协议格式完全不兼容。CDP 因为 Chrome 的市场份额和完善的文档成了事实标准但其他厂商并不愿意实现 Google 的私有协议——这既是政治问题不想把控制权交给 Google也是技术问题CDP 是为 Chromium 架构设计的和 Firefox/WebKit 架构不匹配。BiDi 的本质就是各家都有双向通信能力但协议不统一谁也不服谁所以在 W3C 框架下重新制定了一套大家都认可的标准。BiDi 内置在浏览器中充当一个统一的转化器把标准化的外部指令翻译成各家的私有协议BiDi内置于 Chromium→ 转成 CDP 调用 → V8 Blink BiDi内置于 Firefox → 转成 RDP 调用 → SpiderMonkey Gecko BiDi内置于 WebKit → 转成 Inspector 调用 → JavaScriptCore WebCore各家原有的私有协议CDP、RDP 等不会消失它们依然是浏览器内部的核心调试机制。BiDi 只是在上面加了一层统一的接口。四、Chromium vs Chrome一个常被忽略的区别聊 Playwright 的时候经常有人问Playwright 安装时下载的 Chromium 和我们日常用的 Chrome 有什么区别Chromium开源项目 ├── 纯开源代码 ├── 没有 Google 服务账号同步、自动更新等 ├── 没有专有编解码器部分视频格式不支持 └── 任何人都可以编译、修改 ChromeGoogle 的产品 ├── 基于 Chromium 源码 ├── Google 账号体系 ├── 自动更新机制 ├── 专有媒体编解码器H.264 等 └── 一些闭源商业组件简单说Chromium 是毛坯房Chrome 是 Google 精装修后的成品房。核心引擎V8 Blink完全一样。Playwright 为什么不直接用你电脑上的 Chrome因为 CDP 协议的接口会随版本变化Playwright 需要精确控制 Chromium 版本来确保兼容性。同理支持 BiDi 的浏览器需要较新版本——Chromium 大约 114Firefox 也需要较新版本才完整支持 BiDi。这也是为什么 RuyiPage 推荐使用它指定的 Firefox 版本。五、主流自动化框架对比框架主要浏览器方向底层协议CDP 暴露面Firefox / BiDi 支持度被检测风险RuyiPageFirefoxWebDriver BiDi无高主路线就是 Firefox BiDi低当前阶段PlaywrightChromium / Firefox / WebKitCDP 为主中到高中支持但不以 BiDi 为核心中到高Selenium多浏览器WebDriver Classic 部分 BiDi低到中中兼容广但 BiDi 能力不强中PuppeteerChromiumCDP高低高DrissionPageChromium混合驱动核心偏 Chromium中到高低中到高选型建议主做 Firefox 自动化关注反检测 →RuyiPage多浏览器统一自动化 →Playwright / Selenium主做 Chromium/CDP →Puppeteer / PlaywrightFirefox BiDi 高层封装 →RuyiPage六、反检测深度分析6.1 CDP 方案Playwright/Puppeteer的主要检测点调试端口开放Playwright 启动 Chromium 时需要开放 CDP 调试端口如 9222反爬系统可以探测到这个端口的存在。这是一个从外部建立的 WebSocket 连接网站能够感知到有人从外面在控制我。浏览器启动参数特征# Playwright 启动 Chromium 时典型的参数--disable-blink-featuresAutomationControlled --enable-featuresNetworkService --disable-background-networking --disable-default-apps --no-first-run这些参数组合本身就是特征——正常用户不会这样启动浏览器。navigator / window 属性异常navigator.webdriver// 可能为 truenavigator.plugins.length// 自动化浏览器通常为 0navigator.languages// 可能与系统语言不匹配navigator.permissions.query({name:notifications})// 真实浏览器返回 prompt自动化浏览器可能返回 deniedJS 执行堆栈差异核心 CDP 暴露面通过 CDP 的Runtime.evaluate执行的 JS和页面自身的 JS 相比Error.stack堆栈信息不同。网站可以通过分析堆栈帧来识别 CDP 注入的脚本。consterrnewError();console.log(err.stack);// CDP 调用的堆栈里会出现特殊的帧信息// 正常页面 JS 不会有这些事件可信度CDP 发送的点击事件event.isTrusted可以伪造为true但事件的其他属性时间戳精度、坐标分布、事件序列可能不自然。WebGL / Canvas 指纹WebGLRenderingContext.getParameter(renderer)// 返回 Google SwiftShader → 大概率是自动化环境自动化浏览器通常运行在无 GPU 环境WebGL 渲染器字符串会暴露虚拟 GPU 特征。6.2 BiDi 方案RuyiPage为什么当前检测少无外部 CDP 连接痕迹BiDi 是浏览器内置模块不需要从外部建立 CDP 连接没有调试端口暴露。事件原生触发BiDi 通过浏览器原生事件系统触发操作event.isTrusted天然为true不是伪造的。不需要开放调试端口没有 9222 这样的端口特征。启动参数更干净相比 Playwright 启动 Chromium 时的大量非常规参数BiDi 方式更接近正常浏览器启动状态。打个比方Playwright CDP像有人从窗户外面伸手进来操作你的电脑 → 窗户开着屋里的人能看到 BiDi 内置像电脑自己装了个定时任务在执行 → 没有开窗户屋里的人看不出区别6.3 BiDi 并非不可检测——清醒认知BiDi 模块被激活本身就是特征。正常用户浏览网页时浏览器内置的 BiDi 模块不会被启用。只要风控厂商去逆向研究浏览器就能找到 BiDi 启用后的内部状态差异。启用 BiDi 需要特定的启动参数。和 CDP 一样这些参数就是检测特征。浏览器内部状态差异。BiDi 模块激活后浏览器内部某些标志位、运行状态可能和正常使用不同这些都是潜在的检测点。行为层面的通病。这是所有自动化方案都逃不掉的——鼠标轨迹、点击间隔、滚动模式、页面停留时间、请求时序等机器操作和真人操作在统计特征上总有差异。当前 BiDi 检测少的真实原因CDP 被检测 → 因为用了十几年风控厂商研究透了检测规则成熟 BiDi 暂时安全 → 因为太新风控厂商还没投入精力去研究 这不是技术优势是时间差优势。等 BiDi 普及了、用的人多了风控厂商一定会逆向浏览器找到 BiDi 启用后的特征建立指纹库覆盖检测规则。七、结论没有银弹回顾整个演进路线WebDriver ClassicHTTP 单向 ↓ 解决双向通信问题 CDPWebSocket 双向但 Chromium 专属 ↓ 解决跨浏览器问题 WebDriver BiDiWebSocket 双向 跨浏览器标准每一代协议都在解决上一代的核心痛点但没有任何一代能从根本上解决被检测的问题。因为自动化操控浏览器本身就不是正常用户行为程序控制和真人操作之间的差异不会因为换一个协议就消失。所有自动化方案——无论是 CDP、BiDi 还是未来可能出现的新协议——都只是在拉长被风控追上的时间窗口。选择框架时应该根据实际场景目标浏览器、性能需求、维护成本来决定而不是追求绝对不被检测。务实的选型思路需要 Firefox 当前反检测窗口期 → RuyiPage需要多浏览器通用 生态成熟 → Playwright / Selenium需要 Chromium 深度控制 → Puppeteer / Playwright需要长期稳定 → 关注行为层面的拟人化而不是押注某个协议本文基于对 WebDriver、CDP、WebDriver BiDi 协议的技术分析以及对 RuyiPage、Playwright、Selenium 等框架的对比研究整理而成。协议标准仍在演进中文中观点基于 2026 年 4 月的现状。

更多文章