HAR outils
Un fichier HAR est une transcription JSON de tout ce que votre navigateur a vu sur le réseau : comment il est structuré, ce que signifient ses sept phases de temps, et ce qu'il faut expurger avant de le partager.
2 outils
Un HAR est une transcription, pas une capture de paquets
Un fichier HAR (HTTP Archive) est un unique document JSON décrivant ce qu’un
navigateur a observé sur le réseau. Tout l’intéressant vit dans
log.entries[] : un élément par paire requête/réponse, portant la méthode,
l’URL, les en-têtes, les cookies, les tailles, une décomposition des temps phase
par phase et — parfois — les corps. Le format est HAR 1.2, un brouillon du W3C
jamais ratifié, et pourtant Chrome, Firefox, Safari, Charles et Fiddler émettent
des dialectes suffisamment proches pour que les fichiers circulent entre eux.
Le modèle mental qui vous fait gagner des heures : le fichier est écrit par la pile réseau du navigateur lui-même, après coup — il contient le résumé de cette pile, pas le réseau. Aucun enregistrement de poignée de main TLS, aucune trame HTTP/2, aucun paquet DNS, seulement les durées que la pile a choisi de rapporter. Les requêtes parties avant l’ouverture de DevTools sont absentes, comme la navigation précédente à moins que Preserve log n’ait été actif, et les occurrences servies par le cache ou un service worker apparaissent comme des entrées qui n’ont jamais touché le réseau. Deux captures du « même » bug ne concordent pratiquement jamais.
Anatomie du fichier
log
├─ version "1.2" · creator{name,version} · browser
├─ pages[] id, title, startedDateTime, pageTimings{onContentLoad,onLoad}
└─ entries[] pageref, startedDateTime, time, connection, serverIPAddress
├─ request method, url, httpVersion, headers[], cookies[],
│ queryString[], postData{mimeType,text,params}
├─ response status, statusText, redirectURL, headers[], cookies[],
│ content{size,compression,mimeType,text,encoding}
├─ cache beforeRequest, afterRequest
└─ timings blocked, dns, connect, ssl, send, wait, receive
Deux détails piègent les gens. request.headers[] et request.cookies[] sont
des représentations distinctes des mêmes cookies : un nettoyage qui ne parcourt
que les en-têtes laisse donc le pot intact. Les clés commençant par _
(_initiator, _priority, _resourceType, _webSocketMessages) sont des
extensions propres à l’éditeur : utiles dans Chrome, absentes ailleurs. Et
presque tout champ numérique peut valoir -1 — indisponible, et non zéro — y
compris bodySize, pageTimings et chaque phase de temps.
Les sept phases de temps
En millisecondes, dans l’ordre où elles se produisent.
| Phase | Mesure | Une valeur élevée signifie souvent | -1 quand |
|---|---|---|---|
blocked | Mise en file avant que la requête ne quitte le client | Le plafond d’environ 6 par origine de HTTP/1.1 ; négociation de proxy | Jamais mise en file |
dns | Résolution du nom de l’hôte | Résolveur froid, longue chaîne de CNAME | Connexion réutilisée |
connect | Poignée de main TCP — inclut ssl | Origine distante, RTT élevé, pas de keep-alive | Connexion réutilisée |
ssl | Négociation TLS (comptée à l’intérieur de connect) | Longue chaîne de certificats, pas de reprise de session | HTTP simple, ou réutilisation |
send | Émission des octets de la requête | Un corps d’envoi volumineux | — |
wait | TTFB après le dernier octet de la requête | Traitement backend plus un RTT | — |
receive | Lecture du corps sur le réseau | Charge utile non compressée ou surdimensionnée | — |
entry.time est le temps total écoulé, en pratique
blocked + dns + connect + send + wait + receive. Comme ssl est imbriqué dans
connect, additionner les sept colonnes compte deux fois la poignée de main —
l’erreur arithmétique la plus courante en analyse de HAR.
Reconstituer la cascade
Les deux axes sont récupérables depuis le JSON : la position horizontale est
entry.startedDateTime moins le log.pages[].startedDateTime propriétaire ; la
largeur est entry.time, découpée selon les phases ci-dessus.
entry.connection montre quelles requêtes ont réutilisé une socket.
Ensuite, lisez la forme, pas les nombres. Un escalier — chaque requête démarrant
quand la précédente se termine — est une chaîne de dépendances, HTML → JS → API →
image, et aucun réglage serveur ne la corrige ; c’est la découverte qui doit
avancer plus tôt. Un bloc dense dont le segment blocked grandit à mesure qu’on
descend la liste est de la mise en file côté client, ce qui explique pourquoi
HTTP/2 aplatit souvent une cascade sans qu’aucune réponse ne devienne plus rapide.
Choisir le bon outil
Collez d’abord la capture dans la Visionneuse HAR — également
dans la sélection SRE. Elle aplatit log.entries[] en
Method / Status / Type / Size / Time / URL avec un récapitulatif
N requests · X KB · Y ms total, en colorant la cellule Status en rouge pour
les 4xx/5xx et en orange pour les 3xx : le moyen le plus rapide de trouver
l’anomalie. Métadonnées uniquement, jamais les corps.
La visionneuse donne des totaux par entrée, pas la répartition par phase. Pour les
phases, interrogez le fichier brut avec le
Chercheur JSONPath — $..timings pour toutes les
décompositions, ou $.log.entries[?(@.time>1000)].request.url pour les seules
requêtes lentes. Si l’export refuse de s’analyser (téléchargement tronqué, collage
avec retours à la ligne), passez-le dans le
Formateur JSON pour obtenir la position exacte de l’erreur
selon l’analyseur.
Pour la colonne Status, les Codes HTTP transforment un
simple nombre en nom, classe et signification d’une ligne, filtrables par code ou
mot-clé — la façon rapide de trancher entre 400 et 422. Ils s’arrêtent à la
signification, pas au comportement de redirection : leur ligne 301 dit seulement
que la ressource a été déplacée définitivement. Pour lire une chaîne, ajoutez ceci
qui vient du protocole lui-même — 301 et 302 autorisent un client à réécrire
un POST en GET et à abandonner le corps, tandis que 307 et 308 ne le
permettent pas. La comparaison complète est la matrice de redirections des
outils HTTP, qui couvre aussi le côté en-têtes. Sans capture,
avec seulement une URL, les En-têtes HTTP la chargent côté
serveur depuis api.sitekits.dev et renvoient le statut, le nombre de sauts de
redirection et tous les en-têtes de réponse — corps jamais récupéré, URL jamais
conservée. Décodez le jeton porteur d’un 401 avec le
Décodeur JWT pour voir si exp était dépassé ; rejouez-le
avec le Testeur REST API, qui émet depuis votre navigateur
droit vers la cible, si bien que le CORS s’applique comme dans votre application.
Pièges
Un HAR brut est un identifiant
Cookies de session, Authorization: Bearer …, x-api-key, URL signées, corps de
connexion et toute réponse que votre session pouvait lire s’y trouvent. Le
Nettoyeur HAR s’exécute entièrement dans votre navigateur —
rien n’est téléversé — en remplaçant les en-têtes sensibles, les paramètres
correspondant à
token|key|secret|password|passwd|pwd|auth|session|sig|signature, et les valeurs
entières de postData.text / content.text par [REDACTED], tout en rapportant
combien il en a attrapé. Faites-le même si votre navigateur a proposé un export
« assaini » — ce que ceux-là retirent varie selon la version.
L’expurgation par motifs n’est pas une preuve
Les noms d’en-têtes sont comparés à une liste fixe, les noms de paramètres à une
expression régulière : tout ce qui est inhabituel survit donc — secrets dans les
segments de chemin d’une URL (/v1/reset/9f3c…), tableaux structurés
cookies[], serverIPAddress (l’IP réelle de votre origine), noms d’hôtes
internes. Parcourez la sortie, collez toute URL suspecte dans le
Parseur d’URL pour une chaîne de requête décodée, et cherchez
authorization et set-cookie avant que le fichier ne quitte votre machine. Même
réflexe pour les outils de confidentialité et la
sélection sécurité.
content.size et bodySize ne mesurent pas la même chose
content.size est la longueur du corps décodé ; bodySize est le nombre d’octets
réellement reçus, content.compression enregistrant l’économie. Les réponses
issues du cache rapportent bodySize: 0, si bien qu’un total en Ko calculé depuis
content.size surestime le coût réseau d’un site compressé.