Browser to API
Découverte d'API pilotée par replay. Consommez une capture browser-trace, appairez ses événements de requête / réponse CDP, templatisez les URLs observées, déduisez les schémas JSON à partir d'échantillons, et émettez un document OpenAPI 3.1 accompagné d'un rapport de couverture lisible par l'homme.
Cette skill ne capture pas le trafic. C'est du post-traitement purement hors ligne sur les buckets cdp/network/*.jsonl de browser-trace. Les deux skills se composent :
browser-trace → .o11y/<run>/cdp/network/{requests,responses}.jsonl
browser-to-api → .o11y/<run>/api-spec/index.html + openapi.yaml + client.mjs
Quand l'utiliser
- L'utilisateur veut un document OpenAPI pour l'API d'un site tiers ou non documenté.
- L'utilisateur a une exécution
browser-traceet veut en extraire les endpoints et schémas. - L'utilisateur construit un client/SDK contre un site qui ne publie pas de spec.
- L'utilisateur veut un rapport de couverture montrant quels flux étendraient la spec.
Si l'utilisateur veut capturer le trafic, orientez-le d'abord vers browser-trace.
Workflow en deux étapes
1. Capturer avec browser-trace (et optionnellement les corps via browse network on)
# Exemple local (voir browser-trace SKILL.md pour la variante Browserbase)
browse env local
browse open about:blank
TARGET="$(browse status --json | jq -r .wsUrl)"
node ../browser-trace/scripts/start-capture.mjs "$TARGET" my-site
browse network on # capturer les corps requête/réponse
browse open https://example.com
# ...piloter les flux que vous voulez couvrir...
# Faire un snapshot du répertoire bodies AVANT d'éteindre la capture (le répertoire
# temporaire est partagé par session, donc les exécutions `browse network on` ultérieures
# mélangeraient vos bodies avec ce qu'une future capture écrirait si vous sautez 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 optionnel mais fortement recommandé — sans lui, la spec n'a pas de schémas de corps de réponse (le firehose CDP utilisé par browse cdp n'embarque pas les corps). Avec lui, les corps de requête (déjà capturés par CDP) et les corps de réponse sont joints à la trace par requestId CDP.
2. Générer la spec
node scripts/discover.mjs --run .o11y/my-site
# → .o11y/my-site/api-spec/index.html ← ouvrez ceci
# .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 <run>/cdp/network/bodies/. Pour utiliser une capture de corps provenant d'ailleurs (par ex. snapshot non effectué, vouloir le répertoire browse network en direct), passez --bodies <path> explicitement.
3. Ouvrir le rapport HTML
Après que discover.mjs se termine, ouvrez toujours le rapport HTML généré :
open .o11y/my-site/api-spec/index.html
Le rapport est un fichier HTML autonome (aucun serveur requis) qui affiche chaque opération découverte sous forme de carte dépliable avec variables, utilisation du client, exemples requête/réponse, et un snippet client.mjs généré en bas. C'est le livrable principal — ouvrez-le toujours pour l'utilisateur.
Drapeaux CLI
| Drapeau | Requis | Signification |
|---|---|---|
--run <path> |
oui | Chemin vers un répertoire d'exécution browser-trace |
--out <path> |
non | Répertoire de sortie ; défaut <run>/api-spec/ |
--bodies <path> |
non | Répertoire de capture browse network à joindre à la trace (détecté automatiquement depuis <run>/cdp/network/bodies/ si présent) |
--include <regex> |
non | Inclure uniquement les URLs correspondant à la regex (répétable) |
--exclude <regex> |
non | Exclure les URLs correspondant à la regex (répétable ; en plus des défauts) |
--origins <list> |
non | Liste blanche d'origines séparées par des virgules (ex. api.example.com,example.com) |
--format <yaml\|json\|both> |
non | Format de sortie. Défaut both |
--title <string> |
non | OpenAPI info.title. Défaut déduit de l'origine primaire |
--redact <list> |
non | Noms d'en-têtes / clés JSON supplémentaires à flouter (séparés par des virgules) |
--min-samples <n> |
non | Minimum d'échantillons par endpoint à inclure. Défaut 1 |
--stage <name> |
non | Exécuter une seule étape : load, filter, normalize, infer, emit |
Disposition de la sortie
<run>/api-spec/
├── index.html rapport visuel — ouvrez ceci (autonome, pas de serveur)
├── client.mjs client fetch sans dépendances avec fonctions typées par opération
├── openapi.yaml spec lisible par machine
├── openapi.json miroir
├── report.md résumé markdown + exemples curl
├── confidence.json confiance par endpoint + drapeaux de normalisation
├── samples/ exemples requête/réponse floutés
│ └── <method>__<path-hash>.json
└── intermediate/ sous-produits du pipeline (jsonl appairés/filtrés/endpoints)
Ce que vous obtenez de browse cdp et browse network
Deux sources de capture complémentaires :
| Source | Fournit | Limitation |
|---|---|---|
browse cdp (utilisé par browser-trace) |
méthode/URL/en-têtes de requête/postData, statut/en-têtes/mimeType de réponse, timing complet des événements |
N'embarque pas les corps de réponse. Les corps doivent être récupérés avec Network.getResponseBody, ce que le firehose ne fait pas. |
browse network on (commande séparée) |
corps de requête ET corps de réponse sur disque, indexés par requestId CDP |
Le répertoire de capture est partagé par session browse ; faire un snapshot avant qu'un autre browse network on ne le réécrive. |
discover.mjs extraira les corps d'un répertoire browse network si vous passez --bodies <path> (ou les stockez sous <run>/cdp/network/bodies/, détecté automatiquement). La correspondance se fait par requestId — browse network l'écrit dans chaque request.json comme id, et nous joignons directement.
Ce qui change quand les corps sont présents :
- ✅ Templatisation de chemin, schémas de paramètres de requête, codes de statut, types de contenu — identique de toute façon.
- ✅ Schémas de corps de requête —
postDatade CDP suffit ; le répertoire bodies est un plus pour les cas sanspostData. - ✅ Schémas de corps de réponse — complètement déduits à partir d'échantillons réels. Sans bodies vous obtenez des squelettes
{ description, content: <mimeType> }.
Le rapport signale chaque endpoint qui n'a pas d'échantillon de corps de réponse.
Filtrage automatique du bruit
L'étape normalize classe automatiquement et supprime le bruit d'infrastructure :
- Suivi / analytiques — chemins contenant
/track,/pixel,/beacon,/impression,/pageview,/dag/v* - Défense anti-bot — Akamai (
/akam/), charges utiles d'empreinte (sensor_data), chemins multi-segments obscurcis - Plomberie de session —
/session,/authenticate/start, consentement aux cookies, endpoints d'expériences A/B - Rendus de pages HTML — requêtes
GETrenvoyanttext/html(la page rendue, pas l'API)
Cela supprime généralement 60-80% du trafic capturé. Le drapeau --include peut sauver un faux positif.
Décomposition GraphQL / endpoint multiplexé
Quand un single endpoint (comme /dapi/fe/gql) est appelé avec différentes valeurs operationName, la skill le divise automatiquement en opérations logiques séparées. Chacune obtient sa propre :
- Entrée de chemin OpenAPI (ex.
/dapi/fe/gql [Autocomplete]) - Schéma requête/réponse déduit uniquement des échantillons de cette opération
- Exemple curl et tableau de variables dans le rapport
La détection fonctionne sur les champs de corps (operationName, method, action) et paramètres de requête (opname, op). Cela couvre GraphQL (APQ et inline), JSON-RPC, et patterns de dispatch similaires.
Limitations
- La couverture est bornée par le flux capturé. Les endpoints non exercés dans la trace n'apparaîtront pas. La skill ne peut pas prouver la complétude.
- Les schémas sont inductifs, pas contractuels. Un champ peut être optionnel sur le serveur même si tous les échantillons le contenaient.
- L'authentification est observée, pas spécifiée. La skill enregistre les en-têtes de forme auth dans une extension
x-observed-authmais ne revendiquera pas un schéma de sécurité. - La templatisation de chemin est heuristique. Les patterns numérique / UUID / hex / slug sont détectés par segment. Les URLs ambiguës sont signalées dans
confidence.json. - Le floutage est au mieux un effort. Les floutages par défaut couvrent les identifiants courants, mais les secrets spécifiques à l'app peuvent s'échapper ; utilisez
--redactpour les en-têtes/clés personnalisés connus.
Bonnes pratiques
- Piloter les flux que vous voulez documenter. Plus la browser-trace est riche, plus la spec est riche.
- Utiliser
--originspour les sites bruyants. Une page marketing frappe des douzaines d'hôtes d'analytiques ; limitez à l'origine API qui vous intéresse. - Inspecter
report.mden premier. Il a des exemples curl-ready et des échantillons de réponse pour chaque opération découverte. - Augmenter
--min-samplesà 2+ quand vous voulez uniquement les endpoints confidemment formés dans le doc final — éliminez la queue longue. - Coupler avec
browse network onquand les schémas de corps de réponse importent. Le firehose CDP seul a les corps de requête mais pas les corps de réponse.
Pour les internals du pipeline et la référence de format de fichier, voir REFERENCE.md.