¿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.
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.
# WSL (Ubuntu)
sudo apt install curl
Petición GET
curl https://example.com
El cuerpo de la respuesta se imprime en stdout. Para guardar en un archivo:
# 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
# Solo cabeceras (petición HEAD)
curl -I https://example.com
# Cabeceras + cuerpo juntos
curl -i https://example.com
Modo verbose (depuración)
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
# 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ón | Qué hace |
|---|---|
-o ARCHIVO | Guardar salida en ARCHIVO |
-O | Guardar usando el nombre de archivo de la URL |
-I / --head | Obtener solo cabeceras (petición HEAD) |
-i | Incluir cabeceras de respuesta en la salida |
-v / --verbose | Mostrar petición/respuesta completa (incluyendo TLS) |
-s / --silent | Suprimir progreso y errores |
-L / --location | Seguir redirecciones |
-X MÉTODO | Especificar método HTTP (POST, PUT, DELETE, etc.) |
-H "Cabecera: Valor" | Añadir cabecera personalizada |
-d "datos" | Enviar datos POST |
-u usuario:contraseña | Autenticación básica |
-k / --insecure | Omitir verificación de certificado SSL |
-c ARCHIVO | Guardar cookies en ARCHIVO |
-b ARCHIVO | Enviar cookies desde ARCHIVO |
--limit-rate VELOCIDAD | Limitar velocidad de transferencia (ej. --limit-rate 1M) |
-w "formato" | Formato de salida personalizado para info de respuesta |
--connect-timeout SEG | Timeout 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:
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:
curl -s \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
https://api.example.com/me
Actualizar un recurso con PUT:
curl -s -X PUT \
-H "Content-Type: application/json" \
-d '{"name": "Alice Updated"}' \
https://api.example.com/users/123
Eliminar un recurso:
curl -s -X DELETE \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
https://api.example.com/users/123
Canalizar a jq para salida formateada:
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:
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:
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:
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:
curl -F "file=@photo.jpg" https://api.example.com/upload
Subir múltiples archivos a la vez:
curl -F "file1=@document.pdf" \
-F "file2=@image.png" \
-F "description=Monthly report" \
https://api.example.com/upload
Especificar el tipo MIME explícitamente:
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.
# 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:
# 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.
#!/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
#!/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
# 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
# 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:
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:-oo-O - Llamadas API:
-X POST -H "Content-Type: application/json" -d '{...}' - Depuración:
-vpara traza completa,-wpara tiempos de respuesta - En scripts: siempre usa
-s -fpara modo silencioso + detección de errores - Credenciales: usa
.netrco 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.