Compraste IP residenciales limpias, las rotas a la perfección, y aun así recibes un 403 en la primera petición. La IP no es el problema — tu handshake TLS sí lo es. La huella TLS (TLS fingerprinting) permite a un servidor identificar la biblioteca cliente antes de leer un solo byte de tu petición HTTP. Esta guía explica JA3/JA4, muestra por qué requests de Python es trivial de detectar y ofrece código funcional para imitar navegadores reales con curl_cffi y tls-client.
Cuando cualquier cliente abre una conexión HTTPS, envía un ClientHello que anuncia su versión de TLS, las suites de cifrado, las extensiones, las curvas elípticas y el orden de todas ellas. Ese orden es notablemente específico de la biblioteca que lo construyó. Calcula su hash y obtienes una huella JA3 (o la más nueva y robusta JA4).
Chrome produce una huella. Firefox otra. El requests de Python (construido sobre urllib3 y OpenSSL) produce una huella que grita "automatización" — y es idéntica en millones de bots. Los sistemas antibot mantienen una lista de bloqueo de estas. Por muy residencial que sea tu IP, una JA3 de bot conocido queda marcada.
Antes de arreglar nada, mídelo. Envía una petición desde tu scraper al comprobador gratuito de huella JA3/JA4 de JIBAO y compárala con lo que muestra un Chrome real. Si los hashes JA3 difieren, el objetivo puede distinguirte de un humano — y Cloudflare también.
requests y httpx entregan el TLS al OpenSSL del sistema. Puedes cambiar las cabeceras e incluso el User-Agent todo lo que quieras, pero el handshake subyacente sigue siendo el de OpenSSL, no el de Chrome. El falseo de cabeceras sin falseo del handshake es la razón más común de que ocurra el "copié las cabeceras del navegador y aun así me bloquea". Necesitas un cliente que imite el stack TLS real del navegador.
curl_cffi se enlaza con curl-impersonate, una compilación de curl que reproduce las huellas TLS y HTTP/2 reales de los navegadores. Un solo argumento y tu handshake parece el de Chrome:
# pip install curl_cffi
from curl_cffi import requests
# impersonate a real Chrome TLS + HTTP/2 fingerprint
r = requests.get(
"https://tls.browserleaks.com/json",
impersonate="chrome131",
)
print(r.json()["ja3_hash"]) # now matches real Chrome
La API refleja la de requests, así que migrar un scraper existente es en su mayoría un cambio de import de una línea. Los destinos soportados incluyen compilaciones recientes de Chrome, Edge, Safari y Firefox — elige uno y mantenlo actualizado, porque las huellas rotan a medida que los navegadores se actualizan.
La coincidencia de huella y la rotación de IP son complementarias, no alternativas. Usa ambas: un handshake de grado navegador sobre una IP residencial limpia es lo que realmente pasa:
from curl_cffi import requests
PROXY = "socks5h://USERNAME:[email protected]:10001"
r = requests.get(
"https://example.com/protected",
impersonate="chrome131",
proxies={"http": PROXY, "https": PROXY},
timeout=30,
)
print(r.status_code)
tls-client (un wrapper de Python sobre una implementación de uTLS en Go) es otra opción sólida, con una amplia biblioteca de perfiles con nombre:
# pip install tls-client
import tls_client
session = tls_client.Session(
client_identifier="chrome_120",
random_tls_extension_order=True,
)
session.proxies = {
"http": "socks5h://USERNAME:[email protected]:10001",
"https": "socks5h://USERNAME:[email protected]:10001",
}
r = session.get("https://example.com/protected")
print(r.status_code)
random_tls_extension_order=True baraja el orden de las extensiones para evitar una huella estática y reutilizable — útil contra sistemas que rastrean la JA3 de coincidencia exacta a lo largo del tiempo.
Algunos objetivos comprueban señales de ejecución de JavaScript (canvas, WebGL, tiempo de eventos) que ningún cliente HTTP reproduce. Ahí, maneja un navegador real en su lugar — consulta usar proxies con Playwright y Puppeteer con stealth. La compensación es coste y velocidad: los clientes HTTP como curl_cffi son mucho más baratos por petición, así que úsalos donde basten y reserva los navegadores completos para los objetivos más difíciles.
curl_cffi (impersonate=) o tls-client — las cabeceras por sí solas no bastan.La huella TLS es la capa que falta en la mayoría de las historias de "IP limpia pero aun así bloqueado". Arregla el handshake, conserva la IP residencial, y la tasa de éxito se dispara. Para el stack completo contra el WAF más duro, lee la receta de evasión de Cloudflare 2026.
Consigue 500MB de tráfico gratis e IP residenciales para combinar con huellas TLS de grado navegador.
Empezar prueba gratisLos nuevos usuarios reciben 500MB al registrarse, más un bono en la primera recarga. Oferta por tiempo limitado.