browser-trace
browserbase/skills
Captura un seguimiento completo del protocolo de DevTools de cualquier automatización del navegador, divide el flujo en segmentos por página en los que se puedan realizar búsquedas y adjunta un seguimiento a una sesión en curso para depurarla.
...Expandir todoRastreo del navegador
Conecta un segundo cliente CDP de solo lectura a una sesión de navegador que ya esté siendo controlada por tu automatización principal. El rastreo registra todo el flujo de datos de DevTools en formato NDJSON, recopila capturas de pantalla y volcados del DOM en paralelo, y organiza todo en un árbol de directorios que las herramientas de bash pueden rastrear.
Esta habilidad no controla páginas, solo escucha. Combínala con la browser función, browse, Stagehand, Playwright o cualquier otra herramienta compatible con CDP.
Cuándo utilizarla
- El usuario quiere depurar una ejecución de automatización del navegador (formulario que falla, elemento que falta, navegación bloqueada, excepción de JS).
- El usuario tiene una automatización en ejecución y quiere añadir un seguimiento sobre la marcha sin reiniciarla.
- El usuario quiere dividir un flujo de datos de CDP en grupos de red, consola, DOM y página.
- El usuario quiere capturas de pantalla e instantáneas del DOM a lo largo del tiempo, vinculadas a eventos de CDP mediante una marca de tiempo.
Si el usuario solo quiere controlar el navegador, utilice la browser habilidad correspondiente.
Comprobación de la configuración
node --version # require Node 18+
which browse || npm install -g browse
which jq || true # optional — used only for ad-hoc querying
Comprueba que browse cdp existe:
browse --help | grep -q "^\s*cdp " || echo "browse cdp not available — update browse"
Cómo funciona
Cada objetivo de Chrome DevTools admite varios clientes CDP simultáneos. Tu automatización principal es un cliente; esta skill añade un segundo cliente que solo habilita los dominios de observación (Red, Consola, Tiempo de ejecución, Registro, Página) y nunca envía comandos de acción.
El rastreador consta de tres partes:
- Firehose:
browse cdptransmite cada evento de CDP como un objeto JSON por línea acdp/raw.ndjson. - Muestreador: un bucle de sondeo llama a
browse screenshot --cdpy--path browse get html body --cdpa intervalos (por defecto, cada 2 s). El ayudante pasa--cdpcuándo realiza el muestreo para poder conectarse al objetivo rastreado desde su propio proceso; una vez que una sesión del demonio de exploración se conecta a un objetivo CDP, los comandos posteriores de esa sesión no necesitan repetir--cdp. - Bisector: tras la ejecución,
bisect-cdp.mjsrecorreraw.ndjsonuna vez, lo divide en archivos JSONL por «bucket» con el método CDP como clave y, además, realiza una bisección por página utilizando losPage.frameNavigatedcomo límites.
Guía rápida
Chrome local
# 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 remoto
Dos funciones auxiliares se encargan de la gestión por parte de la plataforma: bb-capture.mjs crea o se vincula a una sesión e inicia el rastreador; bb-finalize.mjs extrae los artefactos de la plataforma (metadatos finales de la sesión, registros del servidor, descargas) y los coloca en el directorio de ejecución al finalizar.
Browserbase finaliza una sesión tan pronto como se desconecta su último cliente CDP. Crea la sesión con «
--keep-alive» y, a continuación, vincula la automatización a «connectUrl» de la sesión antes o al mismo tiempo que el rastreador.bb-capture.mjs --newSe encarga de la configuración de la sesión «keep-alive» y del rastreador; tu automatización aún debe añadirse.
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
Al vincularse a una sesión que ya está en ejecución (por ejemplo, una creada por tu trabajador de producción): bb-capture.mjs acepta un ID de sesión en lugar de --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 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
Lo que obtienes de la plataforma Browserbase
bb-capture.mjs añade un browserbase bloque a manifest.json (ID de sesión, proyecto, región, started_at, expires_at, URL del depurador). bb-finalize.mjs escribe:
— instantánea final/browserbase/session.json browse cloud sessions getinstantánea (proxyBytes, estado, ended_at, ventana de visualización, …)—/browserbase/logs.json browse cloud sessions logssalida. A menudo vacía. El flujo de datos del CDP encdp/raw.ndjsones la fuente de referencia; esto es un canal secundario.— archivos descargados por la sesión, si los hay (el script descarta el archivo zip vacío de 22 bytes que se obtiene cuando no hay ninguno)/browserbase/downloads.zip
La obtención de artefactos de reproducción de sesiones está obsoleta y no se lleva a cabo. Utiliza las capturas de pantalla y los volcados de DOM en screenshots/ y dom/ como referencia visual.
El debugger_url del manifiesto abre una vista interactiva de Chrome DevTools servida por Browserbase —muy útil para observar una automatización de larga duración mientras el rastreador captura el flujo de datos en el disco.
Estructura del sistema de archivos
.o11y//
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/.png one PNG per sample interval
dom/.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)
Cuando se inicia una ejecución mediante bb-capture.mjs, manifest.json también incluye un browserbase : session_id, project_id, region, started_at, expires_at, keep_alive, debugger_url.
La forma «Resumen»
cdp/summary.json es el punto de entrada para cualquier análisis: contiene los totales a nivel de sesión y una pages[] matriz indexada por el nivel superior Page.frameNavigated. Las entradas por página se emiten en orden de navegación (página 0 = primera URL concreta).
{
"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 Son milisegundos de reloj real, derivados de manifest.started_at más el desplazamiento de la marca de tiempo monótona CDP de cada evento. domains[*] solo incluye errors/warnings claves cuando son distintas de cero.
Profundizar con query.mjs
Para una exploración interactiva, utiliza scripts/query.mjs en lugar de memorizar las rutas:
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
En segundo plano, simplemente lee cdp/summary.json y el cdp/pages/ árbol; no dudes en saltártelo utilizando el código en bruto jq/rg una vez que conozcas la estructura.
Recetas de recorrido en orden ascendente
# All failed network requests (use jq -c to keep it line-delimited)
jq -c '.params' .o11y//cdp/network/failed.jsonl
# Find requests to a specific host
jq -c 'select(.params.request.url | test("api\\.example\\.com"))' \
.o11y//cdp/network/requests.jsonl
# 4xx/5xx responses
jq -c 'select(.params.response.status >= 400)
| {status: .params.response.status, url: .params.response.url}' \
.o11y//cdp/network/responses.jsonl
# Console errors only
jq -c 'select(.params.type == "error")' .o11y//cdp/console/logs.jsonl
# Sequence of URLs visited
jq -r '.params.frame.url' .o11y//cdp/page/navigations.jsonl
# Find the screenshot taken closest to a timestamp (e.g., when an exception fired)
ls .o11y//screenshots/ | sort | awk -v t=20260427T1714123NZ '
$0 >= t { print; exit }'
Consulta REFERENCE.md para ver la biblioteca completa de recetas de jq y un mapa de bisección método por método. Consulta EXAMPLES.md para ver escenarios de depuración de principio a fin.
Buenas prácticas
- Utiliza
bb-capture.mjsen Browserbase: garantiza--keep-alive, obtiene la connectUrl, captura la URL del depurador y estampa el manifiesto. Hacerlo manualmente invita a cometer errores. - No utilices `
--release` en una sesión que no te pertenezca:bb-finalize.mjs --releasees para sesiones que hayas creado con--new. Al conectarte a una sesión de producción mediantebb-capture.mjs, ejecutabb-finalize.mjssin--releasepara que la automatización original siga ejecutándose. - El orden es importante para el modo remoto: en Browserbase, conecta el cliente de automatización principal antes (o al mismo tiempo que) el rastreador, y crea la sesión con
--keep-alive. De lo contrario, la sesión finalizará tan pronto como se cierre el WS del rastreador. - No realices sondeos a intervalos inferiores a ~1 s: cada muestra ejecuta comandos de lectura de la CLI del navegador y realiza capturas de pantalla de Chrome. 2 s es un buen valor por defecto.
- Elige los dominios con cuidado: los predeterminados (
Network Console Runtime Log Page) cubren la mayor parte de la depuración. AñadeDOMpara las mutaciones del árbol DOM (muy ruidosas) medianteO11Y_DOMAINS="$O11Y_DOMAINS DOM". - Reutiliza una sesión de Browserbase para el cliente de automatización remoto conectándote a
connectUrlconbrowse open ... --cdp "$CONNECT_URL" --session. El--sessionindicador designa el demonio de navegación local; no es un indicador de conexión a una sesión de Browserbase. - Ejecuta siempre «
stop-capture.mjs», incluso tras un fallo, para que los procesos en segundo plano no permanezcan activos y el manifiesto sestopped_at. - Realiza una bisección una vez por ejecución:
bisect-cdp.mjses idempotente: sobrescribe los archivos por compartimento desderaw.ndjsoncada vez.
Solución de problemas
- de
browse cdp exited immediately: suele significar que no se puede acceder al destino (puerto incorrecto) o que la sesión de Browserbase ya ha finalizado. Para el modo remoto, compruébalo conbrowse cloud sessions get— sistatusesCOMPLETED, vuelve a crearla con--keep-alivey conecta primero la automatización. raw.ndjsonvacío aunque los procesos se estén ejecutando: confirma que un cliente CDP esté controlando realmente la página. El rastreador solo emite eventos que genera el navegador, por lo que un navegador inactivo produce unas 5 líneas de mensajes de conexión/detección y nada más.- Todas las capturas de pantalla parecen idénticas: comprueba
index.jsonl— siurlno cambia, la página aún no ha navegado. El bucle de sondeo se ejecuta independientemente del ritmo de la automatización principal. - La sesión de Browserbase finaliza a mitad de la ejecución: probablemente se haya alcanzado
--timeout. Vuelve a crearla con un tiempo de espera mayor (BB_SESSION_TIMEOUT=1800 node scripts/bb-capture.mjs --new ...) o elimina el indicador de tiempo de espera. bb-capture.mjsindica «not RUNNING»: la sesión a la que intentabas conectarte ha finalizado. Enumera las opciones conbrowse cloud sessions list | jq '.[] | select(.status == "RUNNING")'y vuelve a intentarlo.browserbase/logs.jsonestá vacío[]: es lo esperado —browse cloud sessions logses escaso en la práctica. El flujo de datos de CDP encdp/raw.ndjsones la fuente de referencia.- ¿Dónde está la grabación de la sesión (rrweb)?: la obtención de artefactos de reproducción de sesiones está obsoleta; esta habilidad no los recupera. Utiliza el flujo de capturas de pantalla en
screenshots/y los volcados de DOM endom/.
Para consultar la referencia completa, véase REFERENCE.md. Para ver ejemplos de ejecuciones de depuración, véase EXAMPLES.md.
---
name: browser-trace
description: Capture a full DevTools-protocol trace of any browser automation, bisect the stream into per-page searchable buckets, and attach a trace to an in-progress session for debugging.
license: MIT
---
# Browser Trace
Attach a **second, read-only CDP client** to a browser session that is already being driven by your main automation. The trace records the full DevTools firehose to NDJSON, polls for screenshots and DOM dumps in parallel, and slices everything into a directory tree that bash tools can search.
This skill does **not** drive pages — it only listens. Pair it with the `browser` skill, `browse`, Stagehand, Playwright, or anything else that speaks CDP.
## When to use
- The user wants to debug a browser-automation run (failing form, missing element, hung navigation, JS exception).
- The user has a running automation and wants to attach a trace mid-flight without restarting it.
- The user wants to split a CDP firehose into network / console / DOM / page buckets.
- The user wants screenshots + DOM snapshots over time, joined to CDP events by timestamp.
If the user just wants to **drive** the browser, use the `browser` skill instead.
## Setup check
```bash
node --version # require Node 18+
which browse || npm install -g browse
which jq || true # optional — used only for ad-hoc querying
```
Verify `browse cdp` exists:
```bash
browse --help | grep -q "^\s*cdp " || echo "browse cdp not available — update browse"
```
## How it works
Every Chrome DevTools target accepts **multiple concurrent CDP clients**. Your main automation is one client; this skill adds a second one that only enables observation domains (Network, Console, Runtime, Log, Page) and never sends action commands.
The tracer has three pieces:
1. **Firehose**: `browse cdp <target>` streams every CDP event as one JSON object per line to `cdp/raw.ndjson`.
2. **Sampler**: a polling loop calls `browse screenshot --cdp <target> --path <file>` and `browse get html body --cdp <target>` on an interval (default 2s). The helper passes `--cdp` when it samples so it can attach to the traced target from its own process; once a browse daemon session is attached to a CDP target, follow-up commands in that session do not need to repeat `--cdp`.
3. **Bisector**: after the run, `bisect-cdp.mjs` walks `raw.ndjson` once, slices it into per-bucket JSONL files keyed by CDP method, and additionally bisects per page using top-level `Page.frameNavigated` events as boundaries.
## Quickstart
### Local Chrome
```bash
# 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 remote
Two helpers wrap the platform-side bookkeeping: `bb-capture.mjs` creates or attaches to a session and starts the tracer; `bb-finalize.mjs` pulls platform artifacts (final session metadata, server logs, downloads) into the run dir at the end.
> Browserbase ends a session as soon as its last CDP client disconnects. **Create with `--keep-alive`, then attach automation to the session's `connectUrl` before or together with the tracer.** `bb-capture.mjs --new` handles the keep-alive session and tracer setup; your automation still needs to attach.
```bash
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
```
Attaching to a session that's *already running* (e.g. one your production worker created) — `bb-capture.mjs` accepts a session id instead of `--new`:
```bash
# 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
```
#### What you get from the Browserbase platform
`bb-capture.mjs` adds a `browserbase` block to `manifest.json` (session id, project, region, started_at, expires_at, debugger URL). `bb-finalize.mjs` writes:
- `<run>/browserbase/session.json` — final `browse cloud sessions get` snapshot (proxyBytes, status, ended_at, viewport, …)
- `<run>/browserbase/logs.json` — `browse cloud sessions logs` output. **Often empty.** The CDP firehose in `cdp/raw.ndjson` is the source of truth; this is a side channel.
- `<run>/browserbase/downloads.zip` — files the session downloaded, if any (the script discards the empty 22-byte zip you get when there are none)
Session replay artifact fetching is **deprecated** and isn't fetched. Use the screenshots + DOM dumps in `screenshots/` and `dom/` for visual ground truth.
The live `debugger_url` in the manifest opens an interactive Chrome DevTools view served by Browserbase — handy for *watching* a long-running automation while the tracer captures the firehose to disk.
## Filesystem layout
```
.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)
```
When a run was started via `bb-capture.mjs`, `manifest.json` also carries a top-level `browserbase` block: `session_id`, `project_id`, `region`, `started_at`, `expires_at`, `keep_alive`, `debugger_url`.
### Summary shape
`cdp/summary.json` is the entry point for any analysis: it has session-level totals and a `pages[]` array indexed by top-level `Page.frameNavigated`. Per-page entries are emitted in navigation order (page 0 = first concrete URL).
```json
{
"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` are wall-clock ms, derived from `manifest.started_at` plus the offset of each event's CDP monotonic timestamp. `domains[*]` only includes `errors`/`warnings` keys when non-zero.
### Drilling in with `query.mjs`
For interactive exploration, use `scripts/query.mjs <run-id> <command>` instead of remembering paths:
```bash
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
```
Behind the scenes it just reads `cdp/summary.json` and the `cdp/pages/<pid>/` tree — feel free to bypass it with raw `jq`/`rg` once you know the shape.
## Top traversal recipes
```bash
# 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 }'
```
See **REFERENCE.md** for the full jq recipe library and a method-by-method bisect map. See **EXAMPLES.md** for end-to-end debug scenarios.
## Best practices
1. **Use `bb-capture.mjs` on Browserbase**: it enforces `--keep-alive`, fetches the connectUrl, captures the debugger URL, and stamps the manifest. Doing it manually invites mistakes.
2. **Don't `--release` a session you don't own**: `bb-finalize.mjs --release` is for sessions *you* created with `--new`. When attaching to a production session via `bb-capture.mjs <session-id>`, run `bb-finalize.mjs` without `--release` so the original automation keeps running.
3. **Order matters for remote**: on Browserbase, attach the main automation client before (or together with) the tracer, and create the session with `--keep-alive`. Otherwise the session ends as soon as the tracer's WS closes.
4. **Don't poll faster than ~1s**: each sample runs browser CLI read commands and screenshots Chrome. 2s is a good default.
5. **Pick domains deliberately**: defaults (`Network Console Runtime Log Page`) cover most debugging. Add `DOM` for DOM-tree mutations (very noisy) via `O11Y_DOMAINS="$O11Y_DOMAINS DOM"`.
6. **Reuse one Browserbase session for the automation client on remote** by attaching to that session's `connectUrl` with `browse open ... --cdp "$CONNECT_URL" --session <name>`. The `--session` flag names the local browse daemon; it is not a Browserbase session attach flag.
7. **Always run `stop-capture.mjs`**, even after a crash, so background processes don't linger and the manifest gets `stopped_at`.
8. **Bisect once per run**: `bisect-cdp.mjs` is idempotent — it overwrites the per-bucket files from `raw.ndjson` each time.
## Troubleshooting
- **`browse cdp exited immediately`**: usually means the target is unreachable (wrong port) or the Browserbase session has already ended. For remote, verify with `browse cloud sessions get <id>` — if `status` is `COMPLETED`, recreate with `--keep-alive` and attach automation first.
- **Empty `raw.ndjson` even though processes are running**: confirm a CDP client is actually driving the page. The tracer only emits events that the browser generates, so an idle browser produces ~5 lines of attach/discover messages and nothing else.
- **Screenshots all look identical**: check `index.jsonl` — if `url` doesn't change, the page hasn't navigated yet. The polling loop runs independently of the main automation's pace.
- **Browserbase session ends mid-run**: it likely hit `--timeout`. Recreate with a higher timeout (`BB_SESSION_TIMEOUT=1800 node scripts/bb-capture.mjs --new ...`) or remove the timeout flag.
- **`bb-capture.mjs <id>` says "not RUNNING"**: the session you tried to attach to ended. List candidates with `browse cloud sessions list | jq '.[] | select(.status == "RUNNING")'` and try again.
- **`browserbase/logs.json` is empty `[]`**: expected — `browse cloud sessions logs` is sparse in practice. The CDP firehose in `cdp/raw.ndjson` is the source of truth.
- **Where's the session recording (rrweb)?**: session replay artifact fetching is deprecated; this skill doesn't fetch it. Use the screenshot stream in `screenshots/` and DOM dumps in `dom/`.
For full reference, see [REFERENCE.md](REFERENCE.md).
For example debug runs, see [EXAMPLES.md](EXAMPLES.md).
Todos los archivos
13 archivosInstalar browser-trace
Descarga y descomprime los archivos de habilidades en tu directorio .claude/skills/.
Descargar ZIPClona el repositorio y copia los archivos de la habilidad a tu proyecto.
git clone https://github.com/browserbase/skills/tree/main/skills/browser-trace # Copy SKILL.md to your .claude/skills/ directory
Copiar





Hogar
