browser-to-api
browserbase/skills
Générer une spécification OpenAPI 3.1 à partir d'une trace de navigation, en analysant le trafic HTTP observé, en créant des modèles d'URL et en déduisant des schémas JSON à partir d'échantillons de requêtes et de réponses.
...Développer toutDu navigateur à l'API
Découverte d'API basée sur la relecture. Analyse une trace de navigateur, associe ses événements de requête/réponse CDP, génère des modèles à partir des URL observées, déduit des schémas JSON à partir d'échantillons, puis génère un document OpenAPI 3.1 ainsi qu'un rapport de couverture lisible par l'utilisateur.
Cette compétence ne capture pas le trafic. Il s’agit d’un post-traitement purement hors ligne s’appuyant sur les compartiments cdp/network/*.jsonl de la trace de navigateur. Les deux compétences s’assemblent ainsi :
browser-trace → .o11y//cdp/network/{requests,responses}.jsonl
browser-to-api → .o11y//api-spec/index.html + openapi.yaml + client.mjs
Quand l'utiliser
- L'utilisateur souhaite obtenir un document OpenAPI pour l'API d'un site web tiers ou non documentée.
- L’utilisateur dispose d’une
trace de navigateuret souhaite en extraire les points de terminaison et les schémas. - L'utilisateur développe un client ou un SDK pour un site qui ne publie pas de spécification.
- L’utilisateur souhaite un rapport de couverture indiquant quels flux permettraient d’élargir la spécification.
Si l’utilisateur souhaite capturer le trafic, dirigez-le d’abord vers Browser-Trace.
Workflow en deux étapes
1. Capture avec browser-trace (et, éventuellement, les corps de requêtes via l'option « browse network on »)
# Exemple local sur une cible Chrome existante pouvant être déboguée
TARGET=9222
node ../browser-trace/scripts/start-capture.mjs "$TARGET" my-site
browse open about:blank --cdp "$TARGET"
browse network on # capturer les corps des requêtes/réponses
browse open https://example.com
# ...générez les flux que vous souhaitez couvrir...
# Effectuez un instantané du répertoire des corps AVANT de désactiver la capture (le répertoire temporaire est partagé
# par session ; par conséquent, les exécutions suivantes de `browse network on` mélangeraient vos corps
# avec tout ce qu’une future capture écrirait si vous sautiez cette étape).
cp -r "$(browse network path | jq -r .path)" .o11y/my-site/cdp/network/bodies/
browse network off
node ../browser-trace/scripts/stop-capture.mjs my-site
node ../browser-trace/scripts/bisect-cdp.mjs my-site
browse network on est facultatif mais fortement recommandé — sans cela, la spécification ne dispose d’aucun schéma de corps de réponse (le flux CDP utilisé par browse cdp n’intègre pas de corps). Avec cette option, les corps de requête (déjà capturés par CDP) et les corps de réponse sont joints à la trace via l’identifiant de requête CDP (requestId).
2. Générer la spécification
node scripts/discover.mjs --run .o11y/my-site
# → .o11y/my-site/api-spec/index.html ← ouvrez ce fichier
# .o11y/my-site/api-spec/client.mjs
# .o11y/my-site/api-spec/openapi.yaml
# .o11y/my-site/api-spec/openapi.json
# .o11y/my-site/api-spec/report.md
# .o11y/my-site/api-spec/confidence.json
# .o11y/my-site/api-spec/samples/*.json
# .o11y/my-site/api-spec/intermediate/*.jsonl
discover.mjs détecte automatiquement Pour utiliser une capture de corps provenant d’ailleurs (par exemple, si vous n’avez pas effectué de snapshot et que vous souhaitez utiliser le répertoire réseau en temps réel), passez explicitement l’option --bodies
3. Ouvrez le rapport HTML
Une fois l'exécution de discover.mjs terminée, ouvrez systématiquement le rapport HTML généré:
open .o11y/my-site/api-spec/index.html
Le rapport est un fichier HTML autonome (aucun serveur n’est nécessaire) qui présente chaque opération détectée sous la forme d’une fiche développable contenant les variables, l’utilisation côté client, des exemples de requêtes et de réponses, ainsi qu’un extrait de code client.mjs généré en bas de page. Il s’agit du livrable principal — veillez à toujours l’ouvrir pour l’utilisateur.
Options de la CLI
| Option | Obligatoire | Signification |
|---|---|---|
--run |
oui | Chemin d'accès au répertoire d'exécution de la trace du navigateur |
--out |
non | Répertoire de sortie ; par défaut |
--bodies |
non | parcourir le répertoire de captureréseau à intégrer à la trace (détecté automatiquement à partir de s’il existe) |
--include |
non | N'inclure que les URL correspondant à l'expression régulière (répétable) |
--exclude |
non | Exclure les URL correspondant à l'expression régulière (répétable ; en plus des valeurs par défaut) |
--origins |
non | Liste blanche des origines séparées par des virgules (par ex. api.example.com,example.com) |
--format |
non | Format de sortie. Par défaut : les deux |
--title |
non | Info OpenAPI « title ». Par défaut, dérivé de la source principale |
--redact |
non | Noms d’en-têtes supplémentaires / clés JSON à masquer (séparés par des virgules) |
--min-samples |
non | Nombre minimum d'échantillons à inclure par point de terminaison. Valeur par défaut : 1 |
--stage |
non | Exécuter une seule étape : chargement, filtrage, normalisation, inférence, émission |
Structure de sortie
/api-spec/
├── index.html rapport visuel — ouvrez ce fichier (autonome, sans serveur)
├── client.mjs client fetch « zero-dep » avec des fonctions typées par opération
├── openapi.yaml spécification lisible par machine
├── openapi.json copie miroir
├── report.md résumé au format Markdown + exemples curl
├── confidence.json confiance par point de terminaison + indicateurs de normalisation
├── samples/ exemples de requêtes/réponses anonymisées
│ └── __.json
└── intermediate/ sous-produits du pipeline (paires/filtrages/points de terminaison au format jsonl)
Ce que vous obtenez avec « browse cdp » et « browse network »
Deux sources de capture complémentaires :
| Source | Fournit | Limitation |
|---|---|---|
browse cdp (utilisé par browser-trace) |
méthode derequête/URL/en-têtes/données POST, statut de réponse/en-têtes/type MIME, chronologie complète des événements |
N'intègre pas le corps des réponses. Les corps doivent être récupérés avec Network.getResponseBody, ce que le firehose ne fait pas. |
Parcourir le réseau (commande distincte) |
corps de requête ET corps de réponse sur le disque, indexés par l’identifiant de requête CDP ( requestId) |
Le répertoire de capture est partagé par session de « browse »; un instantané pris avant l’exécution d’un autre « browse network on » l’écrase. |
discover.mjs extraira les corps d’une répertoire « browse network » si vous passez l’option --bodies (ou stockez-les sous , qui est détecté automatiquement). La mise en correspondance s’effectue par requestId — « browse network » l’écrit dans chaque fichier request.json en tant qu’id, et nous effectuons la jointure directement.
Ce qui change lorsque des corps de requête sont présents :
- ✅ Modèles de chemins d’accès, schémas des paramètres de requête, codes d’état, types de contenu — identiques dans les deux cas.
- ✅ Schémas du corps de requête —
les données postDataprovenant du CDP suffisent ; le répertoire des corps est un plus pour les casne pas utilisant postData. - ✅ Schémas du corps de réponse — entièrement déduits à partir d’échantillons réels. En l’absence de corps, vous obtenez des squelettes
de type { description, content:.}
Le rapport signale chaque point de terminaison ne disposant d’aucun échantillon de corps de réponse.
Filtrage automatique du bruit
L’étape de normalisation classe et élimine automatiquement le bruit lié à l’infrastructure :
- Suivi / analyse — chemins contenant
/track,/pixel,/beacon,/impression,/pageview,/dag/v* - Défense contre les bots — Akamai (
/akam/), charges utiles d’empreintes numériques (sensor_data), chemins multisegments obscurcis - Gestion des sessions —
/session,/authenticate/start, consentement aux cookies, points de terminaison d’expériences A/B - Rendu des pages HTML — requêtes
GETrenvoyantdu contenu text/html(la page rendue, et non l'API)
Cela élimine généralement 60 à 80 % du trafic capturé. L’option --include permet de corriger un faux positif.
Décomposition des points de terminaison GraphQL / multiplexés
Lorsqu’un point de terminaison unique (tel que /dapi/fe/gql) est appelé avec différentes valeurs d’operationName, la skill le divise automatiquement en opérations logiques distinctes. Chacune dispose alors de :
- Entrée de chemin OpenAPI (par ex.
/dapi/fe/gql [Autocomplete]) - schéma de requête/réponse déduit uniquement à partir des échantillons de cette opération
- Exemple Curl et tableau des variables dans le rapport
La détection s’applique aux champs du corps de la requête (operationName, method, action) et aux paramètres de requête (opname, op). Cela couvre GraphQL (APQ et inline), JSON-RPC et les modèles de répartition similaires.
Limites
- La couverture est limitée au flux capturé. Les points de terminaison non exploités dans la trace n’apparaîtront pas. La compétence ne peut garantir l’exhaustivité.
- Les schémas sont inductifs, et non contractuels. Un champ peut être facultatif sur le serveur même si tous les échantillons le contiennent.
- L’authentification est observée, non spécifiée. La compétence enregistre les en-têtes de type authentification dans une extension
x-observed-auth, mais ne revendique pas de schéma de sécurité. - La création de modèles de chemins est heuristique. Les motifs numériques, UUID, hexadécimaux et slug sont détectés par segment. Les URL ambiguës sont signalées dans
le fichier confidence.json. - La masquage des données sensibles est effectué au mieux. Les masquages par défaut couvrent les identifiants courants, mais des secrets spécifiques à une application peuvent passer entre les mailles du filet ; utilisez
l’option --redactpour les en-têtes ou clés personnalisés connus.
Bonnes pratiques
- Orientez les flux que vous souhaitez documenter. Plus la trace du navigateur est riche, plus la spécification est complète.
- Utilisez
l’option --originspour les sites générant beaucoup de bruit. Une page marketing interroge des dizaines d’hôtes d’analyse ; limitez-vous à l’origine API qui vous intéresse. - Consultez d’abord
le fichier report.md. Il contient des exemples prêts à être exécutés avec curl et des échantillons de réponses pour chaque opération détectée. - Augmentez la valeur de
`--min-samples`à 2+ si vous ne souhaitez inclure dans le document final que les points de terminaison dont la structure est certaine — éliminez la longue traîne. - Associez cette commande à l’option «
browse network on »lorsque les schémas du corps de réponse sont importants. Le flux CDP (CDP firehose) à lui seul contient les corps de requêtes, mais pas ceux des réponses.
Pour le fonctionnement interne du pipeline et la référence sur le format de fichier, consultez le fichier REFERENCE.md.
---
name: browser-to-api
description: Generate an OpenAPI 3.1 specification from a browser-trace capture by analyzing observed HTTP traffic, templating URLs, and inferring JSON schemas from request/response samples.
license: MIT
---
# Browser to API
Replay-driven API discovery. Consume a `browser-trace` capture, pair its CDP request / response events, templatize observed URLs, infer JSON schemas from samples, and emit an **OpenAPI 3.1** document plus a human-readable coverage report.
This skill **does not capture traffic**. It is purely offline post-processing on top of `browser-trace`'s `cdp/network/*.jsonl` buckets. The two skills compose:
```
browser-trace → .o11y/<run>/cdp/network/{requests,responses}.jsonl
browser-to-api → .o11y/<run>/api-spec/index.html + openapi.yaml + client.mjs
```
## When to use
- The user wants an OpenAPI document for a third-party or undocumented website API.
- The user has a `browser-trace` run and wants endpoints + schemas extracted from it.
- The user is building a client/SDK against a site that doesn't publish a spec.
- The user wants a coverage report showing which flows would broaden the spec.
If the user wants to **capture** traffic, send them to `browser-trace` first.
## Two-step workflow
### 1. Capture with `browser-trace` (and optionally bodies via `browse network on`)
```bash
# Local example against an existing debuggable Chrome target
TARGET=9222
node ../browser-trace/scripts/start-capture.mjs "$TARGET" my-site
browse open about:blank --cdp "$TARGET"
browse network on # capture request/response bodies
browse open https://example.com
# ...drive whatever flows you want covered...
# Snapshot the bodies dir BEFORE turning capture off (the temp dir is shared
# per-session, so subsequent `browse network on` runs would mix your bodies
# with whatever a future capture writes if you skip this step).
cp -r "$(browse network path | jq -r .path)" .o11y/my-site/cdp/network/bodies/
browse network off
node ../browser-trace/scripts/stop-capture.mjs my-site
node ../browser-trace/scripts/bisect-cdp.mjs my-site
```
`browse network on` is **optional but strongly recommended** — without it, the spec has no response-body schemas (the CDP firehose used by `browse cdp` does not embed bodies). With it, both request bodies (already captured by CDP) *and* response bodies are joined into the trace by CDP `requestId`.
### 2. Generate the spec
```bash
node scripts/discover.mjs --run .o11y/my-site
# → .o11y/my-site/api-spec/index.html ← open this
# .o11y/my-site/api-spec/client.mjs
# .o11y/my-site/api-spec/openapi.yaml
# .o11y/my-site/api-spec/openapi.json
# .o11y/my-site/api-spec/report.md
# .o11y/my-site/api-spec/confidence.json
# .o11y/my-site/api-spec/samples/*.json
# .o11y/my-site/api-spec/intermediate/*.jsonl
```
`discover.mjs` auto-detects `<run>/cdp/network/bodies/`. To use a body capture from elsewhere (e.g. didn't snapshot, want the live `browse network` dir), pass `--bodies <path>` explicitly.
### 3. Open the HTML report
After `discover.mjs` finishes, **always open the generated HTML report**:
```bash
open .o11y/my-site/api-spec/index.html
```
The report is a self-contained HTML file (no server needed) that shows each discovered operation as an expandable card with variables, client usage, request/response examples, and a generated `client.mjs` snippet at the bottom. This is the primary deliverable — always open it for the user.
## CLI flags
| Flag | Required | Meaning |
|---|---|---|
| `--run <path>` | yes | Path to a `browser-trace` run directory |
| `--out <path>` | no | Output dir; default `<run>/api-spec/` |
| `--bodies <path>` | no | `browse network` capture dir to join into the trace (auto-detected from `<run>/cdp/network/bodies/` when present) |
| `--include <regex>` | no | Only include URLs matching regex (repeatable) |
| `--exclude <regex>` | no | Exclude URLs matching regex (repeatable; in addition to defaults) |
| `--origins <list>` | no | Comma-separated origin allow-list (e.g. `api.example.com,example.com`) |
| `--format <yaml\|json\|both>` | no | Output format. Default `both` |
| `--title <string>` | no | OpenAPI `info.title`. Default derived from primary origin |
| `--redact <list>` | no | Extra header names / JSON keys to redact (comma-separated) |
| `--min-samples <n>` | no | Minimum samples per endpoint to include. Default `1` |
| `--stage <name>` | no | Run only one stage: `load`, `filter`, `normalize`, `infer`, `emit` |
## Output layout
```
<run>/api-spec/
├── index.html visual report — open this (self-contained, no server)
├── client.mjs zero-dep fetch client with typed functions per operation
├── openapi.yaml machine-readable spec
├── openapi.json mirror
├── report.md markdown summary + curl examples
├── confidence.json per-endpoint confidence + normalization flags
├── samples/ redacted request/response examples
│ └── <method>__<path-hash>.json
└── intermediate/ pipeline byproducts (paired/filtered/endpoints jsonl)
```
## What you get from `browse cdp` and `browse network`
Two complementary capture sources:
| Source | Provides | Limitation |
|---|---|---|
| `browse cdp` (used by `browser-trace`) | request method/URL/headers/`postData`, response status/headers/mimeType, full event timing | **Does not embed response bodies.** Bodies must be pulled with `Network.getResponseBody`, which the firehose doesn't do. |
| `browse network on` (separate command) | request bodies AND response bodies on disk, keyed by CDP `requestId` | Capture dir is shared per `browse` session; snapshot before another `browse network on` overwrites it. |
`discover.mjs` will pull bodies from a `browse network` dir if you pass `--bodies <path>` (or stash them under `<run>/cdp/network/bodies/`, which is auto-detected). The matching is by `requestId` — `browse network` writes that into each `request.json` as `id`, and we join directly.
What changes when bodies are present:
- ✅ Path templating, query-param schemas, status codes, content-types — same either way.
- ✅ Request-body schemas — `postData` from CDP is enough; bodies dir is a nice-to-have for non-`postData` cases.
- ✅ **Response-body schemas** — fully inferred from real samples. Without bodies you get `{ description, content: <mimeType> }` skeletons.
The report flags every endpoint that has no response-body sample.
## Automatic noise filtering
The normalize stage automatically classifies and drops infrastructure noise:
- **Tracking / analytics** — paths containing `/track`, `/pixel`, `/beacon`, `/impression`, `/pageview`, `/dag/v*`
- **Bot defense** — Akamai (`/akam/`), fingerprint payloads (`sensor_data`), obfuscated multi-segment paths
- **Session plumbing** — `/session`, `/authenticate/start`, cookie consent, A/B experiment endpoints
- **HTML page renders** — `GET` requests returning `text/html` (the rendered page, not the API)
This typically drops 60-80% of captured traffic. The `--include` flag can rescue a false positive.
## GraphQL / multiplexed endpoint decomposition
When a single endpoint (like `/dapi/fe/gql`) is called with different `operationName` values, the skill automatically splits it into separate logical operations. Each gets its own:
- OpenAPI path entry (e.g. `/dapi/fe/gql [Autocomplete]`)
- Request/response schema inferred from only that operation's samples
- Curl example and variables table in the report
Detection works on body fields (`operationName`, `method`, `action`) and query params (`opname`, `op`). This covers GraphQL (APQ and inline), JSON-RPC, and similar dispatch patterns.
## Limitations
- **Coverage is bounded by the captured flow.** Endpoints not exercised in the trace will not appear. The skill cannot prove completeness.
- **Schemas are inductive, not contractual.** A field might be optional on the server even if every sample contained it.
- **Auth is observed, not specified.** The skill records auth-shaped headers in an `x-observed-auth` extension but won't claim a security scheme.
- **Path templating is heuristic.** Numeric / UUID / hex / slug patterns are detected per segment. Ambiguous URLs are flagged in `confidence.json`.
- **Redaction is best-effort.** Default redactions cover common credentials, but app-specific secrets may slip through; use `--redact` for known custom headers/keys.
## Best practices
1. **Drive the flows you want documented.** The richer the browser-trace, the richer the spec.
2. **Use `--origins` for noisy sites.** A marketing page hits dozens of analytics hosts; restrict to the API origin you care about.
3. **Inspect `report.md` first.** It has curl-ready examples and response samples for every discovered operation.
4. **Bump `--min-samples` to 2+** when you want only confidently-shaped endpoints in the final doc — drop the long tail.
5. **Pair with `browse network on`** when response-body schemas matter. The CDP firehose alone has request bodies but not response bodies.
For pipeline internals and the file format reference, see [REFERENCE.md](REFERENCE.md).
Tous les fichiers
15 fichiersInstaller browser-to-api
Téléchargez et décompressez les fichiers de compétences dans votre répertoire .claude/skills/.
Télécharger le ZIPClonez 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-to-api # Copy SKILL.md to your .claude/skills/ directory
Copier





Maison
