HAR ferramentas
Um arquivo HAR é uma transcrição em JSON de tudo o que o seu navegador viu na rede: como ele é estruturado, o que significam suas sete fases de tempo e o que ocultar antes de compartilhá-lo.
2 ferramentas
Um HAR é uma transcrição, não uma captura de pacotes
Um arquivo HAR (HTTP Archive) é um único documento JSON que descreve o que um
navegador observou na rede. Tudo o que interessa mora em log.entries[]: um
elemento por par requisição/resposta, carregando método, URL, cabeçalhos,
cookies, tamanhos, um detalhamento de tempos fase por fase e — às vezes — os
corpos. O formato é o HAR 1.2, um rascunho do W3C que nunca foi ratificado e,
mesmo assim, Chrome, Firefox, Safari, Charles e Fiddler emitem dialetos
parecidos o bastante para que os arquivos circulem entre eles.
O modelo mental que economiza horas: o arquivo é escrito pela própria pilha de rede do navegador, depois do fato — ele guarda o resumo dessa pilha, não o que passou no cabo. Nenhum registro de handshake TLS, nenhum frame HTTP/2, nenhum pacote DNS, apenas as durações que a pilha decidiu relatar. As requisições que dispararam antes de o DevTools ser aberto não estão ali, assim como a navegação anterior, a menos que Preserve log estivesse ativo, e acertos de cache ou de service worker aparecem como entradas que nunca tocaram a rede. Duas capturas do «mesmo» bug discordam rotineiramente.
Anatomia do arquivo
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
Dois detalhes pegam as pessoas. request.headers[] e request.cookies[] são
representações separadas dos mesmos cookies, então uma limpeza que só percorre
os cabeçalhos deixa o pote intacto. Chaves que começam com _ (_initiator,
_priority, _resourceType, _webSocketMessages) são extensões proprietárias:
úteis no Chrome, ausentes em outros lugares. E praticamente qualquer campo
numérico pode valer -1 — não disponível, não zero — incluindo bodySize,
pageTimings e cada fase de tempo.
As sete fases de tempo
Em milissegundos, na ordem em que ocorrem.
| Fase | Mede | Um valor alto normalmente significa | -1 quando |
|---|---|---|---|
blocked | Espera na fila antes de a requisição sair do cliente | O teto de cerca de 6 por origem do HTTP/1.1; negociação de proxy | Nunca ficou na fila |
dns | Resolução do nome do host | Resolvedor frio, cadeia longa de CNAME | Conexão reaproveitada |
connect | Handshake TCP — inclui ssl | Origem distante, RTT alto, sem keep-alive | Conexão reaproveitada |
ssl | Negociação TLS (contada dentro de connect) | Cadeia de certificados grande, sem retomada de sessão | HTTP puro, ou reaproveitamento |
send | Empurrar os bytes da requisição para fora | Um corpo de upload grande | — |
wait | TTFB depois do último byte da requisição | Processamento do backend mais um RTT | — |
receive | Ler o corpo vindo da rede | Payload sem compressão ou superdimensionado | — |
entry.time é o tempo total decorrido, na prática
blocked + dns + connect + send + wait + receive. Como ssl está aninhado
dentro de connect, somar todas as sete colunas conta o handshake duas vezes —
o erro aritmético mais comum na análise de HAR.
Reconstruir o waterfall
Os dois eixos podem ser recuperados do JSON: a posição horizontal é
entry.startedDateTime menos o log.pages[].startedDateTime da página à qual
a entrada pertence; a largura é entry.time, dividida nas fases acima.
entry.connection mostra quais requisições reaproveitaram um socket.
Depois leia a forma, não os números. Uma escada — cada requisição começando
quando a anterior termina — é uma cadeia de dependências, HTML → JS → API →
imagem, e nenhum ajuste de servidor resolve isso; o que precisa ser antecipado
é a descoberta. Um bloco denso cujo segmento blocked cresce conforme você
desce na lista é enfileiramento no cliente, e é por isso que o HTTP/2
frequentemente achata um waterfall sem que nenhuma resposta fique mais rápida.
Escolher a ferramenta certa
Cole a captura primeiro no Visualizador HAR — que também está
na seleção para SRE. Ele achata log.entries[] em
Method / Status / Type / Size / Time / URL com um resumo
N requests · X KB · Y ms total, colorindo a célula Status de vermelho para
4xx/5xx e de laranja para 3xx: o jeito mais rápido de achar o ponto fora
da curva. Só metadados, nunca os corpos.
O visualizador dá totais por entrada, não a divisão por fases. Para as fases,
consulte o arquivo bruto com o Buscador JSONPath —
$..timings para todos os detalhamentos, ou
$.log.entries[?(@.time>1000)].request.url só para as lentas. Se a exportação
não for interpretada (download truncado, colagem com quebras de linha), passe-a
pelo Formatador JSON para obter a posição exata do erro
segundo o parser.
Para a coluna Status, os Códigos HTTP transformam um
número solto em nome, classe e um significado de uma linha, filtráveis por
código ou palavra-chave — a forma rápida de resolver 400 contra 422. Eles
param no significado, não no comportamento de redirecionamento: a linha 301
diz apenas que o recurso foi movido permanentemente. Ao ler uma cadeia,
acrescente isto que vem do próprio protocolo — 301 e 302 permitem que um
cliente reescreva POST como GET e descarte o corpo, enquanto 307 e 308
não. A comparação completa é a matriz de redirecionamentos no
conjunto de ferramentas HTTP, que também cobre o lado dos
cabeçalhos. Sem captura, apenas com uma URL, os
Cabeçalhos HTTP a buscam no servidor a partir de
api.sitekits.dev e devolvem status, contagem de saltos de redirecionamento e
todos os cabeçalhos de resposta — o corpo nunca é recuperado, a URL nunca é
armazenada. Decodifique o token bearer de um 401 com o
Decodificador JWT para ver se exp já havia passado;
repita-o com o Testador REST API, que envia do seu
navegador direto ao destino, então o CORS se aplica como no seu aplicativo.
Pegadinhas
Um HAR bruto é uma credencial
Cookies de sessão, Authorization: Bearer …, x-api-key, URLs assinadas,
corpos de login e cada resposta que a sua sessão conseguia ler estão ali dentro.
O Sanitizador HAR roda inteiramente no seu navegador —
nada é enviado — substituindo cabeçalhos sensíveis, parâmetros que casam com
token|key|secret|password|passwd|pwd|auth|session|sig|signature e valores
inteiros de postData.text / content.text por [REDACTED], e informando
quantos ele pegou. Faça isso mesmo que o seu navegador tenha oferecido uma
exportação «sanitizada» — o que essas removem varia conforme a versão.
Ocultar por padrões não é prova
Os nomes de cabeçalho são comparados com uma lista fixa e os nomes de parâmetro
com uma expressão regular, então tudo o que é fora do convencional sobrevive:
segredos em segmentos de caminho de URL (/v1/reset/9f3c…), os arranjos
estruturados cookies[], serverIPAddress (o IP real da sua origem), nomes de
host internos. Passe os olhos pela saída, cole qualquer URL suspeita no
Parseador de URL para ver a query string decodificada e
procure por authorization e set-cookie antes de o arquivo sair da sua
máquina. O mesmo reflexo vale nas
ferramentas de privacidade e na
seleção para segurança.
content.size e bodySize medem coisas diferentes
content.size é o comprimento do corpo decodificado; bodySize são os bytes
efetivamente recebidos, com content.compression registrando a economia.
Respostas servidas do cache informam bodySize: 0, então um total em KB
calculado a partir de content.size exagera o custo de rede de um site
comprimido.