Explainers

Reglas WAF de Cloudflare que desencadenan desafíos CAPTCHA

El firewall de aplicaciones web (WAF) de Cloudflare permite a los operadores de sitios crear reglas que activan desafíos CAPTCHA en función de atributos de solicitud específicos: dirección IP, país, ruta URL, puntuación de bot, encabezados o cualquier combinación. Comprender qué reglas desencadenan desafíos le ayuda a diagnosticar por qué está viendo un CAPTCHA y elegir el enfoque correcto para manejarlo.


Acciones de reglas WAF que producen CAPTCHA

Las reglas WAF de Cloudflare admiten varias acciones. Tres de ellos presentan desafíos solucionables:

Acción WAF Qué ocurre Estado HTTP Método CaptchaAI
Managed Challenge Cloudflare decide: challenge invisible, Turnstile o JS 503 turnstile
JS Challenge Página de challenge de JavaScript de 5 segundos 503 cloudflare_challenge
Interactive Challenge CAPTCHA tradicional (heredado, obsoleto) 403 turnstile
Bloquear 403 duro, sin challenge 403 N/A (no resoluble)
Permitir Pasar, sin control 200 N/A
Saltar Saltar las reglas WAF restantes 200 N/A
Registro Registrar evento, sin acción 200 N/A

Desafío gestionado (el más común)

Managed Challenge es la acción recomendada por Cloudflare. Decide de forma adaptativa el tipo de desafío por visitante:

WAF rule matches → Managed Challenge triggered
    ↓
Cloudflare evaluates visitor:
  ├─ Low risk → Invisible pass (no visible challenge)
  ├─ Medium risk → Turnstile widget (click to verify)
  └─ High risk → JavaScript challenge page
    ↓
Successful → qa_validation_cookie cookie issued

Patrones de reglas WAF comunes

Los operadores del sitio crean reglas WAF utilizando el lenguaje de expresión de Cloudflare. Estos son los patrones con mayor probabilidad de activar CAPTCHA para tráfico automatizado:

Reglas de puntuación de bots

# Challenge traffic with low bot scores
(cf.bot_management.score lt 30)
→ Action: Managed Challenge

# Challenge non-verified bots
(cf.bot_management.score lt 50 and not cf.bot_management.verified_bot)
→ Action: JS Challenge

Las reglas de puntuación de bots son el desencadenante más común de las herramientas de automatización. Los solucionadores de API de CaptchaAI reciben puntuaciones de nivel humano porque utilizan navegadores reales.

Reglas basadas en países

# Challenge traffic from specific countries
(ip.geoip.country in {"CN" "RU" "VN" "IN"})
→ Action: Managed Challenge

# Block specific regions entirely
(ip.geoip.country eq "XX")
→ Action: Block

Reglas basadas en rutas

# Challenge login page access
(http.request.uri.path eq "/login" or http.request.uri.path eq "/signup")
→ Action: Managed Challenge

# Challenge API endpoints
(http.request.uri.path contains "/api/")
→ Action: JS Challenge

Reglas basadas en tarifas

# Challenge after high request rate
(cf.threat_score gt 10 and http.request.uri.path contains "/search")
→ Action: Managed Challenge

Reglas basadas en encabezados

# Challenge requests with no Accept-Language header
(not http.request.headers["accept-language"])
→ Action: JS Challenge

# Challenge requests with suspicious UA
(http.user_agent contains "python" or http.user_agent contains "curl")
→ Action: Managed Challenge

Reglas compuestas

# Multiple conditions
(cf.bot_management.score lt 30
 and http.request.uri.path contains "/api/"
 and ip.geoip.country ne "US")
→ Action: JS Challenge

Identificar qué regla se activó

Cuando aparece un desafío CAPTCHA, puede identificar la regla desencadenante a partir de la respuesta:

Desde encabezados HTTP

import requests

def check_cloudflare_rule_info(url):
    """Extract WAF rule information from Cloudflare challenge response."""
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                      "AppleWebKit/537.36 Chrome/120.0.0.0",
        "Accept": "text/html,*/*;q=0.8",
        "Accept-Language": "en-US,en;q=0.9",
    }

    response = requests.get(url, headers=headers, timeout=15, allow_redirects=False)

    info = {
        "status": response.status_code,
        "cf_ray": response.headers.get("cf-ray", ""),
        "cf_cache_status": response.headers.get("cf-cache-status", ""),
        "server": response.headers.get("server", ""),
    }

    # Challenge-specific info
    html = response.text

    if response.status_code == 503:
        if "jschl" in html:
            info["challenge_type"] = "JS Challenge (IUAM or WAF rule)"
        elif "challenge-platform" in html:
            info["challenge_type"] = "Managed Challenge"
        elif "cf-turnstile" in html:
            info["challenge_type"] = "Turnstile (Managed Challenge)"

    elif response.status_code == 403:
        if "cf-ray" in str(response.headers):
            info["challenge_type"] = "WAF Block (no challenge)"
        else:
            info["challenge_type"] = "Origin 403 (not Cloudflare)"

    return info

Desde el ID de Cloudflare Ray

Cada respuesta de Cloudflare incluye un encabezado cf-ray. Los operadores del sitio pueden usar este Ray ID en el panel de Cloudflare (Seguridad > Eventos) para ver exactamente qué regla se activó y qué acción se tomó.


Resolviendo desafíos desencadenados por WAF

Estrategia basada en el tipo de desafío.

import requests
import time

API_KEY = "YOUR_API_KEY"

def solve_cloudflare_challenge(url, challenge_type):
    """Solve Cloudflare challenge based on WAF rule action."""

    if challenge_type == "managed_challenge":
        # Managed Challenge typically renders as Turnstile
        method = "turnstile"
        sitekey = extract_turnstile_sitekey(url)
    elif challenge_type == "js_challenge":
        # JavaScript Challenge page
        method = "cloudflare_challenge"
        sitekey = "managed"
    else:
        raise ValueError(f"Unknown challenge type: {challenge_type}")

    submit = requests.post("https://ocr.captchaai.com/in.php", data={
        "key": API_KEY,
        "method": method,
        "sitekey": sitekey,
        "pageurl": url,
        "json": 1,
    })

    task_id = submit.json()["request"]

    for _ in range(60):
        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.get("status") == 1:
            return result["request"]

    raise TimeoutError("Challenge solve timed out")


def extract_turnstile_sitekey(url):
    """Fetch page and extract Turnstile sitekey."""
    import re
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                      "AppleWebKit/537.36 Chrome/120.0.0.0",
    }
    response = requests.get(url, headers=headers, timeout=15)
    match = re.search(r'data-sitekey=["\']([0-9x][A-Za-z0-9_-]+)["\']', response.text)
    return match.group(1) if match else None

Nodo.js

const axios = require("axios");

const API_KEY = "YOUR_API_KEY";

async function solveWAFChallenge(url, challengeType) {
  const method =
    challengeType === "js_challenge" ? "cloudflare_challenge" : "turnstile";
  const sitekey =
    challengeType === "js_challenge" ? "managed" : await extractSitekey(url);

  const submit = await axios.post("https://ocr.captchaai.com/in.php", null, {
    params: {
      key: API_KEY,
      method,
      sitekey,
      pageurl: url,
      json: 1,
    },
  });

  const taskId = submit.data.request;

  for (let i = 0; i < 60; i++) {
    await new Promise((r) => setTimeout(r, 5000));

    const result = await axios.get("https://ocr.captchaai.com/res.php", {
      params: { key: API_KEY, action: "get", id: taskId, json: 1 },
    });

    if (result.data.status === 1) {
      return result.data.request;
    }
  }

  throw new Error("Challenge solve timed out");
}

async function extractSitekey(url) {
  const response = await axios.get(url, {
    headers: {
      "User-Agent": "Mozilla/5.0 Chrome/120.0.0.0",
    },
  });
  const match = response.data.match(/data-sitekey=["']([0-9x][A-Za-z0-9_-]+)["']/);
  return match ? match[1] : null;
}

Cambios en las reglas WAF y sus efectos

Los operadores del sitio ajustan con frecuencia las reglas WAF. Estos cambios afectan la automatización:

Cambio Efecto sobre la automatización Cómo detectar
Regla agregada Aparece un nuevo challenge en rutas que funcionaban Monitorear cambios de estado 503/403
Regla eliminada El challenge desaparece 200 donde antes era 503
Acción escalada (Block → Managed) El challenge resoluble se convierte en bloque duro 403 en lugar de 503
Acción relajada (Block → Managed) El bloque duro se convierte en challenge resoluble 503 con página de challenge
Umbral cambiado (bot score 30 → 50) Más solicitudes challengeadas Mayor frecuencia de challenge
Alcance de ruta cambiado Diferentes URLs afectadas Nuevas rutas devuelven challenges

Estrategia de seguimiento

import requests
import time

def monitor_cloudflare_protection(urls, interval=3600):
    """Monitor protection changes across URLs."""
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                      "AppleWebKit/537.36 Chrome/120.0.0.0",
        "Accept": "text/html,*/*;q=0.8",
        "Accept-Language": "en-US,en;q=0.9",
    }

    last_status = {}

    while True:
        for url in urls:
            try:
                response = requests.get(
                    url, headers=headers, timeout=15, allow_redirects=False
                )
                status = response.status_code
                has_challenge = status == 503 or "cf-turnstile" in response.text

                current = {"status": status, "challenge": has_challenge}
                previous = last_status.get(url)

                if previous and current != previous:
                    print(f"[CHANGE] {url}")
                    print(f"  Before: {previous}")
                    print(f"  After:  {current}")

                last_status[url] = current

            except requests.RequestException as e:
                print(f"[ERROR] {url}: {e}")

        time.sleep(interval)

Solución de problemas

Síntoma Probable regla WAF Solución
Challenge solo en /login Regla basada en ruta Resuelve el challenge para esa ruta
Challenge solo desde IPs de centros de datos Bot score o regla de reputación de IP Usa proxies residenciales o resuelve el challenge
Challenge varía según el país Regla basada en país Usa proxy en el país permitido o resuelve
Challenge tras N solicitudes Regla basada en tasa Reduce la tasa de solicitudes o resuelve cada challenge
Challenge siempre JS (nunca Turnstile) Acción JS Challenge (no Managed) Usa el método cloudflare_challenge
403 sin challenge Acción Block (no resoluble) Cambia IP, cabeceras o patrón de solicitud

Preguntas frecuentes

¿Puedo ver qué reglas WAF utiliza un sitio?

No. Las reglas WAF son privadas para el operador del sitio. Sólo puedes inferir reglas a partir del comportamiento: qué rutas desencadenan desafíos, desde qué IP y qué tipo de desafío aparece.

¿Se aplican las reglas WAF a todos los planes de Cloudflare?

Las reglas WAF personalizadas están disponibles en todos los planes pagos (Pro, Business, Enterprise). Los planes gratuitos tienen reglas WAF limitadas. Sin embargo, Managed Challenge está disponible en todos los planes, incluido el gratuito.

¿Pueden las reglas WAF desencadenar diferentes desafíos para diferentes caminos?

Sí. Cada regla WAF puede tener una acción diferente y coincidir con diferentes rutas. Un sitio puede utilizar Managed Challenge para los puntos finales /login y JS Challenge para los puntos finales /api/.

¿Con qué frecuencia los sitios cambian sus reglas WAF?

Varía. Los sitios de comercio electrónico suelen ajustar las reglas durante los eventos de ventas. Los sitios preocupados por la seguridad pueden actualizar las reglas semanalmente. La mayoría de los sitios rara vez cambian las reglas después de la configuración inicial.

¿La resolución de un desafío WAF afecta las solicitudes futuras?

Sí. Después de resolverlo, la cookie qa_validation_cookie permite que las solicitudes posteriores pasen sin desafíos durante aproximadamente 30 minutos. La cookie está vinculada a su IP y Agente de Usuario.


Resumen

Las reglas WAF de Cloudflare activan challenges CAPTCHA según condiciones configurables: bot score, país, ruta, cabeceras o tasa. La acción más común es Managed Challenge, que Cloudflare presenta de forma adaptativa como challenge invisible, Turnstile o JS. Resúelvelos con CaptchaAI usando el método turnstile o cloudflare_challenge según lo que se renderice. Los bloques duros (403) de las reglas WAF no son resolubles; en su lugar, cambia el patrón de solicitud o la IP.

Artículos relacionados

  • Cloudflare Challenge vs Turnstile: cómo detectar
  • Cómo funciona Cloudflare Challenge
  • Cómo manejar el modo bajo ataque de Cloudflare
Los comentarios están deshabilitados para este artículo.

Publicaciones relacionadas

Comparisons Cloudflare Managed Challenge vs Interactive Challenge
Cloudflare Managed Challenge vs Interactive Challenge: diferencias de comportamiento, códigos HTTP, métodos de resolución con Captcha AI y cuándo usar cada uno.

Cloudflare Managed Challenge vs Interactive Challenge: diferencias de comportamiento, códigos HTTP, métodos de...

Apr 18, 2026
Explainers Cómo manejar Cloudflare en modo ataque
Cómo manejar el modo 'I'm Under Attack' (IUAM) de Cloudflare: qué es, cómo funciona el challenge Java Script obligatorio de 5 segundos y cómo resolverlo con Cap...

Cómo manejar el modo 'I'm Under Attack' (IUAM) de Cloudflare: qué es, cómo funciona el challenge Java Script o...

Apr 18, 2026
Troubleshooting Errores y soluciones comunes de reCAPTCHA Invisible
Errores comunes en la resolución de re CAPTCHA Invisible y cómo solucionarlos: callback no ejecutado, parámetro invisible=1, token caducado, pageurl incorrecto...

Errores comunes en la resolución de re CAPTCHA Invisible y cómo solucionarlos: callback no ejecutado, parámetr...

Apr 24, 2026