Inspeccionar una petición HTTP: curl, mensaje en bruto y HAR

Inspeccionar una petición HTTP: curl, mensaje en bruto y HAR

Formatea un Copy as cURL, analiza una petición o respuesta HTTP en bruto y lee un export HAR en tu navegador: no se envía ni se repite nada.

07.10.2026
18 min de lectura
Compartir este artículo:
HTTPcURLHARDepuraciónTutorial

Una petición, tres formas de leerla: comando cURL, mensaje en bruto, archivo HAR

Cuando una integración con una API se comporta mal, la prueba casi siempre es un intercambio HTTP que puedes copiar desde las DevTools. El problema es la forma en que llega: el Copy as cURL de Chrome es una sola línea interminable, una respuesta pegada es un bloque de cabeceras con un cuerpo debajo, y un export HAR es un archivo JSON con cientos de entradas. El formateador de cURL convierte un Copy as cURL o un Copy as fetch en cURL multilínea legible, o en HTTP/1.1, un archivo .http, fetch de JavaScript, Python requests, Go o PHP. El analizador de mensajes HTTP lee una petición en bruto, una respuesta o un bloque de cabeceras, conserva las cabeceras duplicadas y da formato a un cuerpo JSON. El inspector de HAR abre toda una sesión grabada, la reduce a la llamada que falla y la copia de vuelta como cURL. Las tres herramientas trabajan con texto pegado en tu navegador: FastMinify nunca envía la petición, nunca consulta la URL pegada y no tiene ejecutor ni proxy, así que un token incluido en lo pegado se queda en tu pestaña. Esta guía explica qué herramienta responde a qué pregunta, cómo depurar una petición que funciona en el navegador pero no en tu script, los errores que filtran credenciales o te desorientan, la anatomía de un mensaje HTTP y las mismas comprobaciones en un terminal y en Node. Las herramientas están en el hub de herramientas HTTP.

Formateador de cURL: lee el Copy as cURL y el Copy as fetch de Chrome (analizados como texto, nunca ejecutados), un archivo .http de una sola petición o una petición HTTP/1.1 en bruto. Salida como cURL multilínea o en una línea, HTTP/1.1, .http, fetch de JavaScript, Python requests, Go net/http o PHP curl
La opción Quitar secretos (desactivada por defecto en el formateador) omite de la copia las cabeceras Cookie, Authorization, Referer y sec-ch-*, y los valores de -u y -b
Analizador de mensajes HTTP: distingue una petición, una respuesta y un bloque de solo cabeceras, acepta finales de línea LF o CRLF, conserva las cabeceras duplicadas y puede dar formato a un cuerpo JSON. También limpia la salida pegada de <code>curl -v</code> (las líneas que empiezan por > y <)
Inspector de HAR: abre un archivo .har o .json de hasta 50 MB (aviso a partir de 20 MB), filtra las entradas por tipo, método, estado y URL, y copia una llamada como cURL o HTTP/1.1. Su opción Sanitizar secretos viene activada por defecto
Ningún botón Enviar: la petición nunca se ejecuta, así que no hay error de CORS que combatir ni efecto secundario en tu API
Todo ocurre en la pestaña: ningún comando, cabecera ni HAR pegado se sube a un servidor

Qué herramienta responde a qué pregunta

Usos adecuados

Estas tres herramientas sirven para leer, traducir y compartir un intercambio HTTP. No lo ejecutan.

Hacer legible un Copy as cURL de las DevTools antes de ponerlo en un ticket, un README o una revisión de código: una cabecera por línea en vez de un bloque compacto
Traducir la misma petición a fetch, Python requests, Go o PHP para reproducir una llamada en el lenguaje de tu proyecto
Revisar una respuesta que pegó un compañero: línea de estado, cabeceras duplicadas (varias líneas Set-Cookie, Vary) y cuerpo JSON, en el <a href="/es/http-message-parser" class="text-primary hover:underline">analizador de mensajes HTTP</a>
Pegar la salida de <code>curl -v</code> y recuperar la petición o la respuesta sin las líneas de registro <code>*</code>
Encontrar la llamada fallida entre cientos en un HAR con el filtro Errores y copiarla como cURL para repetirla desde un terminal
Lo que corresponde a otra herramienta

Cada herramienta termina donde empieza otra. Pasa el relevo a las herramientas vecinas o a tu propio código.

Repetir una petición: no hay ejecutor. Pega el cURL en un terminal, en Postman o en tu suite de pruebas
Descomponer una URL en protocolo, host, ruta y filas de query, o quitar parámetros de seguimiento: el <a href="/es/url-parser" class="text-primary hover:underline">analizador de URL</a>
Editar una cabecera <code>Cookie</code> o <code>Set-Cookie</code> y comprobar SameSite o el prefijo <code>__Host-</code>: el <a href="/es/cookie-header-editor" class="text-primary hover:underline">editor de cookies</a>
Leer los claims de un token Bearer sacado de una cabecera Authorization: el <a href="/es/jwt-decode" class="text-primary hover:underline">decodificador JWT</a>, y la <a href="/es/blog/codificar-decodificar-jwt-en-linea" class="text-primary hover:underline">guía de JWT</a> para saber qué prueba y qué no un token decodificado
Validar el contrato de la API en lugar de una llamada suelta: el <a href="/es/validate-openapi" class="text-primary hover:underline">validador OpenAPI</a> y la <a href="/es/blog/validar-openapi-swagger-en-linea" class="text-primary hover:underline">guía de validación OpenAPI</a>

Depurar una llamada a una API a partir de una petición copiada

Funciona en el navegador, pero no en tu script

Pega el Copy as cURL en el formateador de cURL y léelo línea por línea: contiene todo lo que añadió el navegador, no solo lo que necesita tu código.

Las cabeceras que añade el navegador, como <code>sec-ch-ua</code>, <code>accept-language</code>, <code>origin</code>, <code>referer</code> y toda la línea <code>cookie</code>, rara vez son necesarias. Quítalas una a una hasta que la llamada falle: la última que quitaste es la que importaba
Una llamada autenticada por cookie falla desde un script porque falta la cookie, no porque el código esté mal: la sesión vive en <code>Cookie</code>, mientras que un cliente de API suele enviar una cabecera <code>Authorization</code>
El método se deduce cuando no lo indicas: un cuerpo sin <code>-X</code> da POST, sin cuerpo da GET. Un GET con cuerpo indica que algo se perdió al copiar
Un <code>Content-Type</code> que no corresponde al cuerpo (JSON enviado como <code>application/x-www-form-urlencoded</code>, o al revés) es la causa clásica de un 400 o un 415
Un <code>--compressed</code> al final significa que el navegador envió <code>Accept-Encoding</code> y descomprimió la respuesta por ti. Tu cliente debe hacer lo mismo, o el cuerpo parecerá basura
Leer una respuesta: estado, cabeceras, cuerpo

Pega la respuesta en el analizador de mensajes HTTP. La línea de estado, la tabla de cabeceras y el cuerpo aparecen por separado.

La clase del estado indica a quién sospechar primero: 4xx la petición, 5xx el servidor, 3xx una redirección que debes seguir (RFC 9110). En un 3xx, mira <code>Location</code>
<code>WWW-Authenticate</code> en un 401 nombra el esquema que espera el servidor, y <code>Retry-After</code> en un 429 o un 503 indica cuánto esperar
Las cabeceras duplicadas se conservan en filas separadas. Dos líneas <code>Set-Cookie</code> son dos cookies, no un error, y un <code>Vary</code> repetido es legal
El Content-Type decide cómo leer el cuerpo: un error JSON servido como <code>text/html</code> suele venir de un proxy o una pasarela, no de tu API
Los cuerpos con transferencia fragmentada (chunked) no se reensamblan. Si el cuerpo empieza con un tamaño hexadecimal en su propia línea, has pegado el flujo en bruto: copia mejor el cuerpo decodificado desde las DevTools
Encontrar la llamada fallida en un HAR

Abre el export en el inspector de HAR y reduce la lista antes de leer ningún detalle.

Los contadores Peticiones, Tamaño, Tiempo y Errores están encima de la lista. Errores cuenta las entradas con estado 400 o superior
Una petición que no recibió ninguna respuesta se registra con estado 0 (bloqueada por una extensión, fallo de DNS, preflight de CORS fallido). No cuenta como error: recorre también la lista sin filtrar
El filtro XHR agrupa las llamadas fetch y XMLHttpRequest. Añade un filtro de texto sobre <code>/api/</code> para descartar fuentes, imágenes y scripts de seguimiento
Selecciona una fila para leer las cabeceras de petición, las de respuesta, el payload y una vista previa del cuerpo de la respuesta, y usa Copiar cURL para repetirla
Un HAR exportado desde Chrome 130 o posterior viene saneado por defecto y omite Cookie, Set-Cookie y Authorization. Que falte la cabecera Authorization en el archivo no prueba que el navegador no la enviara

Cuatro errores que filtran una credencial o te despistan

Compartir una petición copiada con sus credenciales dentro

Un Copy as cURL de una sesión autenticada lleva tus cabeceras Cookie y Authorization, y cualquiera que lea el ticket puede repetir la llamada como si fueras tú. El interruptor Quitar secretos omite de la copia Cookie, Authorization, Referer, sec-ch-* y los valores de -u y -b. Viene desactivado por defecto en el formateador y en el Copiar como cURL del analizador, y activado en el inspector de HAR. Solo actúa sobre cabeceras: un token en la cadena de consulta (?access_token=), en el cuerpo de la petición, en una cabecera propia como X-Api-Key o en el cuerpo de una respuesta se queda exactamente donde estaba. Lee la salida antes de pegarla y renueva todo lo que ya haya salido de tu equipo. El escáner de secretos ayuda a detectar una clave que no habías visto.

Publicar un Copy as cURL en un issue público porque la cabecera Authorization es «solo un token de prueba»
Suponer que Quitar secretos también elimina los tokens de la URL o del cuerpo
Enviar un HAR a un proveedor sin revisar los cuerpos de respuesta, que pueden contener datos personales
Dejar una clave de larga duración en un cURL guardado en una wiki o en el historial del shell
Quita los secretos y vuelve a leer el resultado: cadenas de consulta, cuerpos y cabeceras propias los limpias tú. Renueva toda credencial que se haya compartido.
Leer los contadores del HAR como rendimiento de la página

El Tiempo del inspector de HAR es la duración de la entrada más larga, no el tiempo de carga de la página, y Tamaño suma los tamaños de cuerpo registrados en cada entrada. Responden a «qué llamada fue la más lenta» y «cuántos datos circularon», no a lo que mide Lighthouse. Las peticiones se ejecutan en paralelo, así que la suma de los tiempos tampoco es el tiempo de la página. Las respuestas en caché y los cuerpos comprimidos hacen que los tamaños difieran de los que muestra el pie del panel de red.

Citar el Tiempo del inspector como tiempo de carga de la página
Comparar el tamaño total del HAR con el peso transferido de Lighthouse y declarar erróneo uno de los dos
Ignorar las peticiones con estado 0 porque el contador Errores marca 0
Juzgar un problema de rendimiento por un único HAR grabado con la caché desactivada y una extensión activa
Optimizas el endpoint equivocado, o informas de una tasa de errores nula mientras una petición se bloquea en silencio.
Esperar una reproducción fiel de lo que pegaste

El formateador entiende el subconjunto de cURL que generan las DevTools e ignora el resto sin avisar. Opciones como -L, -s, -k, --insecure, -v y -o desaparecen de la salida: un comando que contaba con -L para seguir una redirección o con -k para saltarse la comprobación del certificado pierde ese comportamiento al traducirse. Algunas entradas se rechazan con un mensaje claro: subidas multipart (-F), subidas de archivo con -T, cuerpos @archivo, {{variables}} de REST Client, archivos .http con varias peticiones, fragmentos de axios y llamadas fetch con plantillas literales o variables sin resolver. Una respuesta pegada no es una petición, así que no hay nada que convertir a cURL.

Traducir un cURL que usaba -L y esperar que el fetch generado se comporte igual
Pegar una subida multipart y extrañarse de que el formateador la rechace
Querer copiar como cURL desde un pegado que solo contiene una respuesta
Tratar el fragmento generado como código de producción en lugar de un punto de partida
Lee una vez el código generado, añade tú los tiempos de espera, los reintentos y el manejo de errores, y guarda los secretos en variables de entorno.
Cambiar el cuerpo sin darte cuenta

Varias salidas reindentan un cuerpo JSON: el cURL multilínea, las salidas HTTP/1.1 y .http, el fetch de JavaScript, y Python requests, que lo convierte en un literal json=. El cURL de una línea conserva el cuerpo tal como lo pegaste. Para la mayoría de las API es inocuo, y fatal cuando el servidor comprueba una firma calculada sobre los bytes exactos, como suelen hacer los endpoints de webhooks: un solo espacio añadido y el HMAC deja de coincidir. La guía de hash y HMAC explica cómo se construyen esas firmas.

Repetir el cuerpo firmado de un webhook después de pasarlo por un formateador
Comparar un fragmento generado con el original byte a byte
Usar la salida multilínea como fixture de una prueba de firma
Pegar la salida multilínea en una prueba que compara el cuerpo como cadena
Con un cuerpo firmado, conserva el texto original, usa el cURL de una línea y calcula la firma sobre la cadena exacta que envías.

Anatomía de un mensaje HTTP y qué mira cada herramienta

Línea inicial, cabeceras, línea vacía, cuerpo

Un mensaje HTTP/1.1 es texto plano (RFC 9112) y su significado lo define la RFC 9110. Petición y respuesta comparten la misma disposición.

Línea de petición: <code>POST /orders HTTP/1.1</code> lleva el método, el destino y la versión del protocolo. Una petición debe incluir una cabecera <code>Host</code>
Línea de estado: <code>HTTP/1.1 201 Created</code> lleva la versión, un código de tres cifras y una frase explicativa que los clientes ignoran
Cabeceras: un <code>Nombre: valor</code> por línea, los nombres no distinguen mayúsculas y un mismo nombre puede repetirse
Una línea vacía termina las cabeceras. Lo que sigue es el cuerpo, que puede estar vacío (un GET, un 204)
Las líneas de cabecera plegadas (una continuación que empieza por un espacio) las une el analizador en un solo valor
La misma petición en cuatro formas

Las herramientas convierten de una a otra, por eso una petición copiada puede acabar siendo cualquiera de ellas.

Copy as cURL: <code>curl URL -H "Nombre: valor" --data-raw CUERPO --compressed</code>, con el método añadido por <code>-X</code> cuando no es GET
Copy as fetch: <code>fetch(url, { method, headers, body })</code>, un literal de JavaScript que el formateador lee como texto y nunca evalúa
HTTP/1.1 en bruto: la línea de petición, una cabecera Host y las demás cabeceras, y luego el cuerpo. El formato <code>.http</code> de las extensiones REST Client es igual, con la URL completa en la primera línea
Entrada HAR: un objeto JSON con <code>request</code> (method, url, headers, postData) y <code>response</code> (status, headers, content), más un <code>time</code> en milisegundos. HAR 1.2 se describe en un borrador del W3C
Las salidas de Python, Go y PHP son la misma llamada escrita con requests, net/http y la extensión curl
Clases de estado y cabeceras que se leen primero

Un orden de lectura corto ahorra la mayoría de las sesiones de depuración largas.

1xx informativo, 2xx éxito, 3xx redirección, 4xx error del cliente, 5xx error del servidor (RFC 9110). El analizador muestra la clase de una respuesta como una insignia de color
401 significa «no autenticado» y viene con <code>WWW-Authenticate</code>; 403 significa autenticado pero sin permiso; 429 significa límite de peticiones y suele llevar <code>Retry-After</code>
<code>Content-Type</code> y <code>Content-Length</code> (o la transferencia chunked) describen el cuerpo; <code>Accept</code> y <code>Accept-Encoding</code> describen lo que el cliente sabe leer
<code>Cache-Control</code>, <code>ETag</code> y <code>Age</code> explican por qué una respuesta está caducada o fresca, y <code>Set-Cookie</code> y <code>Location</code> cambian lo que hace el cliente a continuación
Las mismas clases son el filtro Estado del inspector de HAR, con un atajo Errores para 400 y superiores

Las tres herramientas, paso a paso

Formatear un Copy as cURL con el formateador de cURL

El formateador de cURL reformatea mientras pegas, sin botón Enviar. En Chrome, haz clic derecho sobre la petición en la pestaña Red, luego Copy y Copy as cURL (bash).

1

Pega el comando

Se detectan un Copy as cURL, un Copy as fetch, un archivo .http de una sola petición o una petición HTTP/1.1 en bruto. Las continuaciones de línea se unen por ti.

2

Elige el lenguaje y la disposición

cURL, HTTP/1.1, .http, fetch de JavaScript, Python requests, Go net/http o PHP curl, en disposición multilínea o de una línea.

3

Activa Quitar secretos antes de compartir

Omite de la copia Cookie, Authorization, Referer, sec-ch-* y los valores de -u y -b. Las cadenas de consulta y los cuerpos quedan intactos.

4

Copia o descarga el resultado

Cada lenguaje tiene su propio nombre de archivo (formatted-curl.sh, formatted-request.http, formatted-requests.py y así sucesivamente). Un error de análisis indica qué se rechazó y por qué.

Leer una petición o respuesta en bruto con el analizador de mensajes HTTP

El analizador de mensajes HTTP presenta un mensaje pegado como línea inicial, tabla de cabeceras y cuerpo.

1

Pega el mensaje

Una petición, una respuesta, un bloque de cabeceras sueltas o la salida de curl -v. Funcionan los finales de línea LF y CRLF.

2

Comprueba el tipo detectado

La herramienta lo etiqueta como Petición HTTP, Respuesta HTTP o Solo cabeceras, y muestra el número de cabeceras. Los duplicados siguen en filas separadas.

3

Lee el cuerpo

Un cuerpo JSON se formatea por defecto, con un interruptor para verlo en bruto. Los cuerpos chunked no se reensamblan.

4

Copia una petición como cURL

Hace falta una petición con URL absoluta o una cabecera Host. Con solo Host, el esquema se adivina: http para localhost, 127.0.0.1 o el puerto 80, y https en el resto de casos. El interruptor Sanear la copia viene desactivado por defecto.

Explorar una sesión con el inspector de HAR

El inspector de HAR lee el archivo en tu pestaña y nunca consulta las URL que lista.

1

Exporta el HAR

En el panel Red, usa el icono de descarga (Export HAR). Se abren los exports de Chrome, Firefox, Edge, Charles y HTTP Toolkit de hasta 50 MB; por encima de 20 MB el filtrado puede ir lento.

2

Suelta el archivo o pega el JSON

Un archivo .har o .json, o el propio JSON HAR 1.2. El botón de ejemplo carga una captura pequeña para probar los filtros.

3

Reduce la lista

Filtros de tipo (XHR, JS, CSS, Img, Media, Font, Doc, Otros, Errores), un método, una clase de estado y la búsqueda «URL contiene». El tipo sale de la entrada cuando Chrome lo registra, o del tipo MIME de la respuesta.

4

Abre una llamada y extráela

Lee las cabeceras de petición y de respuesta, el payload y la vista previa del cuerpo. Copiar cURL, Copiar HTTP/1.1 o Copiar URL, o descarga el archivo: con Sanitizar secretos activado se escribe como sanitized.har, sin las cabeceras Cookie, Set-Cookie, Authorization, Referer y sec-ch-* ni las listas de cookies.

Lo que las herramientas no hacen

Algunos límites que conviene conocer antes de fiarse de ellas.

Nunca se envía ni se repite una petición: no hay ejecutor, ni proxy, ni botón Enviar
Sin cuerpos multipart (-F) ni archivos (-T, @archivo), sin {{variables}} de REST Client, sin fragmentos de axios, sin archivos .http con varias peticiones
Las opciones de cURL como -L, -k, -s y -o se ignoran en la salida
Sin reensamblado de cuerpos chunked en el analizador de mensajes
El inspector de HAR no dibuja una cascada (waterfall) ni calcula los tiempos de la página
Quitar secretos actúa sobre cabeceras y listas de cookies, no sobre URL, cuerpos ni cabeceras propias

Las mismas comprobaciones en un terminal y en Node

curl: solo las cabeceras, o todo el intercambio

Cuando puedes ejecutar un comando, curl muestra los mismos datos que presenta el analizador. Guarda los tokens en variables de entorno, no en el comando que pegas en un ticket.

Ejemplo básico

# Response headers only: -D - writes them to stdout, -o /dev/null drops the body curl -sS -D - -o /dev/null https://api.example.com/orders/42 \ -H "Authorization: Bearer $API_TOKEN" # The full exchange: lines starting with > are sent, < received, * is curl's own log curl -v https://api.example.com/orders/42 2>&1 | head -40
Node: filtrar un HAR sin abrir un navegador

Un HAR es JSON, así que unas pocas líneas listan las llamadas fallidas. A diferencia del contador Errores del inspector, este filtro conserva también el estado 0.

Ejemplo básico

import { readFileSync } from 'node:fs' const har = JSON.parse(readFileSync('session.har', 'utf8')) // Status 0 means no response at all (blocked, DNS failure, CORS): keep it in the list const failed = har.log.entries .filter((e) => e.response.status >= 400 || e.response.status === 0) .map((e) => ({ method: e.request.method, status: e.response.status, url: e.request.url, ms: Math.round(e.time), })) console.table(failed)
Node: reproducir una llamada fetch copiada

Toma la salida de Copy as fetch, mueve el secreto a una variable de entorno y muestra lo que vuelve. Los fragmentos que genera el formateador son un punto de partida del mismo tipo.

Ejemplo básico

// The call you copied as fetch(), with the secret read from the environment const res = await fetch('https://api.example.com/orders', { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: 'Bearer ' + process.env.API_TOKEN, }, body: JSON.stringify({ sku: 'A-1042', qty: 2 }), }) console.log(res.status, res.statusText) console.log(res.headers.get('content-type')) console.log(res.headers.getSetCookie()) // every Set-Cookie line, Node 20+ console.log(await res.text())
Las herramientas HTTP de FastMinify

Nada que instalar y nada enviado: el formateador de cURL, el analizador de mensajes HTTP y el inspector de HAR cubren leer, traducir y compartir una petición. Las contrapartidas: sin repetición, un subconjunto de cURL, sin cascada de tiempos y una limpieza que solo conoce las cabeceras. Para una prueba real, lanza la llamada desde un terminal, Postman o tu propia suite de pruebas; para comprobar una especificación en vez de una llamada, usa el validador OpenAPI.

Conclusión

Un intercambio HTTP es solo texto, y depurarlo consiste sobre todo en leerlo en la forma adecuada. El formateador de cURL hace legible y portable un Copy as cURL, el analizador de mensajes HTTP presenta una petición o respuesta en bruto con sus cabeceras duplicadas y su cuerpo JSON, y el inspector de HAR reduce una sesión grabada a la llamada que falló. Ninguno envía nada: tú controlas lo que sale de tu navegador, y eso importa porque lo que pegas contiene cookies y tokens. Quita los secretos antes de compartir, recuerda que eso solo limpia cabeceras y lee los contadores por lo que son. El hub de herramientas HTTP reúne las herramientas vecinas para URL y cookies.

Lee un Copy as cURL línea por línea y quita las cabeceras que añadió el navegador antes de reproducir una llamada
Quita los secretos antes de compartir y limpia a mano la cadena de consulta, el cuerpo y las cabeceras propias
En un HAR, cuenta el estado 0 como un fallo y lee el Tiempo como la llamada más lenta, no como el tiempo de la página
Conserva el cuerpo original cuando una firma lo cubre: reindentar JSON cambia los bytes
Repite una llamada desde un terminal o una suite de pruebas: las herramientas del navegador leen y traducen, nunca envían
Compartir este artículo
Compartir este artículo: