cURL con proxy: cómo configurar proxies HTTP y SOCKS5

Publicado:

16 min de lectura

Actualizado:

PXNET
Autor: PXNET
Marco de esquinas en cruz: logo de Proxynet, un aspa y el de cURL, sobre filas de IP tenues; etiqueta INTEGRATION

Tienes la dirección de un proxy que te dio tu proveedor y quieres saber si funciona antes de ponerla en un scraper, una tarea cron o un pipeline de CI. cURL es la comprobación más rápida: un solo comando envía una petición a través del proxy e imprime la dirección IP que ve el sitio de destino, y ese mismo comando pasa después tal cual a un script de shell.

Este artículo cubre la opción -x, las credenciales, SOCKS5, cómo fijar el proxy para todos los comandos, un script de descarga con reintentos y los mensajes de error exactos. Todos los comandos se ejecutaron con curl 8.21 contra un proxy de prueba local; las opciones están documentadas en la página de manual de curl.

¿Qué es cURL?

cURL (se pronuncia «kerl») es una herramienta de línea de comandos para transferir datos mediante URL: descarga páginas y archivos, envía formularios y peticiones a API, y muestra o guarda la respuesta. El trabajo lo hace libcurl, una biblioteca de transferencia que también usan PHP y otros lenguajes.

Como todo comando, cURL sigue una sintaxis fija:

bash
curl [opciones] [URL]

La parte de «opciones» indica qué debe hacer el comando, y de estos parámetros, también llamados flags, hay más de 250. -o pagina.html guarda la respuesta en un archivo, -I pide solo las cabeceras, -L sigue las redirecciones y -x usa un proxy. Todas las opciones distinguen mayúsculas de minúsculas: -x fija un proxy, mientras que -X fija el método HTTP.

cURL viene incluido en macOS, en Windows 10 y 11 como curl.exe y en la mayoría de las distribuciones Linux; en las imágenes de contenedor mínimas puede que tengas que instalarlo (apt install curl en Debian y Ubuntu). Ejecuta curl --version: si la línea Features: contiene HTTPS-proxy, tu compilación también puede conectarse a un proxy por TLS.

¿Qué protocolos admite cURL?

cURL solo trabaja con protocolos que se pueden escribir como URL; los protocolos de red que no se direccionan mediante una URL no son compatibles. La versión actual incluye DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, MQTTS, POP3, POP3S, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS y WSS. curl --version muestra lo que admite tu compilación; RTMP, que aparece en listas antiguas, ya no está.

Sin esquema, cURL deduce el protocolo del nombre de host (ftp.example.com significa FTP; la mayoría de los nombres, HTTP). Si ese protocolo falla, no prueba otro por su cuenta. Para los proxies esto importa en un punto: un proxy HTTP transporta HTTP y HTTPS; los demás protocolos solo pasan por un túnel CONNECT (-p) y solo si el proxy permite ese puerto. SOCKS5 transporta cualquier conexión TCP, así que FTP o SMTP a través de un proxy suele significar SOCKS5.

¿Por qué usar cURL con un proxy?

  • Pasos visibles. -v muestra la conexión con el proxy, la petición CONNECT y las dos respuestas, así que ves en qué punto falla una petición.
  • Todos los tipos de proxy en una sola opción. HTTP, HTTPS, SOCKS4, SOCKS4a, SOCKS5 y SOCKS5h pasan por -x.
  • Scripts. Los códigos de salida, --retry, los tiempos de espera y --write-out permiten que un script de shell gestione los fallos, y las funciones curl_* de PHP aceptan las mismas opciones.
  • Muchas URL en un comando. Puedes indicar varias variantes de una URL en un solo comando con corchetes o llaves: page[1-20].html o {a,b,c} se expanden en varias peticiones, todas por el mismo proxy.

Usos típicos: comprobar el país de una IP de salida antes de una tarea de extracción de datos, probar destinos de seguimiento de precios desde otro mercado y descargas en tareas programadas. Los equivalentes en Node.js están en cURL en JavaScript: fetch, Axios y proxy, y los de PHP en Web scraping con PHP.

¿Cómo envía cURL una petición a través de un proxy?

  1. cURL se conecta al proxy, no al destino.
  2. Destino HTTP, proxy HTTP: cURL envía la petición con la URL completa (GET http://example.com/ HTTP/1.1). El proxy puede leerla.
  3. Destino HTTPS, proxy HTTP: cURL envía CONNECT example.com:443, con una cabecera Proxy-Authorization si indicaste credenciales. Cuando el proxy responde 200, el TLS con el destino va dentro de ese túnel, así que el proxy solo ve el host y el puerto. El método CONNECT está definido en la RFC 9110.
  4. Proxy SOCKS5: cURL inicia sesión (con usuario y contraseña, si los indicaste) y pide al proxy que se conecte al destino (RFC 1928). Con socks5:// envía una IP que resolvió él mismo; con socks5h:// envía el nombre de host.
  5. El destino responde a la IP del proxy. Tu IP no le llega, pero tus consultas DNS salen por tu propia conexión si cURL resuelve los nombres localmente.

Cómo configurar un proxy en cURL: la opción -x

curl --help proxy muestra todas las opciones de proxy. La principal es esta:

text
 -x, --proxy <[protocol://]host[:port]>  Use this proxy

-x y --proxy son la misma opción, en forma corta y larga:

bash
curl -x "http://user:pass@pr.proxynet.io:8000" https://httpbin.org/ip

httpbin.org/ip devuelve la IP de origen de la petición: si el proxy funciona, ahí verás la IP de salida del proxy y no la tuya.

  • Sin esquema, el proxy es HTTP. -x "user:pass@pr.proxynet.io:8000" se comporta igual que la forma con http://.
  • Escribe siempre el puerto. Sin él, cURL elige uno por defecto: en nuestra prueba con curl 8.21, el 80 para http://, el 443 para https:// y el 1080 para SOCKS (el manual sigue diciendo 1080). Es poco probable que alguno coincida con el puerto de tu proveedor, así que la conexión falla o agota el tiempo de espera.
  • Pon la dirección entre comillas dobles. Es la forma recomendada para que el intérprete de comandos no interprete &, ? o ! dentro de la URL.
  • -x vale para un solo comando y tiene prioridad sobre las variables de entorno del proxy. El siguiente comando vuelve a salir directamente.

En los productos residenciales y móviles de Proxynet, un mismo gateway atiende HTTP y SOCKS5 en puertos distintos, y el Generador de endpoints del panel construye el nombre de usuario con el país, la ciudad y la sesión que elijas.

¿Cómo se usa cURL con un proxy HTTP o HTTPS?

Un proxy HTTP transporta los dos tipos de destino:

bash
# Destino HTTPS: túnel CONNECT, la página sigue cifrada
curl -x "http://user:pass@pr.proxynet.io:8000" https://httpbin.org/ip

# Destino HTTP: el proxy reenvía la petición en claro
curl -x "http://user:pass@pr.proxynet.io:8000" http://httpbin.org/ip

Un proxy HTTPS (https://) cifra además la conexión con el propio proxy. Úsalo solo si el puerto habla TLS; https:// apuntando a un puerto HTTP normal falla en el handshake (SEC_E_INVALID_TOKEN en Windows, normalmente wrong version number con OpenSSL).

Las opciones de certificado se reparten entre las dos conexiones:

  • -k (--insecure) omite la comprobación del certificado solo en el sitio de destino. Con un destino http:// no hace nada.
  • --proxy-insecure omite la comprobación del certificado de un proxy HTTPS. --proxy-cacert archivo.pem es más seguro: confía en la CA del proxy de una empresa sin desactivar las comprobaciones.

Si aparecen errores de certificado SSL, deja -k para pruebas rápidas y no lo uses nunca en scripts que envían tokens. Para protocolos que no son HTTP a través de un proxy HTTP, añade -p (--proxytunnel). En la página de Proxies HTTPS verás cómo pasa el tráfico cifrado por un proxy.

¿Cómo se pasan el usuario y la contraseña del proxy?

Las dos formas envían la misma cabecera Proxy-Authorization:

bash
curl -x "http://user:pass@pr.proxynet.io:8000" https://httpbin.org/ip
curl -x "http://pr.proxynet.io:8000" -U "user:pass" https://httpbin.org/ip

Dentro de la dirección, los caracteres especiales de la contraseña deben ir codificados con porcentaje: @ como %40, : como %3A y # como %23. cURL los decodifica antes de enviarlos; en nuestra prueba, p%40ss llegó al proxy como p@ss. Con -U (--proxy-user) no hace falta codificar nada. La autenticación básica es la predeterminada; los proxies corporativos pueden necesitar --proxy-ntlm, --proxy-digest o --proxy-anyauth.

Las contraseñas escritas en la línea de comandos quedan en el historial de la shell. En scripts, léelas de un archivo de configuración privado (-K archivo) o usa una lista de IP autorizadas (Proxynet acepta hasta 10 IP). Autenticación de proxy: user:pass o lista blanca de IP compara los dos métodos y explica el error 407.

¿Cómo se usa cURL con un proxy SOCKS5?

Escribe la versión de SOCKS como esquema:

bash
curl -x "socks5h://user:pass@pr.proxynet.io:1080" https://httpbin.org/ip
EsquemaQuién resuelve el nombre de hostUsuario y contraseñaPara qué usarlo
http://El proxySíWeb scraping, API, la mayoría de las herramientas
https://El proxySíUn puerto de proxy que habla TLS
socks5h://El proxySíSOCKS5 con un DNS acorde a la ubicación
socks5://Tu equipoSíDestinos que solo tu DNS puede resolver
socks4a://El proxySolo ID de usuarioServidores SOCKS4 antiguos
socks4://Tu equipoSolo ID de usuarioServidores SOCKS4 antiguos

Con socks5://, tu servidor DNS ve cada host que visitas y los sitios que tienen en cuenta la ubicación responden según la tuya; socks5h:// evita las dos cosas, y por eso suele ser la opción recomendable para web scraping (Fugas de WebRTC y DNS explica por qué importa). La opción antigua --socks5-hostname host:puerto equivale a socks5h://, con las credenciales en -U; --socks5, en cambio, equivale a socks5://.

Para las diferencias entre protocolos, consulta Diferencia entre SOCKS y HTTP: ¿cuál elegir? y Proxies SOCKS5: cómo funcionan y en qué se diferencian. Los Proxies SOCKS5 de Proxynet funcionan en su propio puerto, junto al puerto HTTP.

¿Cómo se configura un proxy para todos los comandos de cURL?

MétodoAlcanceEjemplo
-xUn comandocurl -x "http://user:pass@host:port" URL
Variable de entornoLa sesión de la shellexport https_proxy="http://user:pass@host:port"
.curlrcCada ejecución de ese usuarioproxy = "http://host:port"

Variables de entorno. cURL lee http_proxy para destinos HTTP, https_proxy o HTTPS_PROXY para HTTPS y ALL_PROXY como alternativa general. http_proxy solo funciona en minúsculas (una protección para programas CGI), así que HTTP_PROXY se ignora en Linux y macOS. En PowerShell: $env:HTTPS_PROXY = "http://user:pass@host:port". wget, pip y git leen las mismas variables; consulta Proxy con wget: comandos y ejemplos y la página de everything curl sobre las variables de proxy.

El archivo de configuración. cURL lee ~/.curlrc (en Windows, %USERPROFILE%\.curlrc o _curlrc) antes de cada ejecución:

text
proxy = "http://pr.proxynet.io:8000"
proxy-user = "user:pass"

curl -q URL, con -q en primer lugar, lo omite en esa ejecución.

Excepciones. --noproxy "localhost,.internal.example" o la variable NO_PROXY hacen que esos hosts se conecten directamente. Un nombre incluye también sus subdominios, los rangos CIDR como 192.168.0.0/16 funcionan y el único comodín es un * solo. NO_PROXY se aplica incluso con -x.

cURL no tiene motor de JavaScript, así que no puede ejecutar archivos PAC. Si tu red usa uno, léelo (¿Qué es un archivo PAC?) y pasa con -x el proxy que devuelve.

¿Cómo compruebas que cURL está usando el proxy?

Ejecuta curl https://api.ipify.org sin -x y con -x: si la segunda vez obtienes otra dirección, en el país esperado, el proxy funciona. Una petición HTTPS correcta a través de un proxy HTTP muestra estas líneas con -v:

text
* Establishing HTTP proxy tunnel to httpbin.org:443
> CONNECT httpbin.org:443 HTTP/1.1
> Proxy-Authorization: Basic dXNlcjpwYXNz
< HTTP/1.1 200 Connection Established
* CONNECT tunnel established, response 200

El valor de Proxy-Authorization solo está codificado en Base64, no cifrado; bórralo antes de compartir la salida. En scripts, -w imprime el resultado en una línea:

bash
curl -s -o /dev/null -x "http://user:pass@pr.proxynet.io:8000" \
  -w "%{http_code} connect=%{http_connect} proxy_used=%{proxy_used}\n" https://httpbin.org/ip

http_connect es la respuesta del proxy al CONNECT; proxy_used (curl 8.7 o posterior) vale 1 cuando se usó un proxy. Para comprobar la ubicación, la velocidad y las fugas, consulta ¿Funciona tu proxy? Cómo probar un proxy.

Ejemplo: descargar una lista de URL a través de un proxy con reintentos

Este script descarga las URL de urls.txt de cuatro en cuatro a través del proxy, reintenta los fallos temporales e imprime el código de estado y la duración de cada una. Necesita cURL y una shell POSIX (Linux, macOS o Git Bash):

bash
#!/usr/bin/env bash
# fetch.sh: descarga cada URL de urls.txt a través del proxy, 4 a la vez
set -u
PROXY="${PROXY:-http://user:pass@pr.proxynet.io:8000}"

sed 's/^/url = /' urls.txt | curl \
  --parallel --parallel-max 4 \
  --proxy "$PROXY" \
  --connect-timeout 10 --max-time 30 \
  --retry 3 --retry-connrefused \
  --fail --silent --show-error \
  --create-dirs --output-dir pages --remote-name-all \
  --write-out "%{http_code} %{time_total}s %{url}\n" \
  --config -
  • --config - lee las líneas url = … que genera sed y debe ir al final, porque --remote-name-all solo se aplica a las URL añadidas después.
  • --retry 3 reintenta los tiempos de espera agotados y las respuestas HTTP 408, 429, 500, 502, 503, 504, 522 y 524; espera 1, 2 y 4 segundos y respeta la cabecera Retry-After.
  • --max-time corta una transferencia atascada; --fail convierte los errores HTTP en el código de salida 22.
  • Mantén bajo --parallel-max cuando todas las URL son del mismo sitio; demasiadas peticiones en paralelo pueden provocar respuestas 429.

En nuestra prueba se guardaron cuatro páginas y una URL que devolvía 503 se reintentó tres veces antes de que el script terminara con el código 22.

Repite una petición contra api.ipify.org para ver si tu gateway rota: un gateway rotativo devuelve una IP nueva cada vez, y una sesión fija mantiene la misma IP entre 1 y 60 minutos en Proxynet. Qué es la rotación de IP y cómo funciona explica cuándo conviene cada modo; los Proxies residenciales admiten los dos. Para descargas masivas desde sitios que no bloquean las IP de centro de datos, suelen bastar los Proxies de centro de datos.

Errores comunes de cURL con proxy y cómo solucionarlos

Los mensajes aparecen tal como los imprimió curl 8.21 en nuestras pruebas:

  • curl: (5) Could not resolve proxy: … El nombre de host del proxy está mal: revisa la ortografía y que no sobren comillas.
  • curl: (7) Failed to connect to … over proxy … Nada responde en ese puerto (o cURL recurrió a un puerto por defecto porque no se indicó ninguno), o un firewall lo bloquea.
  • curl: (7) CONNECT tunnel failed, response 407 Credenciales incorrectas, caracteres especiales sin codificar o una IP que no está en la lista de IP autorizadas. Las versiones antiguas imprimen curl: (56) Received HTTP code 407 from proxy after CONNECT; con destinos http:// simplemente recibes el estado 407. Consulta Códigos de estado HTTP en web scraping.
  • curl: (56) Proxy CONNECT aborted El proxy cerró la conexión; en nuestra prueba, una dirección http:// apuntaba a un puerto SOCKS5.
  • curl: (97) Received invalid version in initial SOCKS5 response. Una dirección socks5:// apunta a un puerto HTTP. User was rejected by the SOCKS5 server significa que las credenciales SOCKS son incorrectas.
  • curl: (28) Connection timed out after … milliseconds No hubo respuesta a tiempo; consulta El servidor proxy no responde.
  • curl: (35) … o SSL_ERROR_SYSCALL Falló el handshake TLS: https:// en un puerto de proxy sin TLS, o un dispositivo de red que corta las conexiones TLS.
  • curl: (60) SSL certificate problem: unable to get local issuer certificate Suele ser un proxy corporativo que inspecciona el tráfico TLS. Instala su certificado de CA en lugar de usar -k.
  • El proxy se ignora. Busca NO_PROXY, un HTTP_PROXY en mayúsculas u otro .curlrc; -v muestra a qué dirección intenta conectarse cURL primero. La versión en Python de estos fallos está en Max Retries Exceeded With URL: qué es y cómo solucionarlo.

Guía de decisión

NecesidadRecomendación
Probar un proxy nuevo una vezcurl -x "http://user:pass@host:port" https://httpbin.org/ip
La contraseña contiene @, : o #-U "user:pass", o codificarla con porcentaje
DNS resuelto en el proxysocks5h://, no socks5://
FTP, SMTP u otro protocolo que no es HTTPSOCKS5, o -p con un proxy HTTP
Proxy para una sesión de shellexport https_proxy=… y http_proxy en minúsculas
Proxy para todas las ejecucionesproxy = "…" en ~/.curlrc
Sin contraseñas en los scriptsLista de IP autorizadas en el panel
La misma IP para un flujo de inicio de sesiónSesión fija desde el Generador de endpoints

Preguntas frecuentes

¿cURL usa la configuración de proxy del sistema en Windows o macOS?

No. cURL solo toma el proxy de -x, de las variables de entorno y de .curlrc. Un proxy definido en la Configuración de Windows o en los Ajustes del Sistema de macOS no le afecta.

¿Cómo hago que cURL ignore el proxy en una sola petición?

Añade --noproxy "*" o -x "". Cualquiera de las dos opciones envía ese comando directamente aunque https_proxy o .curlrc definan un proxy.

¿Por qué falla mi comando de cURL con proxy en PowerShell?

En Windows PowerShell 5.1, curl es un alias de Invoke-WebRequest, que no conoce -x. Escribe curl.exe para ejecutar el cURL real. PowerShell 7 ya no tiene ese alias.

¿Qué diferencia hay entre socks5 y socks5h en cURL?

Con socks5://, tu equipo resuelve el nombre de host; con socks5h:// lo resuelve el proxy, así que el DNS coincide con la ubicación del proxy.

¿Puedo usar un proxy con cURL en PHP?

Sí. Las funciones cURL de PHP usan libcurl: CURLOPT_PROXY fija la dirección, CURLOPT_PROXYUSERPWD las credenciales y CURLOPT_PROXYTYPE el tipo de SOCKS. Tienes ejemplos en Web scraping con PHP: cURL, Guzzle y uso de proxy.

¿Puede cURL rotar el proxy en cada petición?

cURL usa un proxy por comando. Un gateway rotativo asigna una IP de salida nueva por conexión, así que un bucle de comandos obtiene una IP distinta cada vez. Varias URL en un mismo comando suelen reutilizar una conexión y comparten su IP.

En resumen

Para usar cURL con un proxy, añade -x con la dirección completa: esquema, credenciales, host y puerto. Usa http:// para la mayoría de los trabajos y socks5h:// para SOCKS5 con DNS remoto, pon el proxy en https_proxy o en .curlrc cuando todos los comandos lo necesiten y deja -k para las pruebas. Cuando un comando falla, el código de salida y la salida de -v indican si el problema está en la dirección, en las credenciales o en el destino. Si buscas endpoints residenciales, móviles y SOCKS5 que funcionen con estos comandos, consulta los proxies de Proxynet.