Geonode logo
Geonode Team

Geonode Team

Actualizado: 7 de octubre de 2026

Publicado: 2 de septiembre de 2026

Cómo mostrar los encabezados de respuesta con curl

curl oculta los encabezados de respuesta de forma predeterminada. Hay cuatro opciones para mostrarlos, y sus diferencias son más importantes de lo que sugiere la documentación. Una de ellas envía una solicitud diferente a la que estás intentando depurar, lo cual es una forma estupenda de pasar una hora persiguiendo una discrepancia que no existe. Esta guía aborda las cuatro opciones, además de la salida en formato JSON que la mayoría de la gente desconoce y cómo cambia el panorama al pasar por un proxy.

Por qué nos importa: somos Geonode y vendemos proxies, y los encabezados de respuesta son la forma más rápida de responder a la pregunta que más nos hacen los clientes: ¿es un problema del proxy o no? Una página de bloqueo, un límite de velocidad y un error real se ven idénticos en un navegador, pero son completamente diferentes en los encabezados. Un 429 con Retry-After significa que vas demasiado rápido y ningún proxy puede solucionarlo. Un 403 con un encabezado «security-vendor» significa que el destino te ha identificado. Un 407 significa que el proxy solicita credenciales. Leer los encabezados antes de cambiar nada te ahorra muchas conjeturas, y curl dispone de un indicador para este caso concreto — %{proxy_used}, añadido en la versión 8.7.0—, que devuelve 1 si la transferencia se ha realizado a través de un proxy. Resulta útil cuando no estás seguro de si tu configuración ha surtido efecto.

Las cuatro opciones de un vistazo

OpciónMuestraEnvíaIdeal para
-iEncabezados de respuesta + cuerpoTu solicitud realInspección diaria
-ISolo encabezados de respuestaUna solicitud HEADComprobaciones rápidas, con una salvedad
-D fileEncabezados de respuesta a un archivoTu solicitud realScripts, separación de flujos
-vEncabezados de solicitud y respuestaTu solicitud realDepuración de lo que has enviado

La fila clave es la segunda, y es la que más confusión genera en este ámbito. Todo lo demás depende de dónde se dirija la salida.

-i

: Encabezados con el cuerpo La opción más habitual. El manual de curl la describe como -i, --show-headers : «Muestra los encabezados de la respuesta en la salida... Esta opción hace que los encabezados de la respuesta se guarden en el mismo flujo o salida que los datos».

curl -i https://example.com
HTTP/2 200
content-type: text/html; charset=UTF-8
content-length: 1256
cache-control: max-age=604800
date: Wed, 02 Sep 2026 10:14:22 GMT

<!doctype html>...

Encabezados, una línea en blanco y, a continuación, el cuerpo: la misma estructura que el formato «wire».

Una nota sobre la nomenclatura que puede confundir a quienes lean material más antiguo: la forma completa es ahora --show-headers . Antes era --include , y ambas funcionan, pero la documentación actual utiliza el nombre más reciente.

Dos detalles que conviene conocer. Cuando la salida se envía a un terminal, curl puede mostrar los nombres de los encabezados en negrita y marcar las URL de Location: , lo cual resulta útil en modo interactivo pero no es deseable en una cadena de comandos — --no-styled-output lo desactiva. Y dado que los encabezados y el cuerpo comparten un flujo, -i con -o file escribe ambos en el archivo, lo cual casi nunca es lo que se desea. Utiliza -D para ese caso.

-I: Solo encabezados, y por qué puede llevar a confusión

-I se describe así: «Recupera solo los encabezados. Los servidores HTTP cuentan con el comando HEAD, que se utiliza para obtener únicamente el encabezado de un documento».

Léelo con atención. No recupera la respuesta ni descarta el cuerpo. Envía un método HTTP diferente.

curl -I https://example.com

Se trata de una solicitud HEAD, y las consecuencias son reales:

Algunos servidores gestionan HEAD de forma diferente. Un HEAD puede devolver encabezados distintos, un código de estado diferente o ser rechazado por completo con un 405 Method Not Allowed, mientras que el equivalente GET funciona perfectamente.

Algunos marcos de trabajo no calculan el cuerpo para HEAD, por lo que Content-Length, ETag y Content-Type pueden estar ausentes o ser incorrectos.

Las CDN y las cachés suelen tratar HEAD como una clave de caché distinta, por lo que los encabezados de caché pueden diferir de los que vería una solicitud real.

Los sistemas antibots pueden responder de forma diferente. Un HEAD procedente de un cliente inusual es en sí mismo una señal, y es posible que el desafío que recibas no sea el mismo que generaría un GET.

Por lo tanto, -I es excelente para comprobaciones rápidas —¿está activa esta URL?, ¿a dónde redirige?, ¿qué tamaño tiene el archivo?— pero poco fiable para depurar por qué un GET se comporta de forma extraña. Cuando estés diagnosticando una solicitud real, utiliza el método adecuado:

curl -sS -o /dev/null -D - https://example.com

Esto realiza una solicitud GET normal, descarta el cuerpo a /dev/null y muestra los encabezados en la salida estándar. Te ofrece lo mismo que parece ofrecerte -I, sin modificar la solicitud.

Si necesitas específicamente los encabezados de un POST, se aplica el mismo patrón:

curl -sS -o /dev/null -D - -X POST -H "Content-Type: application/json" \
     -d '{"a":1}' https://api.example.com/items

-D y -v: Separación de flujos y visualización de solicitudes

-D escribe los encabezados en un destino independiente. El manual indica: «Escribe los encabezados de protocolo recibidos en el archivo especificado... Especifica '-' como nombre de archivo (un solo signo menos) para que se escriban en stdout». También señala que, si no se reciben encabezados, la opción «crea un archivo vacío», lo cual constituye en sí mismo información de diagnóstico.

curl -D headers.txt -o body.html https://example.com

Una separación clara, que es lo que se busca en los scripts. -D - envía los encabezados a stdout, mientras que el cuerpo va a donde apunte -o, y esa combinación es la base del patrón anterior.

-v muestra también la solicitud, que suele ser la parte que realmente necesitas. El manual explica los prefijos con precisión:

Las líneas de salida detalladas van precedidas de letras: > encabezado enviado por curl, < encabezado recibido por curl, } datos enviados por curl, { datos recibidos por curl, * información adicional proporcionada por curl.

curl -v https://example.com 2>&1 | grep '^>'

Esto te muestra exactamente lo que curl ha transmitido —lo cual a menudo no es lo que has configurado, ya que las bibliotecas, los valores por defecto y los archivos .curlrc añaden y sobrescriben encabezados—. Muchos de los problemas del tipo «el servidor ignora mi encabezado» se resuelven aquí.

Ten en cuenta que la salida detallada se dirige a stderr, por lo que es necesario utilizar 2>&1 antes de la canalización. Esto es deliberado: mantiene limpio el cuerpo en stdout.

El manual también señala que, desde curl 8.10, repetir «-v» aumenta el nivel de seguimiento. Para tareas verdaderamente de bajo nivel, «--trace-ascii» proporciona «un volcado completo de seguimiento de todos los datos entrantes y salientes, incluida información descriptiva», omitiendo el código hexadecimal para que siga siendo legible.

Hay una advertencia del manual que merece la pena repetir: la salida de seguimiento y la salida detallada «pueden contener datos confidenciales, como nombres de usuario, credenciales o contenido secreto. Tenlo en cuenta y ten cuidado al compartir registros de seguimiento con otras personas». Las credenciales del proxy pasadas en una URL aparecen en la salida detallada. Ocultalas antes de pegarlas en un sistema de seguimiento de incidencias.

Encabezados legibles por máquina con ``%{header_json}`

`: la opción que la mayoría de la gente nunca ha visto, añadida en curl 7.83.0, y la respuesta correcta cada vez que estuvieras a punto de escribir una expresión regular sobre el texto de un encabezado.

El manual la describe como «un objeto JSON con todos los encabezados de respuesta HTTP de la transferencia reciente. Los valores se proporcionan como matrices, ya que, en el caso de que haya varios encabezados, puede haber varios valores». Los nombres de los encabezados aparecen «en minúsculas, ordenados según su orden de aparición en la red», y los duplicados «se agrupan en la primera aparición de ese encabezado; cada valor se presenta en la matriz JSON».

curl -s -o /dev/null -w '%{header_json}' https://example.com | jq
{
  "content-type": ["text/html; charset=UTF-8"],
  "cache-control": ["max-age=604800"],
  "set-cookie": ["a=1; Path=/", "b=2; Path=/"]
}

Esto resuelve tres cosas a la vez. Los nombres se normalizan a minúsculas, por lo que no hay coincidencia que no distinga entre mayúsculas y minúsculas. Los encabezados repetidos, como Set-Cookie , se muestran como matrices en lugar de ser ocultados de forma silenciosa. Y la salida se puede analizar sin necesidad de escribir un analizador sintáctico.

Extraer un único encabezado resulta muy sencillo:

curl -s -o /dev/null -w '%{header_json}' "$URL" | jq -r '.["retry-after"][0] // "none"'

Otras variables de -w que combinan bien con ella:

curl -s -o /dev/null -w 'status=%{response_code} redirects=%{num_redirects} proxy=%{proxy_used} ip=%{remote_ip}\n' "$URL"

response_code es el estado de la última transferencia, num_redirects cuenta las redirecciones seguidas, redirect_url muestra adónde habría llevado una redirección si no hubieras utilizado -L , remote_ip es la dirección a la que se ha conectado realmente, y proxy_used devuelve 1 si ha intervenido un proxy. Esta última es realmente útil cuando un patrón NO_PROXY puede haber excluido silenciosamente tu host.

Siguir cadenas de redireccionamiento

Sin «-L

», curl se detiene en el primer redireccionamiento y solo se ve esa respuesta. Con -L

, curl muestra los encabezados de todas las respuestas de la cadena:

curl -sSL -o /dev/null -D - https://example.com
HTTP/2 301
location: https://www.example.com/

HTTP/2 200
content-type: text/html

Cada bloque representa un salto. Así es como se descubre que una URL redirige tres veces, que en un salto se pasa a HTTP sin cifrar o que una redirección pierde una cookie.

Dos patrones que conviene conservar:

curl -sSL -o /dev/null -w '%{num_redirects} hops -> %{url_effective}\n' "$URL"

El recuento y el destino final en una sola línea. Y cuando quieras ver adónde apunta una redirección sin seguirla:

curl -s -o /dev/null -w '%{redirect_url}\n' "$URL"

Merece la pena inspeccionar las cadenas de redirecciones con más frecuencia de lo que se suele hacer. Cada salto es un viaje de ida y vuelta; una cadena de cuatro añade latencia real, y un salto inesperado a través de un host diferente suele ser la explicación de un problema con las cookies o con CORS.

Encabezados a través de un proxy

Hay dos aspectos que hay que tener en cuenta y que suelen generar confusión la primera vez.

** Las respuestas «CONNECT » aparecen en la salida detallada.** En el caso de HTTPS a través de un proxy HTTP, curl envía primero un «CONNECT » para establecer un túnel, y ese intercambio tiene sus propios encabezados:

curl -v -x http://proxy.example.com:8080 https://example.com

Verás el CONNECT , un HTTP/1.1 200 Connection established del proxy y, solo entonces, la solicitud real. Ese primer bloque corresponde al proxy, no al destino. Confundirlos es un error común al principio. --suppress-connect-headers los elimina de la salida cuando solo te interesa la respuesta del destino.

%{http_connect} muestra el código de respuesta del proxy específicamente para la solicitud CONNECT, independientemente del estado del destino. Esa distinción es precisamente lo que necesitas cuando algo falla y no sabes qué eslabón del proceso ha rechazado la solicitud:

curl -s -o /dev/null -x "$PROXY" \
  -w 'connect=%{http_connect} status=%{response_code} proxy=%{proxy_used}\n' \
  https://example.com

connect=200 status=403 significa que el proxy funcionó y que el destino rechazó la solicitud. connect=407 significa que el proxy solicitó credenciales y nunca llegó al destino. Esas dos situaciones tienen soluciones completamente diferentes y, sin esta distinción, parecen idénticas desde el punto de vista de la aplicación.

Ten en cuenta también que, en el caso de HTTPS a través de un túnel, el proxy no puede añadir ni leer encabezados: se limita a retransmitir bytes cifrados. Si ves encabezados inesperados en una respuesta HTTPS, estos provienen del destino o de una CDN situada delante de él, no del proxy.

Lo que realmente te indican los encabezados

De qué va todo esto. Si los lees bien, pasas de hacer conjeturas a llegar a un diagnóstico.

Primero, la línea de estado. 200 se ha resuelto correctamente. 301/302 redirigido. 403 rechazado. 429 limitado por tasa. 407 autenticación de proxy. 502/503 problema en el servidor de origen.

Retry-After aparece junto con 429 y 503 y te indica exactamente cuánto tiempo debes esperar. Respetar este tiempo es lo correcto y la forma más rápida de volver a funcionar. Ignorarlo e intentarlo de nuevo inmediatamente es la forma en que un límite temporal se convierte en uno más prolongado.

Content-Type te indica lo que realmente has recibido. text/html en un punto final de la API significa que has obtenido una página de error, no JSON, y es la respuesta a una gran parte de los fallos de análisis.

Content-Length frente a lo que llegó. Un cuerpo corto con una longitud declarada grande indica truncamiento.

Los encabezados de caché — Cache-Control, ETag, Last-Modified — te indican si puedes evitar volver a recuperar los datos. If-None-Match y If-Modified-Since en solicitudes posteriores convierten una transferencia completa en una 304, lo que supone un ahorro directo cuando se dispone de un ancho de banda medido.

Set-Cookie muestra qué estado de sesión está estableciendo el servidor, y su ausencia cuando esperabas que estuviera presente explica muchos enigmas de autenticación.

Server y los encabezados específicos del proveedor identifican lo que hay delante del origen. Una respuesta que incluya los encabezados de un proveedor de seguridad con un 403 indica que el bloqueo procedía de una capa de protección y no de la aplicación —un problema diferente con una respuesta diferente.

Encabezados no estándar. Los límites de tasa, los identificadores de solicitud y los metadatos específicos de la API suelen aparecer como encabezados con el prefijo x-, y a menudo son la información más útil de la respuesta. El servicio de asistencia técnica te pedirá el ID de la solicitud.

Preguntas frecuentes

¿Cómo puedo ver los encabezados de respuesta con curl?

curl -i URL muestra los encabezados seguidos del cuerpo. curl -D - URL escribe los encabezados en stdout por separado. curl -v URL muestra tanto los encabezados de la solicitud como los de la respuesta. Evita -I al depurar una solicitud real, ya que envía un HEAD en lugar de un GET.

¿Cuál es la diferencia entre -i y -I en curl?

-i incluye los encabezados de respuesta junto con el cuerpo de tu solicitud real. -I envía una solicitud HEAD en su lugar, por lo que se trata de una solicitud diferente con resultados potencialmente distintos. Utiliza -i o -o /dev/null -D - cuando necesites los encabezados de la solicitud que estás depurando realmente.

¿Cómo puedo ver solo los encabezados sin el cuerpo?

curl -sS -o /dev/null -D - URL. Esto realiza una solicitud GET normal, descarta el cuerpo y muestra los encabezados. Te ofrece lo mismo que parece ofrecer -I sin cambiar el método HTTP, lo cual es importante porque algunos servidores responden de forma diferente a las solicitudes HEAD o las rechazan directamente.

¿Cómo puedo ver los encabezados de solicitud que envía curl?

curl -v URL y busca las líneas que comienzan por >, que son los encabezados enviados por curl. La salida detallada se envía a stderr, así que utilice una tubería con 2>&1 si desea filtrarla. Así es como se confirma que el encabezado que ha configurado se transmite realmente.

¿Cómo puedo obtener los encabezados de curl en formato JSON?

curl -s -o /dev/null -w '%{header_json}' URL. Añadida en la versión 7.83.0 de curl, esta opción emite todos los encabezados de respuesta como un objeto JSON con nombres en minúsculas y valores en forma de matriz, de modo que los encabezados repetidos, como Set-Cookie, se conservan en lugar de agruparse. Envía la salida mediante una tubería a jq para extraer los campos.

¿Por qué veo dos conjuntos de encabezados cuando utilizo un proxy?

Para conexiones HTTPS a través de un proxy HTTP, curl envía primero un CONNECT para abrir un túnel, y la respuesta del proxy a esa solicitud aparece antes que la del destino. Utiliza --suppress-connect-headers para ocultarla, o %{http_connect} para leer el código de estado del proxy por separado del del destino.

¿Cómo puedo ver los encabezados de cada redireccionamiento?

Añade -L para que curl siga los redireccionamientos, y utiliza -D - o -i: curl muestra los encabezados de cada respuesta de la cadena, un bloque por salto. %{num_redirects} y %{url_effective} te proporcionan el recuento y la URL final en una sola línea.

¿Revelan los encabezados de respuesta si estoy siendo bloqueado?

A menudo, sí, y de forma más fiable que el cuerpo de la respuesta. Un 429 con Retry-After indica un límite de velocidad. Un 403 que incluya encabezados de un proveedor de seguridad es una capa de protección. Un 200 con Content-Type: text/html en un punto final de API es una página de autenticación o de inicio de sesión. Cada uno implica una solución diferente, y solo los encabezados permiten distinguirlos.

Conclusión

Cuatro opciones y una trampa habitual. -i para la inspección diaria, -D - cuando quieras que los encabezados estén separados del cuerpo, -v cuando necesites ver tanto lo que has enviado como lo que has recibido, y -I solo para comprobaciones rápidas de actividad —ya que envía un HEAD, y los servidores pueden responder a un HEAD de forma diferente a como lo harían con un GET.

La opción que merece la pena adoptar, si te quedas con algo de todo esto, es %{header_json}. Cualquier script que actualmente analice el texto de los encabezados con una expresión regular debería utilizarla en su lugar: nombres en minúsculas, matrices para los encabezados repetidos y una salida que jq pueda leer. Combinada con %{response_code}, %{num_redirects} y %{proxy_used}, convierte la inspección de los encabezados en algo que puedes verificar de forma sistemática en lugar de a ojo.

Y cuando una solicitud falla, lee los encabezados antes de cambiar nada. El código de estado, Retry-After, Content-Type y cualquier encabezado del proveedor que aparezca entre ellos suelen indicar el problema de forma clara —lo cual es mejor que ir probando configuraciones hasta que algo funcione, y solo lleva unos diez segundos—.