Guía práctica
¿Cómo se usa un proxy residencial asiático con Python Requests?
Respuesta cortaPara usar un proxy con Python Requests, pasa a cada solicitud un diccionario proxies como {"https": "http://USERNAME-country-jp:[email protected]:7777"}. Con Jade Proxies, el nombre de usuario también selecciona la ciudad y una sesión fija (sticky), y SOCKS5 funciona igual con socks5h:// en el puerto 7778.
¿Qué necesitas antes de empezar?
Necesitas Python 3, la biblioteca Requests y credenciales de proxy. Jade Proxies admite usuario y contraseña, o lista de IP permitidas (hasta 10 IP); subusuarios con sus propias credenciales y límite de tráfico; claves de API que puedes revocar en cualquier momento. Todos los ejemplos envían el tráfico a través del gateway gw.jadeproxies.com: el puerto 7777 para HTTP y HTTPS, y el puerto 7778 para SOCKS5.
- 01
Instala Requests con soporte SOCKS
Ejecuta
pip install "requests[socks]", que instala Requests y PySocks. - 02
Guarda tus credenciales
Pon el usuario y la contraseña del proxy de tu cuenta de Jade Proxies en las variables de entorno
PROXY_USERyPROXY_PASS, no en el código. - 03
Crea el diccionario del proxy HTTP
Asigna las claves
httpyhttpsahttp://USER:[email protected]:7777; a los sitios HTTPS se accede mediante un túnel CONNECT, así que el TLS se mantiene de extremo a extremo. - 04
Cambia a SOCKS5 cuando lo necesites
Usa
socks5h://USER:[email protected]:7778para que el DNS se resuelva en la salida, en el país de destino. - 05
Segmenta por país y ciudad
Amplía el nombre de usuario con
-country-jpy luego-city-osaka, según el formatoUSERNAME-country-{cc}-city-{city}-session-{id}-ttl-{minutes}. - 06
Conserva una IP con una sesión fija (sticky)
Añade
-session-ID-ttl-MINUTESy reutiliza unrequests.Session; la IP se conserva hasta 30 minutos (la IP puede cambiar antes). - 07
Verifica la IP de salida
Solicita
https://ipinfo.io/jsona través del proxy y comprueba el campocountryantes del trabajo real. - 08
Configura timeouts y reintentos
Pasa
timeout=(10, 30)y monta unHTTPAdaptercon una políticaRetrypara las respuestas 429 y 5xx. - 09
Ejecuta solicitudes en paralelo
Usa un
ThreadPoolExecutor; una solicitud por conexión da una IP nueva por solicitud.
¿Cómo se configura un proxy HTTP en Python Requests?
Se configura un proxy HTTP pasando un diccionario proxies cuyas claves http y https apuntan ambas al puerto HTTP del gateway.
import os
import requests
from urllib.parse import quote
USER = os.environ["PROXY_USER"]
PASS = quote(os.environ["PROXY_PASS"], safe="") # encodes @ : / in passwords
proxy = f"http://{USER}-country-jp:{PASS}@gw.jadeproxies.com:7777"
proxies = {"http": proxy, "https": proxy}
r = requests.get("https://example.com/", proxies=proxies, timeout=(10, 30))
print(r.status_code)
La URL del proxy empieza por http:// incluso en la clave https: Requests abre un túnel CONNECT a través del gateway y la sesión TLS se establece entre tu script y el sitio. Un estado 407 significa que el gateway rechazó el usuario o la contraseña.
¿Cómo se usa un proxy SOCKS5 con Requests?
Para usar SOCKS5, cambia el esquema a socks5h y el puerto a 7778; el resto del código no cambia.
proxy = f"socks5h://{USER}-country-kr:{PASS}@gw.jadeproxies.com:7778"
proxies = {"http": proxy, "https": proxy}
r = requests.get("https://example.com/", proxies=proxies, timeout=(10, 30))
Con socks5h, el gateway resuelve el nombre de host en Corea. Con socks5 a secas, lo resuelve tu propia máquina, lo que expone la consulta a tu DNS local y puede devolver un servidor fuera del país de destino.
¿Cómo se eligen el país y la ciudad?
Eliges la salida añadiendo parámetros al nombre de usuario. Jade Proxies ofrece segmentación por país y ciudad en todos los planes; segmentación por ASN sin coste adicional; la disponibilidad de ciudades varía.
| Objetivo | Nombre de usuario |
|---|---|
| Cualquier IP en Japón | USER-country-jp |
| Osaka | USER-country-jp-city-osaka |
| Bombay | USER-country-in-city-mumbai |
| Bangkok, la misma IP durante 10 minutos | USER-country-th-city-bangkok-session-a1b2c3-ttl-10 |
Los códigos de país son los códigos ISO de dos letras de los 13 países que aparecen en la página de proxies residenciales asiáticos. Una pequeña función auxiliar mantiene el formato en un solo lugar:
def proxy_url(country, city=None, session=None, ttl=10, socks=False):
user = f"{USER}-country-{country}"
if city:
user += f"-city-{city}"
if session:
user += f"-session-{session}-ttl-{ttl}"
if socks:
return f"socks5h://{user}:{PASS}@gw.jadeproxies.com:7778"
return f"http://{user}:{PASS}@gw.jadeproxies.com:7777"
¿Cómo se mantiene la misma IP entre solicitudes?
Mantienes la misma IP añadiendo un ID de sesión y un TTL al nombre de usuario y enviando las solicitudes a través de un único requests.Session.
import uuid
p = proxy_url("jp", "tokyo", session=uuid.uuid4().hex[:8], ttl=30)
s = requests.Session()
s.proxies = {"http": p, "https": p}
for page in range(1, 4):
s.get(f"https://example.jp/list?page={page}", timeout=(10, 30))
Sin ID de sesión, cada nueva conexión obtiene una IP del pool de IP, normalmente distinta; para obtener una IP nueva en cada solicitud, envía una solicitud por conexión (desactiva keep-alive). Un requests.Session mantiene las conexiones abiertas, así que usa llamadas simples a requests.get() cuando quieras una IP nueva en cada solicitud. La guía de proxies rotativos frente a sesiones fijas explica qué modo conviene a cada tarea.
¿Cómo se comprueba que la IP de salida está en el país correcto?
Compruebas la salida consultando un endpoint de información de IP a través del proxy y comparando su código de país con el que solicitaste.
info = requests.get("https://ipinfo.io/json", proxies=proxies, timeout=15).json()
assert info["country"] == "JP", info
print(info["ip"], info.get("city"), info.get("org"))
El campo org indica la red propietaria de la IP; en una salida residencial es un proveedor de internet (ISP) doméstico, no una empresa de hosting. Ejecuta esta comprobación una vez por país antes de un trabajo largo.
¿Cómo se gestionan los timeouts y los reintentos?
Configura un timeout de conexión y otro de lectura en cada llamada y reintenta los errores transitorios con backoff, porque una salida residencial es una conexión doméstica que puede caerse en cualquier momento.
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
retry = Retry(total=3, backoff_factor=1, status_forcelist=[429, 500, 502, 503, 504], allowed_methods=["GET"])
s = requests.Session()
s.mount("http://", HTTPAdapter(max_retries=retry))
s.mount("https://", HTTPAdapter(max_retries=retry))
r = s.get("https://example.com/", proxies=proxies, timeout=(10, 30))
Los reintentos consumen tráfico solo cuando llegan al sitio: el consumo incluye todos los datos enviados y recibidos a través del proxy (subida y bajada, cabeceras incluidas); 1 GB = 1.000.000.000 bytes; los intentos de conexión que fallan antes de llegar al destino no se contabilizan.
¿Cómo se envían solicitudes en paralelo?
Envías solicitudes en paralelo con un pool de hilos, porque Requests es síncrono y cada hilo espera en su propia conexión.
from concurrent.futures import ThreadPoolExecutor
def fetch(url):
r = requests.get(url, proxies=proxies, timeout=(10, 30))
return url, r.status_code, len(r.content)
with ThreadPoolExecutor(max_workers=10) as pool:
for url, status, size in pool.map(fetch, urls):
print(status, size, url)
Cada llamada a requests.get() abre su propia conexión, así que cada solicitud obtiene su propia IP. Empieza con 10 workers, aumenta el número mientras la proporción de errores y respuestas 429 se mantenga estable, y respeta los límites de frecuencia y las condiciones de cada sitio.
¿Cuánto tráfico consume un rastreo con Python Requests?
Un rastreo consume aproximadamente el número de páginas multiplicado por la transferencia media por página. La tabla supone 100 KB por página: HTML comprimido más las cabeceras de solicitud y respuesta, sin imágenes. Ese peso es una suposición para el cálculo, no una medición.
| Rastreo | Tráfico | Plan | Coste |
|---|---|---|---|
| 10.000 páginas | 1 GB | Prueba | $1.50 |
| 100.000 páginas | 10 GB | Crecimiento | $6.60 |
| 500.000 páginas | 50 GB | Pro | $26 |
| 1.000.000 páginas | 100 GB | Empresa | $50 |
Nuestra tabla de precios muestra que un millón de páginas cuestan $50 en tráfico residencial con el plan 100 GB con ese peso. El peso de las páginas varía según el sitio, así que mide primero tu propia media con una muestra de 1.000 páginas; la guía de Shopee y Lazada trata los marketplaces. Todos los planes están en la página de precios, y el tráfico nunca caduca.
Preguntas frecuentes
¿Por qué Requests ignora mi proxy?
Requests aplica un proxy solo a los esquemas de URL presentes en el diccionario proxies, así que un diccionario con solo la clave http envía las solicitudes HTTPS directamente. Define ambas claves y comprueba que ninguna variable de entorno NO_PROXY coincida con el host de destino.
¿Qué diferencia hay entre socks5 y socks5h en Requests?
Con socks5h, el proxy resuelve el nombre de host en la salida; con socks5, tu máquina lo resuelve localmente. Usa socks5h para destinos asiáticos, de modo que las respuestas DNS coincidan con el país de salida.
¿Cómo obtengo una IP nueva en cada solicitud?
No incluyas el ID de sesión en el nombre de usuario y envía una solicitud por conexión, por ejemplo con llamadas simples a requests.get() en lugar de un Session compartido. Cada nueva conexión obtiene una IP del pool de IP, normalmente distinta.
¿Qué significa un error 407?
Un estado 407 Proxy Authentication Required significa que el gateway no aceptó las credenciales. Revisa la codificación de la contraseña con urllib.parse.quote y la sintaxis del nombre de usuario, por ejemplo USER-country-jp-city-osaka.
¿Cuánto cuesta una primera prueba?
El plan 1 GB cuesta $1.50, unas 10.000 páginas con la suposición de 100 KB indicada arriba. Se paga desde un saldo en criptomonedas con una recarga de saldo mínima de $25, y el tráfico no utilizado nunca caduca.
Prueba 1 GB de IP residenciales asiáticas por $1.50
Recarga de saldo desde $25 en BTC, ETH, USDT, USDC, SOL, LTC. Sin documento de identidad ni selfie. El saldo no usado nunca caduca.