Usar un proxy en un script solo requiere unas pocas líneas, si conoces la sintaxis de cada herramienta y las trampas que hacen perder horas: una clave mal elegida, una contraseña mal codificada, un tiempo de espera olvidado. Aquí tienes ejemplos completos para cURL, Python y Node.js, buenas prácticas de producción y soluciones a los errores habituales.
Antes de empezar: la dirección del proxy
Un acceso proxy se resume en cuatro datos: host, puerto, usuario y contraseña. Airproxy los entrega con el formato host:puerto:usuario:contraseña, pero la mayoría de las bibliotecas esperan una URL:
# Línea entregada
host.ejemplo:8080:usuario:contrasena
# URL para un proxy HTTP(S)
http://usuario:contrasena@host.ejemplo:8080
# URL para un proxy SOCKS5, con resolución DNS en el proxy
socks5h://usuario:contrasena@host.ejemplo:8080
El prefijo indica el protocolo del proxy, no el de la web. Un proxy HTTP transporta sin problema el tráfico HTTPS: tu herramienta le pide que abra un túnel (método CONNECT) y el cifrado se negocia directamente con la web. Así que mantén http://, incluso para páginas en https://. Para elegir entre los dos protocolos, consulta nuestra comparativa proxy HTTP o SOCKS5.
cURL: comprobar un acceso en una línea
El servicio api.ipify.org, usado en todos los ejemplos, devuelve la IP que lo ha consultado: debes ver la del proxy, no la tuya.
# Proxy HTTP, credenciales en la URL
curl -x "http://usuario:contrasena@host.ejemplo:8080" https://api.ipify.org
# Lo mismo, con las credenciales aparte mediante -U
curl -x "http://host.ejemplo:8080" -U "usuario:contrasena" https://api.ipify.org
# SOCKS5, el proxy resuelve los nombres de dominio
curl --socks5-hostname host.ejemplo:8080 -U "usuario:contrasena" https://api.ipify.org
# Equivalente con una sola URL
curl -x "socks5h://usuario:contrasena@host.ejemplo:8080" https://api.ipify.org
--socks5-hostname, igual que el prefijo socks5h://, deja que el proxy resuelva los nombres de dominio, algo que no hacen --socks5 ni socks5://. En Windows PowerShell, escribe curl.exe: ahí, curl es un alias de otro comando.
Python: requests y httpx
requests
La biblioteca requests espera un diccionario que asocia un proxy a cada tipo de dirección visitada:
import requests
proxy = "http://usuario:contrasena@host.ejemplo:8080"
proxies = {"http": proxy, "https": proxy}
r = requests.get("https://api.ipify.org", proxies=proxies, timeout=10)
print(r.text) # debe mostrar la IP del proxy
Trampa clásica: la clave "https" se refiere a las webs en https://, no al protocolo del proxy, cuya dirección sigue siendo http://. Y sin timeout, requests puede esperar indefinidamente.
Para SOCKS5, instala la dependencia opcional y cambia el prefijo:
pip install "requests[socks]"
proxy = "socks5h://usuario:contrasena@host.ejemplo:8080"
proxies = {"http": proxy, "https": proxy}
Con socks5://, requests resolvería los nombres en tu equipo: una fuga de DNS que nuestra guía sobre cómo probar un proxy te enseña a detectar.
httpx
Con httpx, el proxy se configura en el cliente, mediante el parámetro proxy. El antiguo parámetro proxies desapareció en la versión 0.28, lo que deja obsoletos muchos tutoriales.
import httpx
proxy = "http://usuario:contrasena@host.ejemplo:8080"
with httpx.Client(proxy=proxy, timeout=10.0) as client:
r = client.get("https://api.ipify.org")
print(r.text)
httpx.AsyncClient acepta el mismo parámetro. Para SOCKS5, instala httpx[socks] y pasa una dirección socks5://. Por defecto, httpx abandona tras cinco segundos de inactividad de red: ajusta ese tiempo a las webs de destino.
Node.js: fetch, axios y SOCKS5
Los siguientes ejemplos son módulos ES (archivo .mjs o "type": "module" en package.json), lo que permite usar await en el nivel superior.
fetch nativo con undici
El fetch integrado en Node.js desde la versión 18 no pasa por ningún proxy por defecto, aunque HTTPS_PROXY esté definida. Se basa en undici: instala ese paquete y pasa un ProxyAgent en la opción dispatcher.
npm install undici
import { ProxyAgent } from 'undici';
const dispatcher = new ProxyAgent('http://usuario:contrasena@host.ejemplo:8080');
const res = await fetch('https://api.ipify.org?format=json', {
dispatcher,
signal: AbortSignal.timeout(10000), // abandona a los 10 segundos
});
const { ip } = await res.json();
console.log(ip);
Crea el agente una sola vez y reutilízalo. Para evitar cualquier desajuste de versión con el fetch integrado, también puedes importar fetch desde undici.
axios con https-proxy-agent
npm install axios https-proxy-agent
import axios from 'axios';
import { HttpsProxyAgent } from 'https-proxy-agent';
const agent = new HttpsProxyAgent('http://usuario:contrasena@host.ejemplo:8080');
const client = axios.create({
httpsAgent: agent,
proxy: false, // desactiva la gestión de proxy integrada de axios
timeout: 10000,
});
const { data } = await client.get('https://api.ipify.org?format=json');
console.log(data.ip);
proxy: false evita un conflicto: axios lee por su cuenta las variables de entorno de proxy, y ese ajuste podría imponerse a tu agente. HttpsProxyAgent cubre las webs en https://; para http://, el paquete http-proxy-agent cumple la misma función mediante httpAgent.
SOCKS5 con socks-proxy-agent
npm install socks-proxy-agent
import axios from 'axios';
import { SocksProxyAgent } from 'socks-proxy-agent';
const agent = new SocksProxyAgent('socks5h://usuario:contrasena@host.ejemplo:8080');
const { data } = await axios.get('https://api.ipify.org?format=json', {
httpAgent: agent,
httpsAgent: agent,
proxy: false,
timeout: 10000,
});
console.log(data.ip);
Este agente también sirve para los módulos http y https de Node.js (opción agent), pero no para el fetch nativo.
Buenas prácticas en producción
Ninguna contraseña en el código
Una credencial escrita en el código acaba tarde o temprano en un repositorio Git o en una captura de pantalla. Guarda la dirección del proxy en una variable de entorno, alimentada por un archivo .env excluido del repositorio o por un gestor de secretos. Las bibliotecas requests y httpx leen automáticamente las variables estándar HTTPS_PROXY y HTTP_PROXY; cURL también, pero solo en minúsculas (http_proxy) para la segunda:
export HTTPS_PROXY="http://usuario:contrasena@host.ejemplo:8080"
export http_proxy="$HTTPS_PROXY"
curl https://api.ipify.org
python script.py # requests y httpx también usan estas variables
Estas variables afectan a todos los programas lanzados desde ese terminal, pip y git incluidos. En PowerShell, escribe $env:HTTPS_PROXY = "...". En Node.js, pasa el valor al agente: new ProxyAgent(process.env.HTTPS_PROXY).
Codificar los caracteres especiales
En una URL, @, :, /, #, ? y % tienen un papel concreto. Si aparecen en el usuario o la contraseña, la dirección se divide mal y la autenticación falla. Codifica esos dos campos (@ pasa a ser %40). Esta función convierte una línea de Airproxy en una dirección lista para usar:
from urllib.parse import quote
def proxy_url(linea, esquema="http"):
host, puerto, usuario, contrasena = linea.strip().split(":", 3)
return f"{esquema}://{quote(usuario, safe='')}:{quote(contrasena, safe='')}@{host}:{puerto}"
print(proxy_url("host.ejemplo:8080:usuario:contrasena"))
print(proxy_url("host.ejemplo:8080:usuario:contrasena", "socks5h"))
En JavaScript, encodeURIComponent() cumple la misma función.
Tiempos de espera y reintentos
Ni requests ni axios fijan un tiempo de espera por defecto: un proxy o una web que no responde puede bloquear tu script. Fija uno en cada petición y añade algunos reintentos espaciados para absorber los errores pasajeros:
import os
import requests
from requests.adapters import HTTPAdapter
from urllib3.util import Retry
proxy = os.environ["HTTPS_PROXY"]
proxies = {"http": proxy, "https": proxy}
reintentos = Retry(total=3, backoff_factor=1, status_forcelist=[429, 500, 502, 503, 504])
adaptador = HTTPAdapter(max_retries=reintentos)
session = requests.Session()
session.mount("http://", adaptador)
session.mount("https://", adaptador)
r = session.get("https://api.ipify.org", proxies=proxies, timeout=(5, 30))
print(r.text)
El par (5, 30) separa el tiempo de conexión y el de lectura, en segundos. Los reintentos se espacian cada vez más y respetan la cabecera Retry-After de una respuesta 429. Con cURL, el equivalente es --connect-timeout 10 --max-time 30 --retry 3.
Una sesión por proxy
Mantén un cliente por proxy (una requests.Session, un httpx.Client, un ProxyAgent o una instancia de axios): las conexiones se reutilizan y las identidades siguen separadas, porque las cookies de una cuenta nunca deben pasar por la IP de otra. Si recopilas datos, respeta las condiciones de uso de cada web, su robots.txt y el RGPD; nuestra guía de proxies para web scraping explica cómo repartir la carga.
Solución de problemas: 407, tiempos agotados, certificados
Error 407 Proxy Authentication Required
El proxy no ha recibido credenciales válidas. Comprueba que las has copiado sin espacios ni saltos de línea, que los caracteres especiales están codificados, que figuran en la URL o la opción que usas y que el acceso está activo en tu área de cliente. En SOCKS5, el cliente informa de un fallo de autenticación en lugar de un código 407. curl -v muestra el paso exacto que falla.
Tiempos de espera agotados
Un tiempo de conexión agotado suele indicar que no se llega al proxy: host o puerto incorrecto, o un cortafuegos que bloquea ese puerto de salida, habitual en redes de empresa. Un tiempo de lectura agotado apunta a una web lenta o a demasiadas peticiones simultáneas. Comprueba el acceso con nuestro comprobador de proxies: si responde con normalidad, el problema está en otra parte.
Errores de certificado
Dentro del túnel de un proxy HTTP, el cifrado va de extremo a extremo: tu herramienta recibe el certificado de la web, no el del proxy. Por tanto, un error de certificado viene de otro sitio:
- una dirección de proxy en
https://: la herramienta intenta una conexión cifrada con el propio proxy, que espera HTTP sin cifrar (error SSL, a menudo «wrong version number»). Cambia ahttp://; - una inspección TLS de un antivirus o un cortafuegos de empresa: declara su certificado raíz (
--cacerten cURL, el parámetroverifyde requests, la variableNODE_EXTRA_CA_CERTSen Node.js).
No desactives nunca la verificación (-k, verify=False) en producción: tu tráfico podría ser interceptado.
http:// sirve también para las webs en HTTPS, y socks5h:// para SOCKS5. Añade credenciales leídas del entorno y codificadas, un tiempo de espera y reintentos, un cliente por proxy, y comprueba la IP de salida antes de empezar.Los proxies ISP dedicados de Airproxy (Francia, España y la oferta EU) se entregan con el formato host:puerto:usuario:contraseña y responden en HTTP(S) y en SOCKS5 en el mismo host y puerto, así que estos ejemplos se aplican tal cual. Para un navegador o un programa, consulta nuestra guía sobre cómo configurar un proxy. Las ubicaciones disponibles están en la página de ofertas.
Preguntas frecuentes
¿Necesito un acceso distinto para HTTP y para SOCKS5?
En Airproxy no: host, puerto y credenciales son los mismos; solo cambia el prefijo (http:// o socks5h://).
¿Qué diferencia hay entre socks5:// y socks5h://?
Con socks5h://, el proxy resuelve por sí mismo los nombres de dominio. Con socks5://, la mayoría de las herramientas los resuelven en tu equipo, lo que expone los dominios que visitas a tu servidor DNS habitual.
¿Cómo uso varios proxies en un mismo script?
Crea un cliente por proxy y asigna a cada uno una cuenta o una tarea fija. Si recopilas datos, mantén un ritmo que las webs de destino puedan asumir.
Mi contraseña contiene una @: ¿qué hago?
Codifícala: @ pasa a ser %40. En Python, urllib.parse.quote(contrasena, safe="") se encarga; en JavaScript, encodeURIComponent().
