curl_cffi Web Scraping: Huellas digitales TLS del navegador en Python
Specialist in Anti-Bot Strategies
TL;DR:
- curl_cffi es un cliente HTTP de Python que imita el apretón de manos TLS de un navegador real, por lo que un servidor que realiza huellas dactilares de la conexión ve Chrome en lugar de un cliente de scripting.
- Una llamada
requests.get(url, impersonate="chrome")presenta una huella dactilar JA3 de navegador y negocia HTTP/2, sin necesidad de un proceso de navegador. - El hash JA3 cambia en cada ejecución, y eso es correcto: GREASE inserta valores aleatorios en el apretón de manos, lo cual también hace el verdadero Chrome.
- curl_cffi no ejecuta JavaScript, por lo que en una página renderizada por el cliente devuelve la estructura vacía; la guía lo demuestra con 0 bloques de cita de curl_cffi y 10 de Scrapeless con renderizado.
- Utiliza curl_cffi cuando una huella dactilar TLS es el obstáculo, y para Scrapeless cuando la página necesita renderizado, retos superados o rotación de IP.
- Comienza con el plan gratuito de Scrapeless para las páginas a las que la suplantación TLS por sí sola no puede acceder.
Un cliente HTTP de Python básico tiene una señal que un objetivo puede leer antes de que envíe un solo byte de HTML: su apretón de manos TLS. El conjunto de cifrados y extensiones en el ClientHello no se parece al de un navegador, y un servidor que realiza huellas dactilares de ese apretón de manos puede bloquear la solicitud solo con la huella dactilar. curl_cffi cierra esa brecha al tomar prestada la firma TLS de un navegador real.
Esta guía muestra cómo curl_cffi presenta una huella dactilar de navegador, explica por qué el hash JA3 no es constante, y luego establece el límite que curl_cffi no puede cruzar. Donde una página necesita un navegador real, la API Universal de Scraping de Scrapeless toma el relevo. Cada número a continuación proviene de una ejecución real.
Qué hace curl_cffi
curl_cffi es un cliente HTTP estilo requests construido sobre curl-impersonate, y su trabajo es hacer que el apretón de manos TLS se parezca al de un navegador específico. Un servidor que inspecciona el apretón de manos calcula una huella dactilar JA3, un resumen de la versión, cifrados y extensiones del ClientHello definidos sobre el apretón de manos TLS 1.3. Un cliente Python por defecto produce una huella dactilar que ningún navegador produciría; curl_cffi produce una que un navegador nombrado sí. El repositorio de curl_cffi enumera las versiones de navegador que puede suplantar.
Lo que curl_cffi no hace es ejecutar un navegador. No hay motor JavaScript, no hay renderizado y no hay resolución de desafíos. Es una huella dactilar, no un navegador.
Instalación
curl_cffi es una instalación de pip única.
bash
pip install curl_cffi
Suplantar una Huella Dactilar de Navegador
Pasa impersonate con un nombre de navegador y curl_cffi construye el apretón de manos TLS de ese navegador. La solicitud a continuación pide a un servicio de huellas dactilares que informe lo que vio.
python
from curl_cffi import requests
response = requests.get("https://tls.peet.ws/api/all", impersonate="chrome", timeout=30)
fingerprint = response.json()
print("versión http:", fingerprint["http_version"])
print("hash ja3:", fingerprint["tls"]["ja3_hash"])
El servicio informa HTTP/2, que un navegador negocia y un cliente por defecto generalmente no, y un hash JA3.
text
versión http: h2
hash ja3: 9a23d5cedcea13483954537602158034
El valor hash ja3 anterior es el resultado de una ejecución; ejecuta el script nuevamente y cambiará. Eso no es un error. El mecanismo GREASE inserta valores reservados aleatorios en el ClientHello, y el verdadero Chrome hace lo mismo, por lo que el hash JA3 difiere de conexión a conexión. Lo que se mantiene parecido a un navegador es la forma del apretón de manos, que es lo que realmente evalúa una verificación de huellas dactilares.
Donde curl_cffi Se Detiene
Una huella dactilar TLS de navegador permite que la solicitud pase una verificación de apretón de manos, pero no renderiza la página. En un sitio que construye su contenido con JavaScript, curl_cffi devuelve exactamente lo que el servidor envió, que es una estructura vacía, y ninguna cantidad de suplantación TLS la llena. Aquí es donde se requiere una herramienta de renderizado.
Establece tu clave de Scrapeless en la terminal. Usa la clave real en tiempo de ejecución y manten el marcador fuera de tu fuente.
bash
export SCRAPELESS_API_KEY="sk_tu_clave_aqui"
El script a continuación obtiene una página de citas renderizada por JavaScript de dos maneras: curl_cffi con una huella dactilar de Chrome perfecta, y Scrapeless con renderizado activado.
python
import json
import os
import urllib.request
from curl_cffi import requests
JS_PAGE = "https://quotes.toscrape.com/js/"
response = requests.get(JS_PAGE, impersonate="chrome", timeout=30)
print("estado curl_cffi:", response.status_code)
print("bloques de cita curl_cffi:", response.text.count('class="quote"'))
def scrapeless(url: str) -> str:
payload = json.dumps(
```json
{"actor": "unlocker.webunlocker", "input": {"url": url, "js_render": true, "headless": true}}
).encode()
request = urllib.request.Request(
"https://api.scrapeless.com/api/v2/unlocker/request",
data=payload,
headers={"x-api-token": os.environ["SCRAPELESS_API_KEY"], "Content-Type": "application/json"},
method="POST",
)
with urllib.request.urlopen(request, timeout=90) as response:
return json.loads(response.read())["data"]
html = scrapeless(JS_PAGE)
print("bloques de cita de scrapeless:", html.count('class="quote"'))
curl_cffi obtiene un limpio 200 y cero citas, porque las citas son dibujadas por JavaScript que nunca se ejecuta. Scrapeless renderiza la página y las citas aparecen.
text
estado de curl_cffi: 200
bloques de citas de curl_cffi: 0
bloques de citas de scrapeless: 10
El 200 es la trampa: la solicitud tiene éxito, por lo que nada parece estar mal, pero el contenido no está. Las dos herramientas responden a diferentes problemas. curl_cffi derrota una verificación de huella TLS; no renderiza, no supera un desafío, ni rota IPs. Para el concepto detrás de la huella, la guía sobre cómo eludir la huella TLS cubre lo que mide un servidor y por qué.
Antes de ejecutar cualquiera de estos en un sitio, lee su robots.txt y términos. Protocolo de Exclusión de Robots establece qué rutas un sitio pide a los clientes automatizados que eviten, y honrarlo mantiene un scraper sostenible.
¿Listo para las páginas que solo una huella no puede alcanzar? Crea una cuenta gratuita en Scrapeless y renderízalas.
Conclusión
curl_cffi es la herramienta adecuada para un trabajo: hacer que el apretón de manos TLS de una solicitud de Python se asemeje al de un navegador, lo que despeja una verificación de huella sin un proceso de navegador. Es precisa, y su límite es igualmente preciso, porque no ejecuta JavaScript y devuelve la estructura vacía de una página renderizada por el cliente. Úsala donde la pared sea el apretón de manos, y entrega la página a Scrapeless cuando necesite renderizado, un desafío superado, o una IP nueva. Comienza con los scripts anteriores y ajusta la herramienta a la pared que tienes frente a ti.
Comienza con el plan gratuito de Scrapeless para páginas renderizadas, y consulta los precios de Scrapeless cuando planees un trabajo recurrente.
FAQ
P: ¿Qué impersona realmente curl_cffi?
curl_cffi impersona el apretón de manos TLS de un navegador y su configuración HTTP/2, de modo que el ClientHello que ve un servidor coincide con una versión nombrada de navegador en lugar de un cliente Python por defecto. No impersona el motor JavaScript o el renderizado de un navegador, solo la huella a nivel de red.
P: ¿Por qué cambia el hash JA3 cada vez que ejecuto la solicitud?
Debido a GREASE, que inserta valores reservados aleatorios en el TLS ClientHello. Chrome real también hace esto, así que el hash JA3 varía entre conexiones mientras que la forma significativa del apretón de manos se mantiene como la de un navegador. Se espera que un hash cambie, no es una señal de que la suplantación falló.
P: ¿Puede curl_cffi raspar una página renderizada por JavaScript?
No. curl_cffi no tiene un motor JavaScript, así que en una página renderizada por el cliente devuelve la estructura HTML inicial con un estado 200 y ninguno de los contenidos renderizados. Usa una herramienta de renderizado como Scrapeless para esas páginas, y reserva curl_cffi para puntos finales cuyo contenido ya esté en la respuesta.
P: ¿Cómo se diferencia curl_cffi de requests?
La biblioteca requests envía un apretón de manos TLS estándar de Python que un servidor de huellas puede marcar, mientras que curl_cffi envía un apretón de manos de navegador a través de su argumento impersonate. La API es de otra manera familiar, así que requests.get(url, impersonate="chrome") es casi un reemplazo directo para código que estaba siendo bloqueado por su huella.
P: ¿Es suficiente una huella TLS de navegador para evitar bloqueos?
Es suficiente para una verificación de huella TLS y nada más. Las páginas de desafío, el análisis de comportamiento y la reputación de IP son defensas separadas que curl_cffi no toca, así que cuando esas están en juego necesitas renderizado, manejo de desafíos o rotación de proxies además de la huella.
En Scrapeless, solo accedemos a datos disponibles públicamente y cumplimos estrictamente con las leyes, regulaciones y políticas de privacidad del sitio web aplicables. El contenido de este blog es sólo para fines de demostración y no implica ninguna actividad ilegal o infractora. No ofrecemos garantías y renunciamos a toda responsabilidad por el uso de la información de este blog o enlaces de terceros. Antes de realizar cualquier actividad de scraping, consulte a su asesor legal y revise los términos de servicio del sitio web de destino u obtenga los permisos necesarios.



