32blogby StudioMitsu

Guía completa de curl: llamadas API, depuración y más

Aprende curl desde lo básico hasta lo avanzado: peticiones API, cabeceras, autenticación, transferencia de archivos y scripting.

10 min read
Contenido

¿Necesitas probar un endpoint de API desde la terminal? ¿Depurar una cadena de redirecciones? ¿Lanzar un webhook desde un script de CI?

curl es la herramienta para todo eso. Maneja prácticamente cualquier operación HTTP que puedas imaginar — GET, POST, subida de archivos, gestión de cookies, autenticación, tiempos de respuesta — todo desde un solo comando. Viene preinstalado en Linux y macOS, y funciona en Windows a través de WSL o Git Bash.

Esta guía cubre todo, desde lo básico hasta scripting del mundo real, con ejemplos listos para ejecutar.

¿Qué es curl?

curl (abreviatura de "Client URL") es una herramienta de línea de comandos para transferir datos usando URLs. Soporta más de 20 protocolos incluyendo HTTP, HTTPS, FTP, SFTP y SCP.

Características clave:

  • Navaja suiza de HTTP: soporta GET, POST, PUT, DELETE, PATCH y todos los demás métodos
  • Salida flexible: obtén solo las cabeceras, solo el cuerpo, mide tiempos de respuesta o captura todo
  • libcurl: también disponible como biblioteca en C, utilizada por Python, PHP, Ruby y muchos otros lenguajes internamente
  • Multiplataforma: funciona en Linux, macOS y Windows

Cómo se compara con wget: wget está construido para descargar archivos — destaca en descargas recursivas y espejos de sitios. curl es la herramienta HTTP de propósito general — brilla en llamadas a API, inspección de respuestas y creación de peticiones complejas.

Para una comparación detallada, consulta la Guía completa de wget.

Uso básico

Verificar la instalación

Verifica que curl está disponible en tu sistema.

bash
curl --version

Si usas WSL (Windows Subsystem for Linux), la versión de Linux de curl está disponible. Git Bash también incluye curl. Ten en cuenta que el curl de PowerShell es un alias de Invoke-WebRequest — no es la misma herramienta.

bash
# WSL (Ubuntu)
sudo apt install curl

Petición GET

bash
curl https://example.com

El cuerpo de la respuesta se imprime en stdout. Para guardar en un archivo:

bash
# Guardar con un nombre personalizado
curl -o output.html https://example.com

# Guardar usando el nombre del archivo de la URL
curl -O https://example.com/file.zip

Inspeccionar cabeceras de respuesta

bash
# Solo cabeceras (petición HEAD)
curl -I https://example.com

# Cabeceras + cuerpo juntos
curl -i https://example.com

Modo verbose (depuración)

bash
curl -v https://example.com

Esto muestra la conversación completa: handshake TLS, cabeceras de petición, cabeceras de respuesta y cuerpo. Esencial para diagnosticar problemas de conexión.

Modo silencioso

bash
# Suprimir barra de progreso y mensajes de error
curl -s https://example.com

# Mostrar progreso como caracteres # (útil para archivos grandes)
curl -# -O https://example.com/file.zip

Referencia de opciones comunes

OpciónQué hace
-o ARCHIVOGuardar salida en ARCHIVO
-OGuardar usando el nombre de archivo de la URL
-I / --headObtener solo cabeceras (petición HEAD)
-iIncluir cabeceras de respuesta en la salida
-v / --verboseMostrar petición/respuesta completa (incluyendo TLS)
-s / --silentSuprimir progreso y errores
-L / --locationSeguir redirecciones
-X MÉTODOEspecificar método HTTP (POST, PUT, DELETE, etc.)
-H "Cabecera: Valor"Añadir cabecera personalizada
-d "datos"Enviar datos POST
-u usuario:contraseñaAutenticación básica
-k / --insecureOmitir verificación de certificado SSL
-c ARCHIVOGuardar cookies en ARCHIVO
-b ARCHIVOEnviar cookies desde ARCHIVO
--limit-rate VELOCIDADLimitar velocidad de transferencia (ej. --limit-rate 1M)
-w "formato"Formato de salida personalizado para info de respuesta
--connect-timeout SEGTimeout de conexión en segundos
-C -Reanudar descarga interrumpida
-F "clave=@archivo"Subir archivo como datos de formulario

Casos de uso reales

Llamadas REST API (GET / POST / PUT / DELETE)

Los patrones que más usarás al probar APIs.

Enviar datos JSON con POST:

bash
curl -s -X POST \
  -H "Content-Type: application/json" \
  -d '{"name": "Alice", "email": "alice@example.com"}' \
  https://api.example.com/users

Autenticarse con un token Bearer:

bash
curl -s \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
  https://api.example.com/me

Actualizar un recurso con PUT:

bash
curl -s -X PUT \
  -H "Content-Type: application/json" \
  -d '{"name": "Alice Updated"}' \
  https://api.example.com/users/123

Eliminar un recurso:

bash
curl -s -X DELETE \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
  https://api.example.com/users/123

Canalizar a jq para salida formateada:

bash
curl -s https://api.example.com/users | jq '.data[] | {id, name}'

Para más sobre procesamiento de salida JSON, consulta la Guía completa de jq.

Depuración de cabeceras y redirecciones

Inspeccionar el handshake TLS completo y cabeceras:

bash
curl -v https://example.com 2>&1 | head -30

La salida verbose va a stderr, así que 2>&1 la fusiona con stdout para canalizar a head.

Medir el desglose del tiempo de respuesta:

bash
curl -o /dev/null -s -w "DNS: %{time_namelookup}s\nConnect: %{time_connect}s\nTLS: %{time_appconnect}s\nTotal: %{time_total}s\n" https://example.com

Esto muestra la resolución DNS, conexión TCP, handshake TLS y tiempo total por separado — ideal para identificar cuellos de botella de rendimiento.

Trazar la cadena de redirecciones:

bash
curl -s -L -o /dev/null -w "URL final: %{url_effective}\nRedirecciones: %{num_redirects}\n" https://example.com

Subida de archivos

Subir un archivo como datos de formulario:

bash
curl -F "file=@photo.jpg" https://api.example.com/upload

Subir múltiples archivos a la vez:

bash
curl -F "file1=@document.pdf" \
     -F "file2=@image.png" \
     -F "description=Monthly report" \
     https://api.example.com/upload

Especificar el tipo MIME explícitamente:

bash
curl -F "file=@data.csv;type=text/csv" https://api.example.com/import

Gestión de cookies

Mantener sesiones entre peticiones, como después de iniciar sesión.

bash
# Paso 1: Iniciar sesión y guardar cookies
curl -c cookies.txt \
  -d "username=admin&password=secret" \
  https://example.com/login

# Paso 2: Usar cookies guardadas para peticiones posteriores
curl -b cookies.txt https://example.com/dashboard

# Paso 3: Enviar cookies existentes y guardar las nuevas
curl -b cookies.txt -c cookies.txt https://example.com/profile

Reanudar descargas interrumpidas

Cuando una descarga grande se corta:

bash
# Descarga original (interrumpida por Ctrl+C, caída de red, etc.)
curl -O https://example.com/largefile.iso

# Reanudar desde donde se quedó
curl -C - -O https://example.com/largefile.iso

El flag -C - le dice a curl que auto-detecte el tamaño actual del archivo y solicite solo los bytes restantes.

Ejemplos de scripting

Verificador de salud de APIs

Un script que comprueba el estado de múltiples endpoints e informa de fallos.

bash
#!/bin/bash

ENDPOINTS=(
  "https://api.example.com/health"
  "https://api.example.com/v2/status"
  "https://cdn.example.com/ping"
  "https://auth.example.com/health"
)

echo "=== Verificación de Salud de API ==="
echo ""

FAILED=0

for URL in "${ENDPOINTS[@]}"; do
  STATUS=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 --max-time 10 "$URL")

  if [ "$STATUS" -ge 200 ] && [ "$STATUS" -lt 300 ]; then
    echo "[OK]   $STATUS  $URL"
  else
    echo "[FAIL] $STATUS  $URL"
    FAILED=$((FAILED + 1))
  fi
done

echo ""
echo "Resultados: $((${#ENDPOINTS[@]} - FAILED))/${#ENDPOINTS[@]} pasaron"

if [ "$FAILED" -gt 0 ]; then
  exit 1
fi

Descargador por lotes con reintentos

bash
#!/bin/bash

URLS=(
  "https://example.com/data/january.csv"
  "https://example.com/data/february.csv"
  "https://example.com/data/march.csv"
)

DEST_DIR="./downloads"
MAX_RETRIES=3

mkdir -p "$DEST_DIR"

for URL in "${URLS[@]}"; do
  FILENAME=$(basename "$URL")
  ATTEMPT=1

  while [ "$ATTEMPT" -le "$MAX_RETRIES" ]; do
    echo "Descargando $FILENAME (intento $ATTEMPT/$MAX_RETRIES)..."

    if curl -s -f -L -o "${DEST_DIR}/${FILENAME}" --connect-timeout 10 --max-time 120 "$URL"; then
      echo "  OK: $FILENAME"
      break
    else
      echo "  FALLÓ: $FILENAME"
      ATTEMPT=$((ATTEMPT + 1))

      if [ "$ATTEMPT" -le "$MAX_RETRIES" ]; then
        echo "  Reintentando en 5 segundos..."
        sleep 5
      fi
    fi
  done

  if [ "$ATTEMPT" -gt "$MAX_RETRIES" ]; then
    echo "  ABANDONADO: $FILENAME después de $MAX_RETRIES intentos"
  fi
done

echo "Hecho."

Consideraciones de seguridad

Correcciones de seguridad en curl 8.18.0

curl 8.18.0 (lanzado el 7 de enero de 2026) incluyó 6 correcciones de seguridad, 3 de las cuales fueron descubiertas por herramientas de IA — una primicia para el proyecto curl en términos de descubrimiento de vulnerabilidades asistido por IA oficialmente reconocido.

Por separado, el programa de bug bounty de curl terminó a finales de enero de 2026. El programa se vio desbordado por una avalancha de informes de baja calidad generados por IA que consumían recursos de triaje desproporcionados.

Nunca uses -k en producción

bash
# Solo para entornos de prueba con certificados autofirmados
curl -k https://self-signed.example.com/api

-k (--insecure) desactiva la verificación de certificados SSL. Está bien para probar con certificados autofirmados, pero usarlo en producción o scripts automatizados te expone a ataques man-in-the-middle.

Mantén las credenciales fuera de los comandos

bash
# Mal: contraseña visible en el historial del shell
curl -u admin:P@ssw0rd https://api.example.com/admin

# Bien: usar .netrc
echo "machine api.example.com login admin password P@ssw0rd" > ~/.netrc
chmod 600 ~/.netrc
curl -n https://api.example.com/admin

Siempre establece los permisos de .netrc a 600 para que otros usuarios no puedan leerlo.

Las variables de entorno también funcionan:

bash
curl -u "admin:${API_PASSWORD}" https://api.example.com/admin

Conclusión

curl es la navaja suiza de la comunicación HTTP. Ya sea que estés probando APIs, depurando conexiones, subiendo archivos o escribiendo flujos de trabajo automatizados, es la herramienta de referencia.

Referencia rápida de los patrones más útiles:

  • Petición básica: curl URL. Guardar en archivo: -o o -O
  • Llamadas API: -X POST -H "Content-Type: application/json" -d '{...}'
  • Depuración: -v para traza completa, -w para tiempos de respuesta
  • En scripts: siempre usa -s -f para modo silencioso + detección de errores
  • Credenciales: usa .netrc o variables de entorno, nunca las pongas directamente en comandos

Si tu necesidad principal es descargar archivos, wget es más sencillo para esa tarea. Para llamadas API, inspección de respuestas y trabajo HTTP complejo, curl es la elección clara. Usa ambos — cada uno tiene sus fortalezas.

Para más herramientas CLI y cómo trabajan juntas, consulta el Kit de herramientas CLI.