browser-trace

Capturez une trace complète du protocole DevTools pour toute automatisation de navigateur — flux CDP brut, captures d'écran et dumps DOM — puis découpez ce flux en buckets consultables par page. À utiliser quand l'utilisateur veut déboguer une exécution échouée, auditer l'activité réseau/console/DOM, rattacher une trace à une session en cours, ou réinjecter des résumés structurés par page dans une boucle agent afin que sa prochaine itération tire les leçons de la précédente.

npx skills add https://github.com/browserbase/skills --skill browser-trace

Trace de navigateur

Attachez un deuxième client CDP en lecture seule à une session de navigateur déjà contrôlée par votre automation principale. La trace enregistre le flux complet DevTools en NDJSON, récupère les screenshots et les dumps DOM en parallèle, et découpe tout en une arborescence de répertoires que les outils bash peuvent fouiller.

Cette skill ne contrôle pas les pages — elle n'écoute que. Associez-la à la skill browser, bb, Stagehand, Playwright ou toute autre plateforme qui parle CDP.

Quand l'utiliser

  • L'utilisateur veut déboguer une exécution d'automation de navigateur (formulaire défaillant, élément manquant, navigation bloquée, exception JS).
  • L'utilisateur a une automation en cours et veut attacher une trace en vol sans la redémarrer.
  • L'utilisateur veut découper un flux CDP en seaux network / console / DOM / page.
  • L'utilisateur veut des screenshots + snapshots DOM dans le temps, joints aux événements CDP par timestamp.

Si l'utilisateur veut juste contrôler le navigateur, utilisez plutôt la skill browser.

Vérification de la configuration

node --version                                  # require Node 18+
which browse || npm install -g @browserbasehq/browse-cli@alpha
which bb     || npm install -g @browserbasehq/cli   # only needed for Browserbase remote
which jq     || true                                # optional — used only for ad-hoc querying

Vérifiez que browse cdp existe (il est inclus dans 0.5.0-alpha-a4ca430+) :

browse --help | grep -q "^\s*cdp " || echo "browse cdp not in this version — install @alpha"

Fonctionnement

Chaque cible Chrome DevTools accepte plusieurs clients CDP concurrents. Votre automation principale en est un ; cette skill en ajoute un deuxième qui ne permet que les domaines d'observation (Network, Console, Runtime, Log, Page) et n'envoie jamais de commandes d'action.

Le traceur a trois composants :

  1. Firehose : browse cdp <target> diffuse chaque événement CDP sous forme d'un objet JSON par ligne vers cdp/raw.ndjson.
  2. Sampler : une boucle de polling appelle browse --ws <target> screenshot et browse --ws <target> get html body à intervalle régulier (par défaut 2s). --ws est ponctuel et contourne le daemon, ne rentre donc pas en conflit avec l'automation principale.
  3. Bisector : après l'exécution, bisect-cdp.mjs parcourt raw.ndjson une fois, le découpe en fichiers JSONL par seau avec clés CDP method, et découpe aussi par page en utilisant les événements top-level Page.frameNavigated comme délimiteurs.

Démarrage rapide

Chrome local

# 1. Lancez Chrome avec un port debugger (tout user-data-dir le garde isolé).
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
  --remote-debugging-port=9222 \
  --user-data-dir=/tmp/chrome-o11y \
  about:blank &

# 2. Démarrez le traceur.
node scripts/start-capture.mjs 9222 my-run

# 3. Exécutez votre automation principale contre le port 9222.
browse env local 9222
browse open https://example.com
# ...whatever the run does...

# 4. Arrêtez et découpez.
node scripts/stop-capture.mjs my-run
node scripts/bisect-cdp.mjs my-run

Browserbase distant

Deux helpers enveloppent la gestion de plateforme : bb-capture.mjs crée ou s'attache à une session et démarre le traceur ; bb-finalize.mjs récupère les artefacts de plateforme (métadonnées finales de session, logs serveur, téléchargements) dans le répertoire d'exécution.

Browserbase termine une session dès que son dernier client CDP se déconnecte. Créez toujours avec --keep-alive et attachez un client automation avant (ou en même temps que) le traceur. bb-capture.mjs --new le fait pour vous.

export BROWSERBASE_API_KEY=...

# 1. Créez une session keep-alive ET démarrez le traceur en une étape.
#    Affiche l'id de session, le préfixe connectUrl, et une URL de debugger en direct que vous
#    pouvez ouvrir dans un navigateur pour regarder l'exécution interactivement.
node scripts/bb-capture.mjs --new my-run

# 2. Lancez l'automation. bb-capture a tamponné l'id de session dans le manifest.
SID=$(jq -r .browserbase.session_id .o11y/my-run/manifest.json)
browse --connect "$SID" open https://example.com
browse --connect "$SID" open https://news.ycombinator.com

# 3. Arrêtez le traceur, découpez, puis récupérez les artefacts de plateforme et libérez.
node scripts/stop-capture.mjs my-run
node scripts/bisect-cdp.mjs my-run
node scripts/bb-finalize.mjs my-run --release

S'attacher à une session déjà en cours (par ex. une créée par votre worker de production) — bb-capture.mjs accepte un id de session à la place de --new :

# Sélectionnez une session en cours (filtrez côté client ; bb sessions list n'a pas de flag --status)
bb sessions list | jq -r '.[] | select(.status == "RUNNING") | .id'

node scripts/bb-capture.mjs <session-id> mid-flight-debug
# ...traceur s'exécute aux côtés du client automation existant ; pas de 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 de la plateforme Browserbase

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

  • <run>/browserbase/session.json — snapshot final de bb sessions get (proxyBytes, status, ended_at, viewport, …)
  • <run>/browserbase/logs.json — sortie bb sessions logs. Souvent vide. Le flux CDP dans cdp/raw.ndjson est la source de vérité ; ceci est un canal secondaire.
  • <run>/browserbase/downloads.zip — fichiers téléchargés par la session, le cas échéant (le script descarte le zip vide de 22 octets que vous obtenez quand il n'y en a pas)

bb sessions recording (rejeu de session rrweb) est déprécié et n'est pas récupéré. Utilisez les screenshots + dumps DOM dans screenshots/ et dom/ comme source de vérité visuelle.

L'debugger_url en direct dans le manifest ouvre une vue Chrome DevTools interactive servie par Browserbase — pratique pour regarder une automation longue durée pendant que le traceur capture le flux vers le disque.

Arborescence du système de fichiers

.o11y/<run-id>/
  manifest.json                 métadonnées d'exécution : target, domains, started_at, stopped_at
  index.jsonl                   une ligne par sample : {ts, screenshot, dom, url}
  cdp/
    raw.ndjson                  flux CDP complet (un objet JSON par ligne)
    summary.json                {sessionId, duration, totalEvents, pages[]} — voir forme ci-dessous
    network/{requests,responses,finished,failed,websocket}.jsonl   seaux au niveau session (toujours écrits)
    console/{logs,exceptions}.jsonl
    runtime/all.jsonl
    log/entries.jsonl
    page/{navigations,lifecycle,frames,dialogs,all}.jsonl
    dom/all.jsonl                                                  (seulement si O11Y_DOMAINS inclut DOM)
    target/{attached,detached}.jsonl
    pages/                      tranches par page, indexées par délimiteurs frameNavigated top-level
      000/                      première page concrète
        url.txt                 l'URL de cette page
        summary.json            bloc domains/network/timing de cette page (même forme qu'une entry pages[])
        raw.jsonl               flux scoped à cette page
        network/, console/, page/, runtime/, log/, target/, dom/    mêmes seaux, seulement fichiers non-vides
  screenshots/<iso-ts>.png      un PNG par intervalle de sample
  dom/<iso-ts>.html             un dump HTML par intervalle de sample
  browserbase/                  ajouté par bb-finalize.mjs (exécutions Browserbase seulement)
    session.json                snapshot final de `bb sessions get` (proxyBytes, status, ended_at, …)
    logs.json                   sortie `bb sessions logs` (souvent [])
    downloads.zip               sortie `bb sessions downloads get` (seulement si la session a téléchargé des fichiers)

Quand une exécution a été démarrée via bb-capture.mjs, manifest.json porte aussi un bloc browserbase top-level : session_id, project_id, region, started_at, expires_at, keep_alive, debugger_url.

Forme du summary

cdp/summary.json est le point d'entrée pour toute analyse : il contient les totaux au niveau session et un tableau pages[] indexé par Page.frameNavigated top-level. 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 des ms wall-clock, dérivés de manifest.started_at plus l'offset du timestamp CDP monotone de chaque événement. domains[*] inclut seulement les clés errors/warnings quand elles sont non-zéro.

Exploration interactive avec query.mjs

Pour l'exploration interactive, utilisez scripts/query.mjs <run-id> <command> au lieu de mémoriser les chemins :

node scripts/query.mjs my-run list                    # table one-line de pages
node scripts/query.mjs my-run page 1                  # summary complet pour page 1
node scripts/query.mjs my-run page 1 network/failed   # cat failed.jsonl pour page 1
node scripts/query.mjs my-run errors                  # toutes les erreurs entre pages, attribuées par pid
node scripts/query.mjs my-run errors 2                # erreurs de page 2 seulement
node scripts/query.mjs my-run hosts                   # top hosts par nombre de requêtes
node scripts/query.mjs my-run host api.example.com    # toutes les requests/responses pour un host
node scripts/query.mjs my-run summary                 # summary.json complet

Derrière les coulisses, il lit juste cdp/summary.json et l'arbre cdp/pages/<pid>/ — n'hésitez pas à le contourner avec du jq/rg brut une fois que vous connaissez la forme.

Recettes de traversal top

# Toutes les requêtes réseau échouées (utilisez jq -c pour garder le délimiteur de ligne)
jq -c '.params' .o11y/<run>/cdp/network/failed.jsonl

# Trouvez les requêtes vers un host spécifique
jq -c 'select(.params.request.url | test("api\\.example\\.com"))' \
  .o11y/<run>/cdp/network/requests.jsonl

# Réponses 4xx/5xx
jq -c 'select(.params.response.status >= 400)
       | {status: .params.response.status, url: .params.response.url}' \
  .o11y/<run>/cdp/network/responses.jsonl

# Erreurs console seulement
jq -c 'select(.params.type == "error")' .o11y/<run>/cdp/console/logs.jsonl

# Séquence d'URLs visitées
jq -r '.params.frame.url' .o11y/<run>/cdp/page/navigations.jsonl

# Trouvez le screenshot pris le plus proche d'un timestamp (par ex., quand une exception s'est déclenchée)
ls .o11y/<run>/screenshots/ | sort | awk -v t=20260427T1714123NZ '
  $0 >= t { print; exit }'

Voir REFERENCE.md pour la librairie de recettes jq complète et une carte bisect méthode par méthode. Voir EXAMPLES.md pour des scénarios de debug de bout en bout.

Bonnes pratiques

  1. Utilisez bb-capture.mjs sur Browserbase : il impose --keep-alive, récupère la connectUrl, capture l'URL de debugger, et tamponne le manifest. Le faire manuellement invite aux erreurs.
  2. Ne --release pas une session que vous ne possédez pas : bb-finalize.mjs --release est pour les sessions que vous avez créées avec --new. Quand vous vous attachez à une session de production via bb-capture.mjs <session-id>, lancez bb-finalize.mjs sans --release pour que l'automation originale continue.
  3. L'ordre compte pour remote : sur Browserbase, attachez le client automation principal avant (ou en même temps que) le traceur, et créez la session avec --keep-alive. Sinon la session se termine dès que le WS du traceur ferme.
  4. Ne pollez pas plus vite qu'~1s : chaque sample ouvre une connexion CDP ponctuelle et prend un screenshot de Chrome. 2s est un bon défaut.
  5. Choisissez les domaines délibérément : les défauts (Network Console Runtime Log Page) couvrent la plupart des debogage. Ajoutez DOM pour les mutations d'arbre DOM (très bruyant) via O11Y_DOMAINS="$O11Y_DOMAINS DOM".
  6. Utilisez --connect <session-id> pour le client automation sur remote, pas un nouveau browse env remote (ce qui créerait une nouvelle session à chaque fois).
  7. Lancez toujours stop-capture.mjs, même après un crash, pour que les processus de fond ne persistent pas et que le manifest reçoive stopped_at.
  8. Découpez une fois par exécution : bisect-cdp.mjs est idempotent — il réécrit les fichiers par-seau depuis raw.ndjson à chaque fois.

Dépannage

  • browse cdp exited immediately : signifie généralement que la cible est inaccessible (mauvais port) ou que la session Browserbase a déjà terminé. Pour remote, vérifiez avec bb sessions get <id> — si status est COMPLETED, recréez avec --keep-alive et attachez d'abord l'automation.
  • raw.ndjson vide bien que les processus s'exécutent : confirmez qu'un client CDP conduit réellement la page. Le traceur n'émet que les événements que le navigateur génère, donc un navigateur inactif produit ~5 lignes de messages attach/discover et rien d'autre.
  • Les screenshots se ressemblent tous : vérifiez index.jsonl — si url ne change pas, la page ne s'est pas encore navigée. La boucle de polling s'exécute indépendamment du rythme de l'automation principale.
  • Browserbase session se termine mid-run : elle a probablement atteint --timeout. Recréez avec un timeout plus élevé (BB_SESSION_TIMEOUT=1800 node scripts/bb-capture.mjs --new ...) ou supprimez le flag de timeout.
  • bb-capture.mjs <id> dit "not RUNNING" : la session à laquelle vous avez essayé de vous attacher a terminé. Listez les candidats avec bb sessions list | jq '.[] | select(.status == "RUNNING")' et réessayez.
  • browserbase/logs.json est un [] vide : attendu — bb sessions logs est sparse en pratique. Le flux CDP dans cdp/raw.ndjson est la source de vérité.
  • Où est l'enregistrement de session (rrweb)? : bb sessions recording est déprécié ; cette skill ne le récupère pas. Utilisez le flux de screenshots dans screenshots/ et les dumps DOM dans dom/.

Pour une référence complète, voir REFERENCE.md. Pour des exécutions de debug example, voir EXAMPLES.md.

Skills similaires