凌晨一点四十,监控群里跳出第一条报警。
一个跑了大半年的商品价格采集任务,前一天还稳稳地每小时出一批数据,这一晚突然开始大面积超时。日志翻上去看,请求并没有被拒,页面也返回了 200,只是内容变成了一张 Cloudflare 的验证页。运维把代理换了一轮,IP 是干净的住宅 IP,换完照旧。有人怀疑是频率太高,把并发从 20 压到 3,还是照旧。
最后是一位同事在本地打开同一个链接,顺利看到了商品列表。同样的网络,同样的代理,同样的目标站。区别只有一个:他用的是自己日常用的 Chrome,脚本用的是 Playwright 启动的 Chromium。
这类故事在做爬虫、做自动化测试、做 RPA 的人里几乎人人经历过。它揭开的问题不是”反爬变严了”,而是一个更具体的技术事实:对方并不是在判断你请求得快不快,而是在判断屏幕后面坐的到底是不是人。 一旦这个问题被摆到桌面上,你的工具选择就从”哪个框架 API 好用”,变成了”哪个浏览器能扮得像”。
今天要比的两位,正好代表了回答这个问题的两条路。一条是大家最熟的老路:微软的 Playwright 加上社区的 stealth 插件,在 JavaScript 层给浏览器打补丁。另一条是 CloakBrowser 走的路:干脆去改 Chromium 的 C++ 源码,重新编译出一个浏览器,再包一层跟 Playwright 一模一样的 API。
先搞清楚:网站到底在看你什么
要判断两条路的优劣,得先知道检测方手里有哪些牌。这部分不复杂,说透了你会发现所有争论其实都围着这几张牌转。
最浅的一张是自动化标记。浏览器被程序驱动的时候,navigator.webdriver 这个值会变成 true。这是 W3C 规范里明确写着的,本意是好的,让页面知道自己正被测试工具操作。落到反爬场景里,它就成了最廉价的一道筛子,一行 JS 就能查。
往深一层是指纹。同一段绘图指令,不同显卡、不同驱动、不同字体库画出来的图,像素级别上会有细微差异。把这张图哈希一下,就得到一个 Canvas 指纹。WebGL 能吐出显卡的厂商和型号字符串,音频处理管线有自己的数值特征,系统装了哪些字体也能一个个试出来。这些值单看都不敏感,凑在一起就相当于一张身份证。真正要命的地方在于一致性:一台机器自称是 macOS 上的 Chrome,却报出一个 Linux 服务器上常见的显卡型号,字体列表里又少了苹果系统标配的那几套,这就矛盾了。检测系统不需要证明你是机器人,它只要发现你在撒谎,就足够给你一个低分。
再深一层是网络层握手。TLS 连接建立的时候,客户端会把自己支持的加密套件、扩展、顺序一股脑发出去,这串东西的排列组合本身就有特征,业内把它的指纹算法叫 JA3、JA4。真 Chrome 发出来的握手长什么样,是有定数的。如果你的浏览器自称 Chrome,握手却不对版,连页面都还没加载,服务端就已经心里有数了。
最后一层是行为。鼠标是不是走直线、点击前有没有减速、打字的间隔是不是整齐得像节拍器、滚动是一格一格跳还是有惯性。这些东西不会立刻把你判死,但会作为分数的一部分累加进去。reCAPTCHA v3 那个 0.0 到 1.0 的评分,很大程度上就吃这一层。
四层牌摊开之后,选工具的标准就清楚了:你的方案能覆盖到第几层,以及覆盖得牢不牢。
老路:Playwright 加一层插件
Playwright 本身是微软出的浏览器自动化框架,Apache 2.0 许可,代码全开,谁都能用、能改、能商用。它的定位从第一天起就是端到端测试,不是反爬。所以官方版本里没有任何伪装逻辑,navigator.webdriver 老老实实报 true,headless 模式下 User-Agent 里还大方地写着 HeadlessChrome。在测试场景里这完全合理,你测自己的站,没必要藏。
真正干反检测这件事的,是社区。playwright-extra 提供插件机制,puppeteer-extra-plugin-stealth 提供具体的伪装模块,两个装在一起,就是过去几年最主流的组合。它的工作方式是在每个页面加载之前注入一段 JS,把那些会露馅的属性改掉:把 navigator.webdriver 改成 false,给 navigator.plugins 填上一份看起来正常的插件清单,把 window.chrome 这个真 Chrome 才有的对象补出来,再拦下 WebGL 的查询接口,让它返回一张显卡的名字。
这套路子之所以流行,是它足够便宜。装两个 npm 包,改几行初始化代码,原有脚本一行不动。对于大量只做了第一层检测的站点,这就够用了,而且用了好几年。
问题也出在同一个地方:它改的是结果,没改机制。
JS 注入有个绕不开的尴尬,你想把某个函数的行为改掉,就得替换它。而被替换过的原生函数,在 JS 里是留痕的。原生函数打印出来是 function toString() { [native code] },你自己写的不是。于是插件得再劫持一次 toString,把打印结果伪装回去。检测脚本知道这招,就换个角度查:看函数的属性描述符,查原型链上的继承关系,拿 Object.getOwnPropertyDescriptor 对比,或者在 iframe 里取一份没被污染的原生实现来比对。这是一场你补一处、对方查一处的循环,规则还天然不对等:防守方要把每个入口都堵住,进攻方只要找到一个没堵住的就赢了。
更难受的是两个结构性问题。
第一是 TLS 那一层,JS 根本碰不到。加密握手发生在浏览器网络栈里,注入脚本只能在页面里跑,伸不进去。插件把页面伪装得再好,握手指纹该不对版还是不对版。
第二是维护节奏。Chrome 大约每四周发一个大版本,每次都可能动到这些接口的实现细节,原本有效的补丁随时失效。这就要求插件跟着高频更新。这里有个可以自己去查的事实:playwright-extra 和 puppeteer-extra-plugin-stealth 在 npm 上最近一次发版,都停在 2023 年 3 月。两个包是 MIT 许可,代码摆在那里谁都能 fork 能改,社区里也确实有人维护自己的分支。但如果你的生产任务直接依赖官方包,你依赖的是一份三年多没动过的伪装逻辑,去对抗一个每月更新的浏览器和一群每天都在调模型的检测服务。
开源项目作者没有义务永远维护下去,反检测这件事也确实费力。只是作为选型的人,你得把这个前提摆到明面上算。
新路:不打补丁,直接改浏览器
CloakBrowser 的思路是另一个方向。既然在 JS 层伪装总会留痕,那就不在 JS 层做,把改动放到 Chromium 的 C++ 源码里,编译进二进制。
按官网的说法,这些改动一共 73 处,覆盖 Canvas 行为、WebGL 渲染器、WebGPU 适配器、音频处理、字体枚举与字体度量、GPU 厂商与型号、CPU 核心数、设备内存、屏幕参数、时区、语言、User-Agent 与 Client Hints、语音合成列表、媒体设备、WebRTC 的 IP 暴露、存储配额、WebAuthn 能力这些点,再加上驱动层的输入行为和自动化信号移除。官网那句话说得挺直接:这是一个真浏览器,反爬系统把它评成正常浏览器,因为它本来就是。
改源码带来的差别在哪?回到刚才那个 toString 的例子。JS 方案里,那个函数确实被替换过,你只能层层伪装替换的痕迹。而在源码层面,函数的实现从一开始就是你要的那个,它就是原生的,没有痕迹可查,因为没有发生过替换。检测脚本翻属性描述符、翻原型链、开 iframe 取干净实现,拿到的都是同一份自洽的答案。
TLS 那一层也顺带解决了。网络栈就在同一个二进制里,握手指纹跟着 Chrome 走,官网列的测试结果里写着 ja3n、ja4、akamai 三套指纹与 Chrome 一致。
行为层给了个开关。打开 humanize=True 之后,鼠标按贝塞尔曲线移动,键盘输入带停顿,滚动有惯性。这类东西自己写得出来,难在写好一套还要长期维护,做成一个参数确实省事。
它的产品形态是:一个自己编译的 Chromium 二进制,外面套一层薄封装。Python 用 pip install cloakbrowser,JavaScript 用 npm install cloakbrowser,第一次启动的时候自动下载对应平台的二进制,大约 200MB,下完缓存在本地。之后每次启动,都是让 Playwright 或 Puppeteer 去驱动这个二进制。Linux x64、Linux ARM64、Windows x64、macOS 都有,官网标的内核版本是 Chromium 151,还提供 Docker 镜像。除了 Python 和 JavaScript,.NET 也有对应的入口。
有一点要说清楚,它跑在你自己的机器上。浏览器会话、页面内容、Cookie、登录凭据都留在你自己的环境里,不经过第三方。对于要处理账号和敏感数据的活,这个区别很实在。
还有一条容易被忽略的能力:它带一个 Manager,官网把它定位成 Multilogin、GoLogin、AdsPower 这类指纹浏览器的自托管替代品,每个配置文件有独立指纹、独立代理、独立 Cookie,跑在同一个内核上。做多账号运营的人应该一眼就懂这是什么。
摆在一起看
把两条路的关键差异放到一张表里,方便你对着自己的场景勾选。看之前提醒一句:右边这一列的检测结果和参数来自 CloakBrowser 官网自己公布的测试页,标注的最近测试时间是 2026 年 8 月、内核 Chromium 151。厂商自测数据当然要打个折扣,自己跑一遍才算数,官网给了 docker run --rm cloakhq/cloakbrowser cloaktest 这个命令,验证成本不高。
| 对比项 | Playwright + stealth 插件 | CloakBrowser |
|---|---|---|
| 伪装发生的位置 | 页面加载前注入 JS,改运行时属性 | 改 Chromium C++ 源码后编译,官网称 73 处 |
| 自动化标记 | 靠脚本改写,可能被深层反射查出 | 源码层处理,navigator.webdriver 报 false |
| TLS 握手指纹 | 覆盖不到,JS 碰不到网络栈 | 官网称 ja3n / ja4 / akamai 与 Chrome 一致 |
| 行为模拟 | 自己写移动轨迹和输入节奏 | humanize=True 一个开关 |
| 许可与费用 | Playwright 本体 Apache 2.0,插件 MIT,全免费 | 二进制闭源,订阅制,有免费档但只给一个并发会话 |
| 维护状态 | 两个插件包 npm 最新发版停在 2023 年 3 月 | 按订阅页说法随版本持续更新,当前 v151 |
| 部署方式 | 装 npm 包,自己管 Chromium | 自动拉 200MB 二进制,自托管,有 Docker 镜像 |
| 语言支持 | Node 生态为主 | Python、JavaScript、.NET |
| 能不能打包进自家产品卖 | 可以,遵守开源许可即可 | 不行,要单独谈 OEM 授权 |
| 迁移成本 | 已有 Playwright 代码改几行初始化 | 换 import,其余代码不动 |
| 验证码 | 不处理 | 不处理,官网明确写了不做解码服务 |
| 代理 | 自己接 | 自己接,不内置轮换 |
表里最后两行值得单独说一下,因为它是很多人选型时的误解来源。两边都不解验证码。CloakBrowser 的说法是它帮你减少验证码被触发的次数,而不是出现之后替你点掉。代理同理,两边都要你自己带 IP 资源。所以任何一方都不是”装上就通”的银弹,IP 质量差、行为模式蠢、请求节奏离谱,照样会被拦。
钱和自由,得一起算
技术之外,许可和费用这笔账往往才是拍板的那一下。
Playwright 这边干净利落。本体 Apache 2.0,插件 MIT,零成本,能商用,能改源码,能打包进你自己的产品卖给客户。你唯一付出的是时间:出问题自己查,补丁失效自己修,想要行为模拟自己写。
CloakBrowser 是商业产品。二进制不开源,按并发会话数订阅。官网当前的促销价格是 Solo 档每月 19 美元、5 个并发会话,Team 档 49 美元、20 个,Business 档 199 美元、200 个,Scale 档 499 美元、2000 个,四档对应的原价分别是 29、79、249 和 699 美元。四个档位用的都是同一个最新内核,买的是并发上限。免费档给一个会话,够你验证能不能过目标站。授权用环境变量 CLOAKBROWSER_LICENSE_KEY 配,代码不用改。取消订阅之后当期继续可用,之后封装层在下一次授权检查时退回免费版,不再拿新版本。
有两条限制条款要提前看清楚,它直接决定某些团队能不能用。
第一条,二进制不许再分发、转售、转授权或重新打包,改没改都不行。在你自己的基础设施里跑原版是允许的,给自己组织内部用的 Docker 镜像、虚拟机模板、CI runner、内部制品镜像也都允许。在依赖清单里写上它不算再分发,因为最终用户是从官方渠道下载二进制的。
第二条,你自己的业务用它不需要 OEM 授权,但如果要把它嵌进一个交付给第三方的产品或服务里,包括在自己的服务器上跑它来服务外部客户,也就是做浏览器即服务这类生意,就得单独谈 OEM 或 SaaS 授权。
这两条一摆出来,有些方案就自动出局了。你要做一个爬虫 SaaS 卖给别人,或者在自家 RPA 平台里内置一个反检测浏览器给客户用,不能直接装上就开卖。反过来,你是电商公司自己抓竞品价格、是测试团队自己跑回归、是运营团队自己管一堆账号,这两条都不碍事。
还有一个折中选项。官网提到有 CloakBrowser Cloud,他们托管浏览器,你用自己的代理通过 CDP 连过去,按需申请、邮件联系。不想自己管二进制和字体环境的团队可以问问。另外他们在试预付的浏览器小时套餐,给更喜欢按量付费的团队,也是走邮件谈。
迁移这件事,两边都便宜得出奇
这可能是整篇里最让人省心的部分:两个方案的迁移成本都极低,因为它们说的是同一种 API。
已经在用 Playwright 的人,换到 CloakBrowser 基本就是把导入语句换掉。官网给的 Python 示例里,原来那三行创建 playwright 实例、启动 chromium 的代码,合并成 from cloakbrowser import launch 加一句 launch(),后面 new_page、goto 全部照旧。JavaScript 侧同理,Puppeteer 用户走 cloakbrowser/puppeteer 这个子路径。官网也提到跟 Selenium 一起用过,还有 browser-use、Crawl4AI 这类 AI 浏览器代理项目在拿它做底座。
换到 playwright-extra 那套也不难,装包,把 chromium 对象用 addExtra 包一层,use 一下 stealth 插件,之后启动和操作代码不变。
所以决策的重量并不在改代码上。你可以花半小时给现有项目接上任意一方,拿目标站跑一批真实请求,看通过率。这类选型最好的做法从来不是读评测,而是在自己的目标站上跑一次对照实验。 两边都支持免费试,一个本身免费,一个有免费档,试的代价基本只有你的时间。
到底该选哪个
抛开立场,按场景说。
你在做自动化测试,测的是自己公司的产品。 用官方 Playwright 就好,连 stealth 插件都不必装。你不需要骗任何人,反而应该把自动化标记留着,方便测试环境识别。往上叠伪装只会让 CI 变慢、让问题更难排查。这类需求里唯一可能用得上 CloakBrowser 的情况,是你的产品自己接了风控,要验证真实用户在风控下的体验,那时候需要一个”看起来像真人”的客户端来跑通链路。
你在抓公开数据,目标站防护轻,量也不大。 老路够用。Playwright 加 stealth 插件,加一组像样的代理,控制好节奏,大概能覆盖不少站点。真被挡了再往上升级,没必要一开始就付订阅。要注意那两个包已经三年多没发新版,遇到问题先去 issue 和各家 fork 里翻,别指望官方包会给你修。
你的任务已经在 Cloudflare、FingerprintJS、ShieldSquare 这类防护前反复撞墙。 这时候两边不在一个层级上。TLS 指纹和源码级一致性是 JS 注入方案结构上覆盖不了的部分,继续在插件上堆配置,大概率是把时间花在一个补不完的洞上。先用免费档拿你真实的目标站测一轮,通过了再谈订阅,几十美元一个月和一个工程师持续填坑的人力成本相比,账很好算。
你在做多账号运营、RPA、需要一堆互相隔离的浏览器环境。 CloakBrowser Manager 这条线值得单独看。它对标的是 Multilogin、GoLogin、AdsPower 这几家,区别是自托管,配置文件数量不设上限,数据留在你自己手里。如果你现在正在按账号数给指纹浏览器付费,把总价拉出来跟按并发付费的模式对比一下,账面差异可能不小。
你要把浏览器能力打包进产品卖给客户。 先把授权问题谈明白,再谈技术。CloakBrowser 需要 OEM 或 SaaS 授权,谈不下来就只剩开源方案,那意味着你要自己组一支能持续跟进 Chrome 版本的团队,这是长期投入,得提前算进产品成本里。
你是个人开发者,预算为零,主要是学习和折腾。 从 Playwright 加 stealth 插件开始,顺手把前面说的四层检测机制读明白,这比会用某个工具值钱得多。CloakBrowser 的免费档也可以拿来做对照,看看两种伪装在同一个检测站上分数差多少。
最后一句实在话
反检测这条赛道上没有永久有效的方案。检测方在升级,伪装方在跟进,今天能过的站点明天可能就过不去。CloakBrowser 自己在 FAQ 里也承认,不可能每个站每次都赢,这是他们每天在做的事。这个坦白比任何”包过”的承诺都更可信。
所以选型的时候别问”哪个更强”,问两个更具体的:这个方案覆盖到了哪几层检测,以及背后有没有人在持续跟着 Chrome 的版本节奏往前修。 前者决定它现在能不能用,后者决定它三个月后还能不能用。老路在第一个问题上有结构性缺口,在第二个问题上要看你愿不愿意自己接手维护;新路两个问题都给了答案,代价是每月一笔订阅费和一份闭源二进制带来的依赖。
至于最开始那个凌晨报警的故事,后来的处理很直接:先用免费档在被挡的目标站上跑了一轮对照,通过了,再把订阅买上,导入语句换掉,任务当天恢复。那位同事的 Chrome 能打开而脚本不能,问题从来不在网络和代理,在浏览器本身。
还有一件事顺手提醒。CloakBrowser 官网写了使用边界:只用于正当自动化,你自己的账号、你自己的数据、公开站点,不做批量注册、不做凭据滥用、不碰受限的金融和政府类目标。这不只是他们的合同条款,也是这类工具的常识。技术能力越强,越要自己划清线在哪里,不然省下的那点人力成本,迟早会从别的地方加倍付回去。



