option
MaisonMaison Skill DevOps et CI/CD browser-trace

browser-trace

browserbase/skills browserbase/skills

Enregistrez une trace complète du protocole DevTools pour toute automatisation de navigateur, divisez le flux en segments consultables par page, puis associez une trace à une session en cours à des fins de débogage.

...Développer tout
0
Heure mise à jour 30 septembre 2026

Trace du navigateur

Associez un deuxième client CDP en lecture seule à une session de navigateur déjà pilotée par votre automatisation principale. La trace enregistre l’intégralité du flux DevTools au format NDJSON, interroge en parallèle les captures d’écran et les dumps DOM, puis découpe le tout en une arborescence de répertoires que les outils bash peuvent parcourir.

Cette compétence ne pilote pas les pages — elle se contente d'écouter. Associez-la à la browser compétence browse, Stagehand, Playwright ou tout autre outil compatible avec CDP.

Quand l’utiliser

  • L’utilisateur souhaite déboguer une exécution d’automatisation de navigateur (formulaire qui échoue, élément manquant, navigation bloquée, exception JS).
  • L’utilisateur dispose d’une automatisation en cours d’exécution et souhaite y ajouter une trace en cours d’exécution sans la redémarrer.
  • L’utilisateur souhaite diviser un flux CDP en compartiments réseau / console / DOM / page.
  • L'utilisateur souhaite obtenir des captures d'écran et des instantanés DOM au fil du temps, associés aux événements CDP par horodatage.

Si l’utilisateur souhaite simplement piloter le navigateur, il doit plutôt utiliser la browser compétence à la place.

Vérification de la configuration

node --version                                  # require Node 18+
which browse || npm install -g browse
which jq     || true                                # optional — used only for ad-hoc querying

Vérifiez que browse cdp existe :

browse --help | grep -q "^\s*cdp " || echo "browse cdp not available — update browse"

Fonctionnement

Chaque cible Chrome DevTools accepte plusieurs clients CDP simultanés. Votre automatisation principale correspond à un client ; cette compétence en ajoute un deuxième qui active uniquement les domaines d’observation (Réseau, Console, Exécution, Journal, Page) et n’envoie jamais de commandes d’action.

Le traceur comporte trois éléments :

  1. Firehose : browse cdp diffuse chaque événement CDP sous la forme d’un objet JSON par ligne vers cdp/raw.ndjson.
  2. Échantillonneur : une boucle d’interrogation appelle browse screenshot --cdp --path et browse get html body --cdp à un intervalle donné (2 s par défaut). L’assistant transmet --cdp le moment de l’échantillonnage afin de pouvoir se connecter à la cible tracée depuis son propre processus ; une fois qu’une session du démon de navigation est connectée à une cible CDP, les commandes suivantes de cette session n’ont pas besoin de répéter --cdp.
  3. Bisector : après l’exécution, bisect-cdp.mjs parcourt raw.ndjson une seule fois, le découpe en fichiers JSONL par compartiment, indexés par méthode CDP, et procède en outre à une bisection par page en utilisant les Page.frameNavigated comme limites.

Guide de démarrage rapide

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 à distance

Deux fonctions d’aide gèrent la gestion côté plateforme : bb-capture.mjs crée ou se connecte à une session et lance le traceur ; bb-finalize.mjs récupère les artefacts de la plateforme (métadonnées finales de la session, journaux du serveur, téléchargements) dans le répertoire d'exécution à la fin.

Browserbase met fin à une session dès que son dernier client CDP se déconnecte. Créez-la avec --keep-alive, puis associez l’automatisation à l’connectUrl de la session avant ou en même temps que le traceur. bb-capture.mjs --new Il gère la session « keep-alive » et la configuration du traceur ; votre automatisation doit tout de même y être associée.

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

Associer une automatisation à une session déjà en cours d’exécution (par exemple, celle créée par votre travailleur de production) — bb-capture.mjs accepte un identifiant de session à la place 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

Ce que vous obtenez grâce à la plateforme Browserbase

bb-capture.mjs ajoute un browserbase bloc à manifest.json (identifiant de session, projet, région, started_at, expires_at, URL du débogueur). bb-finalize.mjs écrit :

  • /browserbase/session.json — browse cloud sessions get instantané (proxyBytes, statut, ended_at, viewport, …)
  • /browserbase/logs.json — browse cloud sessions logs sortie. Souvent vide. Le flux de données CDP dans cdp/raw.ndjson est la source de référence ; il s’agit ici d’un canal secondaire.
  • /browserbase/downloads.zip — fichiers téléchargés par la session, le cas échéant (le script ignore le fichier zip vide de 22 octets que vous obtenez lorsqu’il n’y en a pas)

La récupération des artefacts de relecture de session est obsolète et n’est pas effectuée. Utilisez les captures d’écran + les dumps DOM dans screenshots/ et dom/ pour une vérification visuelle.

Le debugger_url dans le manifeste ouvre une vue interactive de Chrome DevTools hébergée par Browserbase — très pratique pour surveiller une automatisation de longue durée pendant que le traceur enregistre le flux de données sur le disque.

Structure du système de fichiers

.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)

Lorsqu’une exécution a été lancée via bb-capture.mjs, manifest.json comporte également un bloc de niveau supérieur browserbase : session_id, project_id, region, started_at, expires_at, keep_alive, debugger_url.

La forme « Summary »

cdp/summary.json constitue le point d’entrée de toute analyse : elle contient les totaux au niveau de la session et un pages[] tableau indexé par le niveau supérieur Page.frameNavigated. Les entrées par page sont émises dans l’ordre de navigation (page 0 = première URL concrète).

{
  "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 sont exprimées en millisecondes « temps réel », dérivées de manifest.started_at auxquelles s'ajoute le décalage de l'horodatage monotone CDP de chaque événement. domains[*] ne contient des errors/warnings les clés lorsqu’elles sont différentes de zéro.

Exploration approfondie avec query.mjs

Pour une exploration interactive, utilisez scripts/query.mjs plutôt que de mémoriser les chemins d’accès :

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 coulisses, cela se résume simplement à lire cdp/summary.json et l’ cdp/pages// arbre — n’hésitez pas à le contourner en utilisant le format brut jq/rg une fois que vous en connaissez la structure.

Principales recettes de traversée

# 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 }'

Consultez REFERENCE.md pour découvrir la bibliothèque complète de recettes jq et une carte de bisection méthode par méthode. Consultez EXAMPLES.md pour des scénarios de débogage de bout en bout.

Bonnes pratiques

  1. Utilisez « bb-capture.mjs » sur Browserbase : cela garantit --keep-alive, récupère l’URL de connexion, capture l’URL du débogueur et horodate le manifeste. Le faire manuellement est source d’erreurs.
  2. N’utilisez pas `--release` sur une session qui ne vous appartient pas : bb-finalize.mjs --release cette méthode est destinée aux sessions que vous avez créées avec --new. Lorsque vous vous connectez à une session de production via bb-capture.mjs , exécutez bb-finalize.mjs sans --release afin que l’automatisation d’origine continue de s’exécuter.
  3. L'ordre est important pour l'accès à distance : sur Browserbase, connectez le client d'automatisation principal avant (ou en même temps que) le traceur, puis créez la session avec --keep-alive. Sinon, la session se termine dès que le WS du traceur se ferme.
  4. Ne lancez pas de requêtes à une fréquence supérieure à environ 1 s : chaque échantillon exécute des commandes de lecture de la CLI du navigateur et réalise des captures d’écran de Chrome. 2 s est une bonne valeur par défaut.
  5. Choisissez les domaines avec soin : les valeurs par défaut (Network Console Runtime Log Page) couvrent la plupart des cas de débogage. Ajoutez DOM pour les mutations de l’arborescence DOM (très bruyantes) via O11Y_DOMAINS="$O11Y_DOMAINS DOM".
  6. Réutilisez une session Browserbase pour le client d’automatisation à distance en vous connectant à la connectUrl avec browse open ... --cdp "$CONNECT_URL" --session . Le --session indicateur désigne le démon de navigation local ; il ne s’agit pas d’un indicateur de connexion à une session Browserbase.
  7. Toujours exécuter « stop-capture.mjs », même après un plantage, afin que les processus en arrière-plan ne persistent pas et que le manifeste soit stopped_at.
  8. Effectuez une bisection une fois par exécution : bisect-cdp.mjs est idempotente — elle écrase les fichiers propres à chaque compartiment à raw.ndjson à chaque exécution.

Dépannage

  • browse cdp exited immediately : cela signifie généralement que la cible est inaccessible (port incorrect) ou que la session Browserbase est déjà terminée. Pour les exécutions à distance, vérifiez avec browse cloud sessions get — si status est COMPLETED, recréez-la avec --keep-alive et connectez d’abord l’automatisation.
  • raw.ndjson vide alors que les processus sont en cours d’exécution : vérifiez qu’un client CDP pilote bien la page. Le traceur n’émet que les événements générés par le navigateur ; ainsi, un navigateur inactif produit environ 5 lignes de messages « attach/discover » et rien d’autre.
  • Les captures d’écran semblent toutes identiques : vérifiez index.jsonl si url ne change pas, la page n’a pas encore été parcourue. La boucle d’interrogation s’exécute indépendamment du rythme de l’automatisation principale.
  • La session Browserbase se termine en cours d’exécution : elle a probablement atteint la limite de --timeout. Recréez-la avec un délai d’expiration plus long (BB_SESSION_TIMEOUT=1800 node scripts/bb-capture.mjs --new ...) ou supprimez le drapeau de délai d'expiration.
  • bb-capture.mjs indique « not RUNNING » : la session à laquelle vous avez tenté de vous connecter s’est terminée. Répertoriez les sessions candidates avec browse cloud sessions list | jq '.[] | select(.status == "RUNNING")' et réessayez.
  • browserbase/logs.json est vide [] : c’est normal — browse cloud sessions logs est clairsemé dans la pratique. Le flux CDP dans cdp/raw.ndjson est la source de référence.
  • Où se trouve l’enregistrement de la session (rrweb) ? : la récupération des artefacts de relecture de session est obsolète ; cette compétence ne les récupère pas. Utilisez le flux de captures d’écran dans screenshots/ et les dumps DOM dans dom/.

Pour une référence complète, consultez REFERENCE.md. Pour des exemples d'exécution de débogage, consultez EXAMPLES.md.

Voir sur GitHub
---
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).

Installer browser-trace

Téléchargez et décompressez les fichiers de compétences dans votre répertoire .claude/skills/.

Télécharger le ZIP

Clonez le dépôt et copiez les fichiers de compétence dans votre projet.

git clone https://github.com/browserbase/skills/tree/main/skills/browser-trace # Copy SKILL.md to your .claude/skills/ directory

Copier Copier
Configuration rapide: Copiez le dossier de la compétence dans .claude/skills/ Claude détectera automatiquement la compétence et l'utilisera

Compétences similaires

klingai-upgrade-migration
Heure mise à jour 3 juillet 2026
Verification &amp; Quality Assurance
Heure mise à jour 29 juin 2026
base44-cli
Heure mise à jour 29 juin 2026
Railway CLI Management
Heure mise à jour 2 juillet 2026
OR