Cloudflare Turnstile reemplazó a reCAPTCHA en la mayoría de los sitios protegidos en 2025 y bloquea el 90% de los scrapers ingenuos. Este tutorial muestra cómo enrutar solicitudes a través del solucionador administrado de Scavio para que el desafío se maneje de manera transparente y su raspador devuelva HTML limpio.
Requisitos previos
- Python 3.10+
- Una clave API de Scavio
- Una URL de destino detrás de Turnstile
Guia paso a paso
Paso 1: Detectar el bloque Torniquete
Una búsqueda de referencia devuelve una página de desafío, no su contenido.
import requests
html = requests.get('https://turnstile-protected.com').text
if 'Just a moment' in html or 'challenge-platform' in html:
print('Blocked by Turnstile')Paso 2: Ruta a través del extracto de Scavio
Scavio maneja el desafío detrás de escena.
import os
API_KEY = os.environ['SCAVIO_API_KEY']
def fetch(url):
r = requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': API_KEY},
json={'query': url, 'platform': 'extract', 'render_js': True})
return r.json().get('html', '')Paso 3: Validar la respuesta
No hay marcadores de torniquete en el HTML devuelto.
def passed(html):
return 'challenge-platform' not in html and len(html) > 1000Paso 4: Reintentar con un perfil más fuerte
Si aún está bloqueado, pregúntele a Scavio por el solucionador premium.
def fetch_premium(url):
r = requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': API_KEY},
json={'query': url, 'platform': 'extract', 'render_js': True, 'resolver': 'premium'})
return r.json().get('html', '')Paso 5: Caché para evitar reelaboraciones
Mantenga las recuperaciones exitosas en caché durante 24 horas.
import time, hashlib, os
def cache_key(url):
return 'cache/' + hashlib.md5(url.encode()).hexdigest() + '.html'
def cached_fetch(url):
k = cache_key(url)
if os.path.exists(k) and time.time() - os.path.getmtime(k) < 86400:
return open(k).read()
html = fetch(url)
os.makedirs('cache', exist_ok=True); open(k, 'w').write(html)
return htmlEjemplo en Python
import os, requests
API_KEY = os.environ['SCAVIO_API_KEY']
def fetch(url):
r = requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': API_KEY},
json={'query': url, 'platform': 'extract', 'render_js': True, 'resolver': 'premium'})
return r.json().get('html', '')
html = fetch('https://turnstile-protected.com')
print('clean' if 'challenge-platform' not in html else 'still blocked')Ejemplo en JavaScript
const API_KEY = process.env.SCAVIO_API_KEY;
export async function fetchPage(url) {
const r = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST',
headers: { 'x-api-key': API_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({ query: url, platform: 'extract', render_js: true, resolver: 'premium' })
});
return (await r.json()).html;
}Salida esperada
Clean HTML from Turnstile-protected pages in 2-8 seconds. Typical success rate via premium resolver: 95%+ on Turnstile-protected pages.