返回博客归档

ISSUE / 041

你的浏览器就是 API:bb-browser 如何把没有 API 的网站变成 Agent 工具

最近我在给 OpenClaw 配 agent browser。 看 OpenClaw 这类工具的时候,我顺手注意到了一个名字很野的库: bb-browser 。 这里的 bb ,跟 browser bridge 这类解释没关系,它的意思就是 BadBoy 。 名字起得有点坏,思路也确实有点坏。 如果你最…

你的浏览器就是 API:bb-browser 如何把没有 API 的网站变成 Agent 工具的文章题图

文章封面

最近我在给 OpenClaw 配 agent browser。

看 OpenClaw 这类工具的时候,我顺手注意到了一个名字很野的库:bb-browser

这里的 bb,跟 browser bridge 这类解释没关系,它的意思就是 BadBoy

名字起得有点坏,思路也确实有点坏。

如果你最近也在折腾 OpenClaw、Playwright、CDP 这套东西,那你会很快意识到:bb-browser 走的是另一条 agent browser 路线。

它的实现可以概括成这样:

先让人或者 Agent 把某个网站逆向成一段 JS adapter,运行时再把这段代码注入你已经登录的真实页面,让页面自己去调内部 API、webpack 模块或者 Pinia store,最后只把结构化 JSON 交回来。

如果你理解了这句话,基本就理解了这个库。


顺着 OpenClaw 往下看

先说 OpenClaw 官方这条线。

OpenClaw 官方文档其实写得很直白:它的浏览器控制,本质上是一个 小控制服务 + CDP + Playwright-on-CDP 的组合。

简单说就是:

  • 先有一个控制服务接收命令
  • 再去连接 Chromium 系浏览器的 CDP
  • 对复杂动作,比如点击、输入、快照、PDF
  • 再由 Playwright 站在 CDP 之上完成

而且 OpenClaw 官方同时支持两种形态:

  • 一个隔离的、专门给 Agent 用的浏览器 profile
  • 一个通过 extension relay 接管你现有 Chrome tab 的模式

所以如果你最近在配 OpenClaw,你其实已经接触到了今天多数 agent browser 的主流路线。

粗暴概括一下,现在常见的 agent browser 大概就是三类:

  • Playwright-first:先把浏览器当成一个可点击、可截图、可等待的自动化对象
  • CDP-first:直接对 Chrome DevTools Protocol 下指令,自己封装一层动作
  • Extension relay:通过浏览器扩展接管用户真实 tab,再把命令转发进去

OpenClaw 官方实际上把这几条路拼在了一起:

  • 底层连的是 CDP
  • 复杂交互常用的是 Playwright-on-CDP
  • 想接管现有 Chrome,又能切到 extension relay
常见 agent browser 的实现栈

这条路线很合理,也很标准。它擅长的是:

  • 通用浏览
  • 任意页面操作
  • 点击、输入、截图、等待
  • 把网页当成一个可以交互的图形界面
OpenClaw / Playwright 类 Agent Browser 与 bb-browser 的差别

一个 adapter 文件意味着什么

bb-browser 的表层用法看起来也很像浏览器工具:

bb-browser site twitter/search "AI agent"
bb-browser site zhihu/hot
bb-browser site github/repo epiral/bb-browser

但它真正的重点,不在这些命令本身,而在背后的 site adapter

这个模型非常简单:

  1. 一个网站命令,就是一个 JS 文件
  2. 文件头部写 @meta,声明名字、参数、域名
  3. 运行时找到对应站点的 tab
  4. 把那段 JS 当成函数注入页面执行
  5. 最后拿回结构化 JSON

也就是说,site twitter/search "AI" 这类命令,并不需要每次都经历下面这套流程:

  • 打开 X
  • 找搜索框
  • 输入关键字
  • 点搜索
  • 等页面加载
  • 再从 DOM 里抠结果

它更接近下面这种形态:

  • 我已经知道 X 的内部请求怎么打
  • 我已经把这段调用逻辑写成 adapter
  • 现在把 adapter 扔进已登录的真实页面里跑
  • 让它直接返回结果

这也是它和 OpenClaw 官方那条“浏览器操作路线”最不一样的地方。

OpenClaw / Playwright 这类方案,重点是让 Agent 会操作网页
bb-browser 的重点是让 Agent 少操作网页,直接借网页内部能力


逆向和执行分属两个阶段

要回答这个问题,得先分清 “构建时”“运行时”

先看构建时

bb-browser 的生态前提是:

  • 先有人,或者先让 Agent
  • 用抓包、network --with-body、页面调试
  • 把站点的内部接口、header、store action 搞明白
  • 再写成一个几十行的 JS adapter

所以“通过 Agent 来逆向”这件事,主要发生在 adapter 的生产阶段

也就是说,Agent 可以帮你做这种事:

  • 观察页面发了哪些请求
  • 找到真正的 API 路径
  • 分析需要哪些 header
  • 判断是不是要读 cookie
  • 判断是不是该借 webpack / Pinia
  • 最后生成一个 adapter 文件

再看运行时

到了真正调用的时候,bb-browser 并不会每次都现场逆向一遍。

运行时发生的事情更像这样:

  1. 找到目标站点的 adapter
  2. 找到对应域名的已登录 tab
  3. 把 adapter 拼成一段 eval 脚本
  4. 在页面上下文里执行
  5. 把结果 JSON 返回给 CLI / MCP / Agent

更准确的说法是:

bb-browser 不会在每次调用时重新逆向网站。逆向主要发生在 adapter 的生产阶段;等 adapter 写好之后,运行时只是执行它。

这句话很重要。

因为一旦你这样理解,就会明白它为什么能跑得这么轻。

bb-browser 的关键路径:逆向一次,运行很多次

为什么它一定要跑在页面里

因为它运行的地方,不在 Node,也不在一个脱离上下文的爬虫容器里。

它运行在 网站自己的页面上下文 里。

这意味着 adapter 能天然接触到很多普通自动化很难优雅拿到的东西:

  • document.cookie
  • 页面自己的 fetch
  • window 上挂着的运行时对象
  • webpack 内部模块
  • Vue / Pinia / Vuex store
  • 页面自己的签名、拦截器和状态机

这会带来一个非常实际的结果:

很多你原本以为要逆向半天的东西,其实根本不用重写,只要借页面自己那套就行。

比如:

  • 能直接 fetch(..., { credentials: 'include' }) 的,就直接调
  • 需要 Bearer + CSRF 的,就从 cookie 里读 token 补 header
  • 遇到签名特别重的站点,就干脆借页面自己的 webpack 或 store action

于是它看起来像“没有 API 的网站也有了 API”。

更贴切一点的描述是:

它把网站原本只给浏览器用的那套内部能力,整理成了 Agent 可以复用的执行路径。


放回 OpenClaw 的语境里

这点对最近在配 OpenClaw 的人尤其有意思。

如果你把 OpenClaw 看成一个通用 agent browser,那么 bb-browser 更像是一层专门负责“站点 CLI 化”的能力层。

两者并不冲突,甚至可以叠在一起。

因为 bb-browser 其实已经考虑了这件事:它支持直接借 OpenClaw 的浏览器去跑自己的 adapter。

这就意味着:

  • OpenClaw 负责给你一个可控的浏览器环境
  • bb-browser 负责把某些网站提前压缩成可重复调用的 adapter

于是同一个 Agent 面前,会同时出现两种能力:

  • 一种是通用浏览器动作:打开、点击、输入、截图、等待
  • 一种是站点级工具:twitter/searchzhihu/hotgithub/repo

前者解决“我需要浏览和操作网页”。
后者解决“我已经知道这个网站该怎么拿数据,别再一遍遍点 UI 了”。


接入难度的三个台阶

bb-browser 很聪明的一点,是它没有把所有网站都当成同一个难度。

它基本把 adapter 分成三层。

最简单的一类站点,根本不需要复杂逆向。

只要在真实页面上下文里执行:

  • fetch('/api/...', { credentials: 'include' })

就能拿到结果。

这种站点往往并非完全没有接口,更多是接口只给浏览器里的已登录用户用。

第二层:补 Header

有些站点会要求:

  • Bearer token
  • CSRF token
  • 几个固定的内部 header

那就从页面里把这些值读出来,再手动发请求。

这一层还是请求驱动,只是多补一点站内上下文。

第三层:借页面自己的运行时

最难的是那些签名复杂、请求链又长的网站。

这时候你自己重放请求,很可能会失败。因为页面真正发请求之前,还会先做:

  • 动态 token 生成
  • 参数拼装
  • XHR / fetch 拦截
  • store 状态更新
  • 页面内部的风控与校验

bb-browser 对这种站点的处理方式很直接:

直接借页面自己的那一套。

这也是为什么它能碰小红书这类站点,而不是一上来就卡死在签名上。

适配器复杂度的三级台阶

这里的巧思

我觉得 bb-browser 最巧的一步,是它把:

“让 Agent 接入一个网站”

这件事的成本,压缩到了一个新量级。

以前你要把一个网站接入 Agent,往往要做这些事:

  • 研究站点接口
  • 搭登录
  • 维护 cookie
  • 处理风控
  • 做服务端封装
  • 再把它包装成工具

而 bb-browser 试图把这件事压成:

先逆向一次,写成一个 adapter,以后反复执行。

这会让“互联网里到底有多少站点能被 Agent 用起来”这件事,变成一个比以前更工程化、也更可扩展的问题。


直接试试

如果你最近就在用 OpenClaw,可以直接从这几步开始:

bb-browser site update
bb-browser site list
bb-browser site twitter/search "AI agent" --openclaw
bb-browser site zhihu/hot --openclaw
bb-browser site github/repo epiral/bb-browser --openclaw

如果你更习惯把浏览器当成通用操作界面,OpenClaw / Playwright 这条线会更顺手。
如果你已经知道某个网站该怎么拿数据,想把这件事压成可重复调用的站点命令,那 bb-browser 很值得试一下。