No puedes copiar la cookie de acceso de Cloudflare desde tu navegador y pegarla en un scraper: sólo aparece al superar el challenge y viene atada a la IP y al User-Agent que lo resolvieron. Esa cookie —aquí la llamamos qa_validation_cookie— convierte un 403 o un 503 en un 200. Veamos cómo la genera Cloudflare y cómo obtenerla con CaptchaAI.
Esta guía asume que trabajas sobre sitios propios o con permiso, y que respetas los términos de servicio y la normativa de protección de datos aplicable. Resolver el challenge es el producto; el uso responsable corre de tu cuenta.
Qué pasa cuando Cloudflare te marca como sospechoso
Es una página intersticial que Cloudflare intercala antes del contenido. El flujo es siempre el mismo:
- Solicitas una página protegida por Cloudflare.
- Cloudflare evalúa señales de riesgo: reputación de la IP, encabezados HTTP y la huella TLS del cliente.
- Si te marca, responde con un 403 o un 503 que sirve una página de challenge en JavaScript.
- Ejecuta comprobaciones del navegador y, según el nivel, muestra un widget Turnstile.
- Al superarla, Cloudflare establece
qa_validation_cookiey te redirige a la URL original. - Las siguientes solicitudes que llevan la cookie pasan sin volver a ver el challenge.
Sin resolver el challenge no hay cookie que extraer.
Los tres niveles de Cloudflare Challenge
Cloudflare sirve tres niveles:
| Nivel | Código de respuesta | Interacción del usuario | Descripción |
|---|---|---|---|
| JS Challenge | 503 | Ninguna | Sólo ejecución de JavaScript |
| Managed Challenge | 403 | Puede que sí | Cloudflare decide: muestra Turnstile o pasa en silencio |
| Interactive Challenge | 403 | Sí | Siempre muestra un widget Turnstile |
CaptchaAI resuelve los tres con el solver de Cloudflare Challenge.
La cookie qa_validation_cookie por dentro
Al superar el challenge recibes una cookie con estas propiedades:
| Propiedad | Detalle |
|---|---|
| Nombre | qa_validation_cookie |
| Dominio | Dominio del sitio de destino (por ejemplo, .example.com) |
| Ruta | / |
| Duración | Normalmente de 30 minutos a 24 horas |
| HttpOnly | Sí |
| Secure | Sí (sólo HTTPS) |
| SameSite | None |
Va ligada a tu identidad de red:
- Dirección IP: usar la cookie desde una IP distinta a la que resolvió el challenge suele fallar.
- User-Agent: debe coincidir con el UA empleado durante la resolución.
- Huella TLS: algunas configuraciones la vinculan al TLS ClientHello del cliente.
En la práctica, estos tres factores explican casi todos los rechazos: una cookie que "funcionaba" deja de valer en cuanto cambias de máquina, de red o de cabecera.
Resolver el challenge con CaptchaAI
Obtienes el token de Turnstile: envías la tarea a in.php y consultas res.php hasta tenerlo.
Python
import requests
import time
API_KEY = "YOUR_API_KEY"
TARGET_URL = "https://example.com/protected-page"
# Submit Cloudflare Challenge task
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": "turnstile",
"sitekey": "0x0000000000000000000000", # may be generic for CF challenge
"pageurl": TARGET_URL,
"json": "1",
}).json()
if resp["status"] != 1:
raise Exception(f"Submit error: {resp['request']}")
task_id = resp["request"]
print(f"Task ID: {task_id}")
# Poll for result
for _ in range(30):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY, "action": "get", "id": task_id, "json": "1"
}).json()
if result["status"] == 1:
token = result["request"]
print(f"Token received: {token[:50]}...")
break
if result["request"] != "CAPCHA_NOT_READY":
raise Exception(f"Error: {result['request']}")
JavaScript
const axios = require('axios');
const API_KEY = 'YOUR_API_KEY';
const TARGET_URL = 'https://example.com/protected-page';
const submit = await axios.post('https://ocr.captchaai.com/in.php', null, {
params: {
key: API_KEY,
method: 'turnstile',
sitekey: '0x0000000000000000000000',
pageurl: TARGET_URL,
json: 1,
}
});
const taskId = submit.data.request;
// Poll
let token = null;
for (let i = 0; i < 30; i++) {
await new Promise(r => setTimeout(r, 5000));
const poll = await axios.get('https://ocr.captchaai.com/res.php', {
params: { key: API_KEY, action: 'get', id: taskId, json: 1 }
});
if (poll.data.status === 1) {
token = poll.data.request;
break;
}
}
console.log(`Token: ${token.substring(0, 50)}...`);
Del token a la cookie qa_validation_cookie
El token no basta: inyéctalo en el campo de respuesta de Turnstile y deja que Cloudflare procese el envío para recibir qa_validation_cookie. Aquí necesitas un navegador real (Selenium o Puppeteer).
# With Selenium
from selenium import webdriver
driver = webdriver.Chrome()
driver.get(TARGET_URL) # Load the challenge page
# Inject token into Turnstile response field
driver.execute_script("""
const input = document.querySelector('input[name="cf-turnstile-response"]');
if (input) input.value = arguments[0];
// Trigger form submit or callback
const form = document.querySelector('form');
if (form) form.submit();
""", token)
# Wait for redirect and extract cookies
import time
time.sleep(3)
cookies = driver.get_cookies()
qa_validation_cookie = next(
(c for c in cookies if c['name'] == 'qa_validation_cookie'), None
)
if qa_validation_cookie:
print(f"qa_validation_cookie: {qa_validation_cookie['value'][:30]}...")
Reutilizar la cookie en tu sesión
Traslada la cookie a una sesión de requests. Usa el mismo User-Agent de la resolución; si no coincide, vuelve el challenge.
session = requests.Session()
session.cookies.set("qa_validation_cookie", qa_validation_cookie["value"], domain=".example.com")
session.headers.update({
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
})
# Now access protected pages
resp = session.get("https://example.com/api/data")
print(resp.status_code) # 200
Si repartes el trabajo entre varios workers, guarda la cookie y su
expiryen un almacén compartido como Redis: así resuelves el challenge una vez y todos los procesos reutilizan la misma cookie hasta que caduca.
Cuánto dura la cookie y cuándo renovarla
qa_validation_cookie caduca; comprueba su validez y renueva antes de que expire, sin esperar al primer 403:
import datetime
def is_cookie_valid(cookie):
if not cookie:
return False
expiry = cookie.get("expiry", 0)
return datetime.datetime.now().timestamp() < expiry - 60 # 60s buffer
def get_or_refresh_clearance(driver, target_url, solve_func):
cookies = driver.get_cookies()
cf = next((c for c in cookies if c["name"] == "qa_validation_cookie"), None)
if is_cookie_valid(cf):
return cf["value"]
# Re-solve
token = solve_func(target_url)
# ... inject and extract new cookie
Ejemplo típico: para monitorizar precios en un marketplace regional, resuelve una vez, reutilízala mientras dure y renueva al agotarse el margen.
Cuándo reutilizar la cookie y cuándo volver a resolver
No toda petición necesita un challenge nuevo. Cada resolución consume un thread de tu plan y suma latencia, así que conviene exprimir cada cookie mientras siga válida. Vuelve a resolver sólo cuando se cumpla alguna de estas condiciones:
- La cookie ha caducado, según el campo
expiry. - Cambias de IP o de salida de red respecto a la que resolvió el challenge.
- El sitio empieza a devolver 403 pese a enviar una cookie que parecía válida.
Este último caso suele indicar que el sitio endureció su configuración de Cloudflare o rotó el secreto; volver a resolver genera una cookie fresca sin más cambios en tu código.
Errores frecuentes al reutilizar la cookie
| Síntoma | Causa probable | Cómo resolverlo |
|---|---|---|
| La cookie se rechaza tras resolver | La IP no coincide | Usa el mismo proxy para resolver y para las solicitudes |
| La cookie caduca enseguida | TTL corto fijado por el sitio | Resuelve antes de que expire; revisa el campo expiry |
| 403 con una cookie válida | El User-Agent no coincide | Iguala el UA entre la sesión de resolución y la de solicitud |
| La página de challenge no carga | JavaScript deshabilitado | Usa un navegador completo (Selenium, Puppeteer) |
Si un síntoma persiste después de igualar la IP y el User-Agent, vuelve a resolver el challenge: suele salir más a cuenta que depurar una cookie ya inservible.
Preguntas frecuentes
¿Por qué no puedo copiar la cookie desde mi navegador y pegarla en el scraper?
Porque va atada a la IP y al User-Agent que resolvieron el challenge; con otra IP u otra cabecera, Cloudflare la invalida.
¿Necesito un proxy para reutilizar qa_validation_cookie?
Depende: la IP que resuelve y la que reutiliza deben ser la misma. Si ambas salen por la misma red, no necesitas nada extra.
¿CaptchaAI resuelve los tres niveles de Cloudflare Challenge?
Sí. El solver cubre el JS Challenge, el Managed Challenge y el Interactive Challenge, sin que detectes el nivel por adelantado.
¿Puedo saltarme el navegador y trabajar sólo con la API?
No del todo. La API te da el token de Turnstile, pero para que Cloudflare emita qa_validation_cookie alguien tiene que inyectar ese token en la página y enviar el formulario, y eso exige un navegador que ejecute JavaScript, como Selenium o Puppeteer.
¿Qué hago si sigo viendo un 403 con la cookie puesta?
Revisa que la IP y el User-Agent coincidan con los de la resolución; si coinciden y aun así falla, lo más probable es que la cookie haya caducado o que el sitio la rechace, así que resuelve de nuevo para obtener una fresca.
Resuelve Cloudflare Challenge con CaptchaAI
Obtén tu clave API en captchaai.com y genera cookies de acceso válidas resolviendo el challenge, sin copiar sesiones a mano.