关于 browser-trace
browser-trace 是用于调试浏览器自动化的只读观测技能。它同步记录 CDP 事件、定时截图和 DOM 快照,并整理数据供后续检查,不会操作页面。
主要功能
- 01只读捕获 CDP 事件
- 02定时采集截图和 DOM 快照
- 03按方法和页面拆分事件
- 04查询页面、错误和主机
适用场景
- 01排查表单或导航失败
- 02为运行中的自动化附加追踪
- 03检查网络与控制台事件
- 04按时间对照截图和 DOM
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ browserbase/ skills --skill browser-trace安装后在 Claude Code 中输入/browser-trace确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
EXAMPLES.mdLICENSE.txtpackage.jsonREFERENCE.mdscripts/bb-capture.mjsbb-finalize.mjsbisect-cdp.mjslib.mjsquery.mjssnapshot-loop.mjsstart-capture.mjsstop-capture.mjs详细介绍
浏览器跟踪
将第二个只读 CDP 客户端连接到已由主自动化程序控制的浏览器会话。跟踪器会将完整的 DevTools 事件流记录为 NDJSON,同时轮询截图和 DOM 转储,并将所有内容切分到目录树中,方便使用 bash 工具搜索。
此技能不会驱动页面,只负责监听。请将它与 browser 技能、browse、Stagehand、Playwright 或任何其他支持 CDP 的工具搭配使用。
适用场景
- 用户想要调试一次浏览器自动化运行(表单失败、元素缺失、导航卡住、JS 异常)。
- 用户正在运行自动化任务,想在任务进行中附加跟踪器,而不重启任务。
- 用户想将 CDP 事件流拆分到网络、控制台、DOM 和页面分类中。
- 用户想要按时间获取截图和 DOM 快照,并与 CDP 事件对应起来。
如果用户只是想驱动浏览器,请改用 browser 技能。
检查设置
node --version # require Node 18+
which browse || npm install -g browse
which jq || true # optional — used only for ad-hoc querying
验证 browse cdp 是否存在:
browse --help | grep -q "^\s*cdp " || echo "browse cdp not available — update browse"
工作原理
每个 Chrome DevTools 目标都支持多个并发 CDP 客户端。主自动化程序是一个客户端;此技能会添加第二个客户端,只启用观测域(Network、Console、Runtime、Log、Page),绝不发送操作命令。
跟踪器包含三个部分:
- 事件流:
browse cdp <target>会将每个 CDP 事件作为一行 JSON 对象流式写入cdp/raw.ndjson。 - 采样器:轮询循环会按固定间隔(默认 2s)调用
browse screenshot --cdp <target> --path <file>和browse get html body --cdp <target>。采样时,辅助程序会传入--cdp,以便从自己的进程连接到被跟踪的目标;一旦 browse 守护进程会话连接到 CDP 目标,该会话中的后续命令就无需重复传入--cdp。 - 二分器:运行结束后,
bisect-cdp.mjs会遍历一次raw.ndjson,按 CDP 方法将内容切分到各分类的 JSONL 文件中;此外,还会以顶层Page.frameNavigated事件为边界,按页面进一步切分。
快速开始
本地 Chrome
# 1. Launch Chrome with a debugger port (any user-data-dir keeps it isolated).
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
--remote-debugging-port=9222 \
--user-data-dir=/tmp/chrome-o11y \
about:blank &
# 2. Start the tracer.
node scripts/start-capture.mjs 9222 my-run
# 3. Run your main automation against port 9222.
browse open https://example.com --cdp 9222
# ...whatever the run does...
# 4. Stop and bisect.
node scripts/stop-capture.mjs my-run
node scripts/bisect-cdp.mjs my-run
Browserbase 远程服务
两个辅助程序负责处理平台端的相关操作:bb-capture.mjs 会创建或连接会话并启动跟踪器;bb-finalize.mjs 会在结束时将平台资源(最终会话元数据、服务端日志、下载文件)拉取到运行目录。
Browserbase 会在最后一个 CDP 客户端断开连接时立即结束会话。使用
--keep-alive创建会话,然后在启动跟踪器之前或同时,让自动化程序连接到会话的connectUrl。bb-capture.mjs --new会处理启用 keep-alive 的会话创建和跟踪器设置;自动化程序仍需自行连接。
export BROWSERBASE_API_KEY=...
# 1. Create a keep-alive session AND start the tracer in one step.
# Prints the session id, connectUrl prefix, and a live debugger URL you
# can open in a browser to watch the run interactively.
node scripts/bb-capture.mjs --new my-run
# 2. Drive automation. bb-capture stamped the session id into the manifest.
SID=$(jq -r .browserbase.session_id .o11y/my-run/manifest.json)
CONNECT_URL="$(browse cloud sessions get "$SID" | jq -r .connectUrl)"
BROWSE_NAME=my-run-browser
browse open https://example.com --cdp "$CONNECT_URL" --session "$BROWSE_NAME"
browse open https://news.ycombinator.com --session "$BROWSE_NAME"
# 3. Stop the tracer, bisect, then pull platform artifacts and release.
node scripts/stop-capture.mjs my-run
node scripts/bisect-cdp.mjs my-run
node scripts/bb-finalize.mjs my-run --release
连接到已在运行的会话(例如由生产工作进程创建的会话)——bb-capture.mjs 接受会话 ID,无需使用 --new:
# Pick a running session (filter client-side; browse cloud sessions list has no --status flag)
browse cloud sessions list | jq -r '.[] | select(.status == "RUNNING") | .id'
node scripts/bb-capture.mjs <session-id> mid-flight-debug
# ...tracer runs alongside the existing automation client; no disruption...
node scripts/stop-capture.mjs mid-flight-debug
node scripts/bisect-cdp.mjs mid-flight-debug
node scripts/bb-finalize.mjs mid-flight-debug # without --release: leave the session running
Browserbase 平台会提供哪些内容
bb-capture.mjs 会在 manifest.json 中添加一个 browserbase 块(会话 ID、项目、区域、started_at、expires_at、调试器 URL)。bb-finalize.mjs 会写入:
<run>/browserbase/session.json— 最终的browse cloud sessions get快照(proxyBytes、status、ended_at、viewport 等)<run>/browserbase/logs.json—browse cloud sessions logs输出。通常为空。cdp/raw.ndjson中的 CDP 事件流才是事实来源;这是一个辅助通道。<run>/browserbase/downloads.zip— 会话下载的文件(如果有;没有文件时,脚本会丢弃生成的空 22 字节 ZIP 文件)
已弃用会话回放资源的获取功能,因此不会获取这些资源。请使用 screenshots/ 和 dom/ 中的截图和 DOM 转储作为视觉事实依据。
清单中的实时 debugger_url 会打开由 Browserbase 提供的交互式 Chrome DevTools 视图,方便在跟踪器将事件流捕获到磁盘的同时查看长时间运行的自动化任务。
文件系统布局
.o11y/<run-id>/
manifest.json run metadata: target, domains, started_at, stopped_at
index.jsonl one line per sample: {ts, screenshot, dom, url}
cdp/
raw.ndjson full CDP firehose (one JSON object per line)
summary.json {sessionId, duration, totalEvents, pages[]} — see shape below
network/{requests,responses,finished,failed,websocket}.jsonl session-wide buckets (always written)
console/{logs,exceptions}.jsonl
runtime/all.jsonl
log/entries.jsonl
page/{navigations,lifecycle,frames,dialogs,all}.jsonl
dom/all.jsonl (only if O11Y_DOMAINS includes DOM)
target/{attached,detached}.jsonl
pages/ per-page slices, indexed by top-level frameNavigated boundaries
000/ first concrete page
url.txt the URL for this page
summary.json this page's domains/network/timing block (same shape as a pages[] entry)
raw.jsonl firehose scoped to this page
network/, console/, page/, runtime/, log/, target/, dom/ same buckets, only non-empty files
screenshots/<iso-ts>.png one PNG per sample interval
dom/<iso-ts>.html one HTML dump per sample interval
browserbase/ added by bb-finalize.mjs (Browserbase runs only)
session.json final `browse cloud sessions get` snapshot (proxyBytes, status, ended_at, …)
logs.json `browse cloud sessions logs` output (often [])
downloads.zip `browse cloud sessions downloads get` output (only if the session downloaded files)
通过 bb-capture.mjs 启动运行时,manifest.json 还会包含一个顶层 browserbase 块:session_id、project_id、region、started_at、expires_at、keep_alive、debugger_url。
摘要结构
cdp/summary.json 是所有分析的入口:其中包含会话级别的总数,以及按顶层 Page.frameNavigated 编号的 pages[] 数组。每页条目按导航顺序生成(page 0 = 第一个具体 URL)。
{
"sessionId": "45f28023-…",
"duration": { "startMs": 1777312533000, "endMs": 1777312609000, "totalMs": 76000 },
"totalEvents": 420,
"pages": [
{
"pageId": 0,
"url": "https://example.com/",
"startMs": 1777312533000, "endMs": 1777312538886, "durationMs": 5886,
"eventCount": 60,
"domains": {
"Network": { "count": 18, "errors": 1 },
"Console": { "count": 2 },
"Page": { "count": 24 },
"Runtime": { "count": 13 }
},
"network": { "requests": 4, "failed": 1, "byType": { "Document": 2, "Script": 1, "Other": 1 } }
}
]
}
startMs / endMs / durationMs 是墙上时钟毫秒数,由 manifest.started_at 加上每个事件的 CDP 单调时间戳偏移量得出。domains[*] 仅在 errors / warnings 非零时才包含这些键。
使用 query.mjs 深入查询
交互式探索时,请使用 scripts/query.mjs <run-id> <command>,无需记忆各文件路径:
node scripts/query.mjs my-run list # one-line table of pages
node scripts/query.mjs my-run page 1 # full summary for page 1
node scripts/query.mjs my-run page 1 network/failed # cat failed.jsonl for page 1
node scripts/query.mjs my-run errors # all errors across pages, attributed by pid
node scripts/query.mjs my-run errors 2 # errors from page 2 only
node scripts/query.mjs my-run hosts # top hosts by request count
node scripts/query.mjs my-run host api.example.com # all requests/responses for a host
node scripts/query.mjs my-run summary # full summary.json
在幕后,它只会读取 cdp/summary.json 和 cdp/pages/<pid>/ 目录树——了解结构后,也可以直接使用原始 jq / rg 命令。
常用遍历方案
# All failed network requests (use jq -c to keep it line-delimited)
jq -c '.params' .o11y/<run>/cdp/network/failed.jsonl
# Find requests to a specific host
jq -c 'select(.params.request.url | test("api\\.example\\.com"))' \
.o11y/<run>/cdp/network/requests.jsonl
# 4xx/5xx responses
jq -c 'select(.params.response.status >= 400)
| {status: .params.response.status, url: .params.response.url}' \
.o11y/<run>/cdp/network/responses.jsonl
# Console errors only
jq -c 'select(.params.type == "error")' .o11y/<run>/cdp/console/logs.jsonl
# Sequence of URLs visited
jq -r '.params.frame.url' .o11y/<run>/cdp/page/navigations.jsonl
# Find the screenshot taken closest to a timestamp (e.g., when an exception fired)
ls .o11y/<run>/screenshots/ | sort | awk -v t=20260427T1714123NZ '
$0 >= t { print; exit }'
完整的 jq 方案库和逐方法二分查找图请参见 REFERENCE.md。端到端调试场景请参见 EXAMPLES.md。
最佳实践
- 在 Browserbase 上使用
bb-capture.mjs:它会强制启用--keep-alive、获取 connectUrl、捕获调试器 URL,并为清单添加时间戳。手动操作容易出错。 - 不要
--release不属于你的会话:bb-finalize.mjs --release适用于由你通过--new创建的会话。通过bb-capture.mjs <session-id>连接生产会话时,请运行不带--release的bb-finalize.mjs,以便原自动化继续运行。 - 远程场景下,顺序很重要:在 Browserbase 上,应在跟踪器之前(或同时)连接主自动化客户端,并使用
--keep-alive创建会话。否则,跟踪器的 WS 一旦关闭,会话就会结束。 - 轮询间隔不要短于约 1 秒:每次采样都会运行浏览器 CLI 读取命令并截取 Chrome 屏幕截图。建议默认使用 2 秒。
- 谨慎选择域:默认值(
Network Console Runtime Log Page)涵盖大多数调试场景。可通过O11Y_DOMAINS="$O11Y_DOMAINS DOM"添加DOM,以跟踪 DOM 树变更(噪声很多)。 - 远程场景下,为自动化客户端复用同一个 Browserbase 会话:通过
browse open ... --cdp "$CONNECT_URL" --session <name>连接该会话的connectUrl。--session标志用于命名本地 browse 守护进程,并非用于连接 Browserbase 会话。 - 始终运行
stop-capture.mjs:即使发生崩溃也要运行,以免后台进程残留,并确保清单包含stopped_at。 - 每次运行只进行一次二分查找:
bisect-cdp.mjs具有幂等性——每次都会从raw.ndjson覆写各分桶文件。
故障排除
browse cdp exited immediately:通常表示无法访问目标(端口错误),或 Browserbase 会话已结束。对于远程服务,使用browse cloud sessions get <id>验证——如果status为COMPLETED,请使用--keep-alive重新创建会话,并先连接自动化工具。- 进程正在运行,但
raw.ndjson为空:确认 CDP 客户端确实在驱动页面。追踪器只会发出浏览器生成的事件,因此空闲的浏览器只会产生约 5 行连接/发现消息,不会有其他内容。 - 所有截图看起来都一样:检查
index.jsonl——如果url没有变化,说明页面尚未导航。轮询循环独立于主自动化流程的运行速度。 - Browserbase 会话在运行中途结束:可能是触发了
--timeout。请使用更长的超时时间重新创建会话(BB_SESSION_TIMEOUT=1800 node scripts/bb-capture.mjs --new ...),或移除超时标志。 bb-capture.mjs <id>提示“not RUNNING”:你尝试连接的会话已结束。使用browse cloud sessions list | jq '.[] | select(.status == "RUNNING")'列出候选会话,然后重试。browserbase/logs.json是空的[]:这是预期行为——实际使用中,browse cloud sessions logs提供的日志很少。cdp/raw.ndjson中的 CDP 事件流才是事实来源。- 会话录制文件(rrweb)在哪里?:已弃用会话回放产物的获取功能;此技能不会获取该文件。请使用
screenshots/中的截图流和dom/中的 DOM 转储。
完整参考请见 REFERENCE.md。 示例调试运行请见 EXAMPLES.md。