
一、Browser Harness 到底是什么
官方把它定义成“通过 CDP 直接控制浏览器”的工具,默认连接的是用户已经在运行的 Chrome,而不是自己再起一个新浏览器。run.py 的模式非常简单:从标准输入读一段 Python,先 ensure_daemon(),再把 helpers.py 里预先导入的函数拿来执行。也就是说,你平时不是在写一整套自动化工程,而是在给一个已经连上浏览器的轻量运行时下指令。(GitHub)
它的核心哲学也很明确:去掉 Playwright 这类更高层的中间抽象,直接给 LLM 一个原始 CDP WebSocket,再允许它自己补工具。作者在 Hacker News 上直接说,这个实验就是“用 CDP 替换 Playwright,并给 LLM 完整自由”,整个项目大约 600 行级别。仓库 README 也强调:缺什么能力,Agent 可以中途自己把函数写进 helpers.py。
二、它为什么适合“自动进化爬虫”
这里的“进化”不是指模型参数更新,而是三层东西在迭代:
第一层是交互能力。helpers.py 里已经给了最基础的浏览器原语,例如 new_tab、goto、page_info、screenshot、click、type_text、press_key、scroll、js、upload_file、http_get、cdp 等。Agent 先用这些做事,不够再补。(GitHub)
第二层是交互经验。interaction-skills/ 用来沉淀可复用的 UI 机制,比如下拉框、对话框、iframe、shadow DOM、上传、标签页这些“交互肌肉记忆”。官方文档明确把这类内容定位成可复用的 UI mechanics。(GitHub)
第三层是站点经验。domain-skills/ 用来记某个网站的稳定规律:URL 模式、私有 API、稳定选择器、框架怪癖、特殊等待条件和常见陷阱。官方还要求发现有价值的站点规律后,默认应该贡献回去,因为这样下一次运行就不必再为同一个坑交学费。(GitHub)
所以,Browser Harness 的“自动进化爬虫”可以理解成这样一条闭环:任务执行 → 发现缺口 → 补 helper / 记 interaction skill / 记 domain skill → 下一轮更快更稳。这和传统“脚本挂了就人工修 XPath”是完全不同的工作方式。(GitHub)
三、它的操作原理:为什么它能自修复
1)截图优先,而不是元素定位优先
官方 SKILL.md 写得很直接:默认策略是先 screenshot() 看页面,再决定是否 click(x, y),操作后再截图验证结果。也就是说,它把“视觉闭环”当成主路径,而不是先写一堆选择器。(GitHub)
更关键的是,官方强调坐标点击是默认策略,因为它通过 Input.dispatchMouseEvent 在合成器层生效,能直接穿透 iframe、shadow DOM、跨域嵌套这类前端自动化常见难点。只有当坐标法不合适时,才降级到 js(...) 做 DOM 读取;再不够,就直接发原始 cdp("Domain.method", ...)。(GitHub)
2)自修复靠的是“可编辑安装”
官方安装方式不是普通安装,而是推荐 uv tool install -e .。install.md 解释得很清楚:这样 browser-harness 这个命令会全局可用,但依然指向你本地那个真实仓库目录。于是 Agent 一旦改了 helpers.py,下一次调用 browser-harness 时,执行的就是刚改过的新代码,不需要重新打包、重新安装、重启服务。(GitHub)
3)架构非常薄
SKILL.md 给了架构图:Chrome / Browser Use cloud → CDP WebSocket → daemon.py → Unix socket → run.py。协议也很简单,请求是一行 JSON,响应也是一行 JSON;BU_NAME 用来区分 socket、pid 和日志文件。这个结构的意义是:前端浏览器保持“真实用户态”,而 Agent 只是在一个轻量桥接层上编排动作。(GitHub)
四、新手从零开始:最稳的安装方式
先把仓库克隆到一个长期存在的位置,不要放 /tmp。官方明确建议用稳定目录,因为它希望这个 repo 持续被 Agent 编辑。安装命令如下:
git clone https://github.com/browser-use/browser-harness
cd browser-harness
uv tool install -e .
command -v browser-harness
这组命令和“为什么必须 editable install”的解释,直接来自官方 install.md。(GitHub)
接着,把 SKILL.md 注册给你的 AI 编码助手。官方给了两条路线:
# Codex
mkdir -p "${CODEX_HOME:-$HOME/.codex}/skills/browser-harness" \
&& ln -sf "$PWD/SKILL.md" "${CODEX_HOME:-$HOME/.codex}/skills/browser-harness/SKILL.md"
Claude Code 则是在 ~/.claude/CLAUDE.md 里导入这个 repo 的 SKILL.md。官方说明这样做以后,新的 Codex 或 Claude Code 会话会自动加载 Browser Harness 的运行规范。(GitHub)
五、第一次连浏览器,别一上来就折腾 chrome://inspect
这是官方安装文档里对新手最重要的一条:先直接试连,不要先入为主地以为必须手动开 remote debugging 页面。 因为 Chrome 的 remote-debugging 复选框对 profile 是“粘性”的,只要某个 profile 之前开过一次,后续启动 Chrome 往往就能直接连。(GitHub)
先试:
browser-harness <<'PY'
print(page_info())
PY
如果能返回页面信息,说明 daemon 和浏览器已经通了。run.py 的行为就是:helpers 预导入、daemon 自动启动、再执行 stdin 里的 Python。(GitHub)
只有在 DevToolsActivePort 缺失或为空时,官方才建议打开 chrome://inspect/#remote-debugging,勾选复选框并点击 Allow。反过来,如果只是 connection refused、/json/version 404,官方建议继续轮询最多 30 秒,因为这通常只是 Chrome 还没完全启动。(GitHub)
六、真正适合新手的“自动进化爬虫”使用方案
我建议你把 Browser Harness 用成一个三层采集系统,而不是把所有网页都当成“视觉点点点”:
第 1 层:能不用浏览器就不用浏览器
官方在 SKILL.md 里明确建议:静态页面和直接可用的 API,优先走 http_get(url),甚至可以配 ThreadPoolExecutor 做并发。也就是说,Browser Harness 并不主张“凡事先开浏览器”,而是主张把浏览器留给必须依赖真实会话、动态渲染或复杂交互的页面。(GitHub)
第 2 层:浏览器只负责“拿到对的状态”
如果页面必须登录、必须点筛选器、必须展开异步内容,那就先用真实 Chrome 把页面切到正确状态。这里的默认套路是:
new_tab(url)wait_for_load()screenshot()看当前状态click(x, y)或press_key(...)做交互- 再
screenshot()验证有没有真的成功
这套顺序正是官方推荐的默认工作方式。(GitHub)
第 3 层:抽取时优先 js(),必要时再上原始 CDP
官方对 DOM 读取的态度也很明确:截图和坐标是默认交互路径,但一旦任务变成“读数据”,js(...) 是首选工具;如果 helpers 不覆盖,再直接调用原始 cdp(...)。所以,一个成熟的 Browser Harness 爬虫,不应该停留在“截图识字”,而应该尽快切换到“浏览器负责进入状态,JS/CDP 负责拿结构化数据”。(GitHub)
七、一套完整的落地工作流
下面这套流程,最适合把 Browser Harness 真正做成“会自己越来越好用”的爬虫系统。
第一步:先让 Agent 搜已有技能
官方要求在克隆仓库后,先搜索 domain-skills/,不要一上来发明新打法;只有当你在具体交互机制上卡住了,再去看 interaction-skills/。这一步的目的,是先复用已有经验。(GitHub)
第二步:把任务描述成“目标状态 + 输出 schema”
不要给 Agent 只下“爬这个网站”的模糊命令。更好的写法是:
- 目标网站和入口 URL
- 需要的字段
- 登录态是否允许复用当前 Chrome
- 是否优先找站点私有 API
- 产出 JSON / CSV / Markdown 的结构
这部分是实践建议,但它和官方强调的“domain skill 应记录 URL 模式、私有 API、稳定选择器、等待条件、陷阱”是同方向的。(GitHub)
第三步:执行时坚持“静态/API 优先,视觉兜底”
一个健康的 Browser Harness 爬虫,应当优先找页面请求、接口和直接 HTTP 拉取;只有接口拿不到、页面强依赖交互时,才使用截图和坐标点击。官方甚至把“私有 API”列为最值得沉淀回 domain-skills/ 的发现之一。(GitHub)
第四步:发现共性能力缺失,就改 helpers.py
如果你反复遇到某个动作,比如复杂文件上传、站点内批量下载、某类特殊键盘事件,那就不要每次在任务代码里临时乱写,直接把能力补到 helpers.py。官方 README 的示例就是:Agent 发现 upload_file() 缺失,中途补函数,然后继续完成任务。(GitHub)
第五步:发现站点规律,就写进 domain-skills/
比如某站搜索页有固定 query 参数、某表格必须滚容器而不是滚页面、某下拉框只有按 Escape 才会提交,或者某接口比 DOM 抓取快 10 倍,这些都应该记成站点知识。官方对 domain skill 的要求就是记录“durable shape of the site”,也就是站点持久不变的地图,而不是某次运行日志。(GitHub)
第六步:多代理并发时,用不同 BU_NAME
官方支持 remote browser,也支持用不同 BU_NAME 启多个隔离会话,适合并行子代理或部署在 headless server 上。SKILL.md 明确要求并行代理使用不同名字,否则会抢同一个默认会话。(GitHub)
八、给 Claude Code / Codex 的实用任务模板
你可以直接给 Agent 这样的任务说明:
使用 Browser Harness 采集目标站点数据。
要求:
1. 先搜索 domain-skills/ 和 interaction-skills/,不要重复发明已有方案。
2. 优先找私有 API、网络请求和可直接 http_get 的页面。
3. 必须交互时,采用 screenshot() -> click(x, y) -> screenshot() 验证的循环。
4. DOM 抽取优先用 js(),helpers 不够时再补 helpers.py。
5. 发现网站特有规律后,整理成 domain-skill;发现通用交互规律后,整理成 interaction-skill。
6. 最终输出 JSON 文件,并给出失败页面、失败原因和下一步建议。
这不是官方原文,但它严格贴合官方建议的工作顺序:先搜 skill、默认截图闭环、优先静态/API、js 负责抽取、helpers 可扩展、经验要回流到 skill。(GitHub)
九、最常见的四个坑
1)一上来就 goto(url)
官方明确提醒,第一次导航应优先用 new_tab(url),因为 goto() 会在用户当前活动标签页里跳转,容易把用户正在看的页面冲掉。(GitHub)
2)把截图当最终抽取手段
官方把 screenshot 定位成“理解当前页面和验证动作”的工具,不是主数据通道。真正的数据抓取应尽快切到 js()、http_get() 或原始 cdp()。(GitHub)
3)连不上就疯狂重启 Chrome
官方反复强调:要根据错误信息升级处理。DevToolsActivePort 不存在,才去开 inspect 页;connection refused 往往只是还在启动;no close frame received or sent 更多是 daemon / websocket 陈旧,这时应该先 restart_daemon()。(GitHub)
4)把浏览器视觉点击写死成像素坐标文档
官方对 skill 的要求很清楚:不要把原始像素坐标沉淀成经验,因为 viewport、缩放和布局一变就废。应沉淀的是“如何定位目标”,例如 selector、可见文本、aria 属性、滚动容器规律。(GitHub)
十、什么时候该用 Browser Harness,什么时候不该用
如果你的任务是:真实登录态、重 JS、页面经常改版、iframe/shadow DOM 多、需要 Agent 自己修补流程,Browser Harness 很有优势,因为它本来就是为这种“别拿框架约束 LLM”的场景设计的。(黑客新闻)
如果你的任务是:目标站点极稳定、流程固定、强追求可重放和严格确定性,那我会把 Browser Harness 看成更偏“Agentic browser ops”的方案,而不是最朴素的回归测试工具。这是基于它的设计取向做出的工程判断:它把自由度、自修复和真实浏览器环境放在了比固定脚本回放更高的位置。(黑客新闻)
十一、给新手的最终建议
最稳的入门方式不是“让它直接大规模爬站”,而是按这个顺序:
- 先把 Browser Harness 装好,并接到你自己的 Chrome。
- 先做一个单站、单任务、少字段的小采集。
- 把站点规律沉淀成
domain-skills/。 - 把通用交互补到
helpers.py或interaction-skills/。 - 等单任务稳定后,再用不同
BU_NAME和 remote browser 做并发扩展。
这样你得到的不是“一次性脚本”,而是一套会随着任务积累而越来越强的浏览器采集底座。这个方向,才是 Browser Harness 最有价值的用法。(https://github.com/browser-use/browser-harness)