Explainers

Como lidar com Cloudflare sob modo de ataque

Seu scraper começou a receber HTTP 503 do nada, mesmo trocando o user-agent? É bem provável que o site tenha ativado o "Modo Estou Sob Ataque" (IUAM) da Cloudflare — a proteção anti-DDoS mais agressiva da plataforma.

Diferente do Desafio Gerenciado, que desafia só o tráfego suspeito, o IUAM desafia toda requisição enquanto ativo — inclusive chamadas de API sem navegador. Veja como reconhecer o IUAM e resolvê-lo com a API da CaptchaAI em Python e Node.js.


Resumo rápido

  • Sinal: HTTP 503 com uma página "Verificando seu navegador antes de acessar..."
  • Exigência: execução de JavaScript e espera mínima de 5 segundos
  • Escopo: domínio inteiro, enquanto o IUAM estiver ativo
  • Solução prática: resolver via API (turnstile_staging) em vez de manter um navegador aberto

O que é o Modo Estou Sob Ataque (IUAM) da Cloudflare

Quando um operador de site ativa o "Modo Estou Sob Ataque" no painel da Cloudflare, toda requisição segue este fluxo antes de chegar à página real:

Every request → Cloudflare edge
    ↓
JavaScript challenge page served (HTTP 503)
    ↓
Browser executes JavaScript challenge (~5 seconds)
    ↓
Challenge answer submitted automatically
    ↓
cookie_qa_validacao cookie set
    ↓
Original page loaded with cookie_qa_validacao cookie

Como reconhecer a página de desafio IUAM

  • Status HTTP 503 (não 403 — sinal de bloqueio pelo WAF), com os campos jschl_vc, pass, jschl_answer, cf_chl_opt e ray
  • Espera obrigatória de 5 segundos antes do envio da resposta do desafio
  • Exige execução de JavaScript — clientes HTTP simples nunca passam sozinhos
  • Mensagem "Verificando seu navegador antes de acessar..." visível ao usuário
  • Cookie cookie_qa_validacao válido por ~30 minutos, libera as requisições seguintes
  • Vale para o domínio inteiro enquanto o modo está ativo

Diferença rápida de leitura: 503 = desafio a resolver; 403 = bloqueio do WAF, sem desafio nenhum para tentar.


Diferenciando IUAM de outras proteções da Cloudflare

Confirme a proteção antes de escolher o método — cada uma exige uma abordagem diferente:

import requests

def identify_cloudflare_protection(url):
    """Distinguish IUAM from other Cloudflare protections."""
    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, allow_redirects=False)
    html = response.text
    status = response.status_code

    if status == 503 and "jschl" in html:
        return "IUAM (I'm Under Attack Mode)"

    if status == 503 and "challenge-platform" in html:
        return "Managed Challenge"

    if status == 403 and "cf-ray" in str(response.headers):
        return "Blocked by WAF/Bot Management"

    if "cf-turnstile" in html:
        return "Turnstile widget"

    if "challenges.cloudflare.com" in html:
        return "Cloudflare Turnstile em staging (generic)"

    if status == 200:
        return "No challenge (passed)"

    return f"Unknown (status: {status})"

Tabela comparativa de sinais

Sinal IUAM Desafio gerenciado Turnstile Bloqueio WAF
Status HTTP 503 503 200 403
jschl no corpo
Espera de 5 segundos Às vezes
Cookie cookie_qa_validacao definido Depois de resolver Depois de resolver
Página do desafio Página inteira Página inteira Somente o widget Página de erro
Exige JS

Regra prática: 503 + jschl no HTML é IUAM; 200 com widget cf-turnstile é Turnstile; 403 é bloqueio direto.


Como funciona o desafio JavaScript por trás do IUAM

O desafio JavaScript do IUAM verifica se quem está do outro lado é um navegador real.

Etapas do fluxo do desafio

  1. A Cloudflare entrega a página de desafio com JavaScript ofuscado.
  2. O JavaScript executa os cálculos — operações sobre strings da página, medições do DOM e um tempo mínimo de 4 a 5 segundos.
  3. A resposta é calculada a partir do desafio.
  4. O formulário é enviado automaticamente com jschl_vc, pass e jschl_answer.
  5. A Cloudflare valida a resposta e o tempo decorrido.
  6. O cookie cookie_qa_validacao é devolvido — libera o acesso por ~30 minutos.

Por que os clientes HTTP simples falham

# This will ALWAYS get the challenge page:
import requests
response = requests.get("https://iuam-protected-site.com")
# response.status_code == 503
# response.text contains "Checking your browser..."

# Plain HTTP clients cannot:
# - Execute JavaScript
# - Compute the challenge answer
# - Meet the timing requirement
# - Generate the required cookies

Como resolver o desafio IUAM com a CaptchaAI

Método 1: solucionador Cloudflare Turnstile em staging (recomendado)

O método turnstile_staging da CaptchaAI resolve o desafio IUAM diretamente, sem precisar manter um navegador aberto:

import requests
import time

API_KEY = "YOUR_API_KEY"
TARGET_URL = "https://iuam-protected-site.com/data"

# Step 1: Submit challenge to CaptchaAI
submit = requests.post("https://ocr.captchaai.com/in.php", data={
    "key": API_KEY,
    "method": "turnstile_staging",
    "sitekey": "managed",
    "pageurl": TARGET_URL,
    "json": 1,
})

task_id = submit.json()["request"]
print(f"Task submitted: {task_id}")

# Step 2: Poll for result
for attempt 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:
        token = result["request"]
        print(f"Challenge solved! Token: {token[:50]}...")
        break
    elif result.get("request") == "ERROR_CAPTCHA_UNSOLVABLE":
        print("Challenge could not be solved")
        break
else:
    print("Timed out waiting for solution")

# Step 3: Use cookie_qa_validacao cookie or token
# The response contains the clearance data needed to access the site

Método 2: combine automação de navegador com a CaptchaAI

Para sessões que precisam durar mais do que uma única requisição, combine um navegador headless com a CaptchaAI:

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import requests
import time

API_KEY = "YOUR_API_KEY"

# Launch browser
options = webdriver.ChromeOptions()
options.add_argument("--disable-blink-features=AutomationControlled")
driver = webdriver.Chrome(options=options)

# Navigate to IUAM page
driver.get("https://iuam-protected-site.com")

# Wait for challenge page to load
time.sleep(3)

# Check if IUAM challenge is present
if "Checking your browser" in driver.page_source or driver.title == "Just a moment...":
    print("IUAM challenge detected")

    # Option A: Wait for browser to solve natively (if not headless)
    try:
        WebDriverWait(driver, 15).until(
            lambda d: "Checking your browser" not in d.page_source
        )
        print("Challenge passed natively")
    except:
        print("Native solve failed — using CaptchaAI")
        # Submit to CaptchaAI for solving
        # Token submission via JavaScript injection

# After challenge is passed, extract cookies for API use
cookies = driver.get_cookies()
cookie_qa_validacao = next(
    (c["value"] for c in cookies if c["name"] == "cookie_qa_validacao"), None
)

if cookie_qa_validacao:
    print(f"cookie_qa_validacao obtained: {cookie_qa_validacao[:30]}...")

    # Use cookie with requests library
    session = requests.Session()
    for cookie in cookies:
        session.cookies.set(cookie["name"], cookie["value"])
    session.headers.update({
        "User-Agent": driver.execute_script("return navigator.userAgent"),
    })

    # Now make requests with the clearance cookie
    response = session.get("https://iuam-protected-site.com/api/data")
    print(f"Status: {response.status_code}")

driver.quit()

Depois de extrair os cookies do navegador, reaproveite-os em requisições subsequentes com requests.Session() — é isso que o trecho acima faz na prática.

Exemplo em Node.js

O mesmo fluxo de duas etapas (enviar, consultar), agora em Node.js com axios:

const axios = require("axios");

const API_KEY = "YOUR_API_KEY";
const TARGET_URL = "https://iuam-protected-site.com/data";

async function solveIUAM() {
  // Submit challenge
  const submit = await axios.post("https://ocr.captchaai.com/in.php", null, {
    params: {
      key: API_KEY,
      method: "turnstile_staging",
      sitekey: "managed",
      pageurl: TARGET_URL,
      json: 1,
    },
  });

  const taskId = submit.data.request;
  console.log(`Task submitted: ${taskId}`);

  // Poll for result
  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) {
      console.log("IUAM challenge solved!");
      return result.data.request;
    }
  }

  throw new Error("Timed out");
}

solveIUAM().then((token) => console.log("Token:", token.substring(0, 50)));

Qual método escolher

  • Requisição pontual? Método 1 — mais rápido, sem overhead de navegador.
  • Sessão com várias páginas? Método 2 — reaproveite os cookies extraídos.
  • Stack em Node.js? Mesmo fluxo do Método 1, com axios.

Erros comuns ao resolver o IUAM (e como corrigir)

Confira estes casos antes de investigar a fundo:

  • Desafio repete indefinidamente → IP mudou após obter o cookie de clearance; use o mesmo IP para resolver e acessar.
  • cookie_qa_validacao rejeitado → User-Agent diferente entre resolução e requisição seguinte; use o mesmo em ambas.
  • 503 volta a aparecer → cookie expirou (mais de 30 min); renove antes de vencer.
  • Página de desafio diferente do esperado → o site usa Desafio Gerenciado, não IUAM; troque o método para Turnstile.
  • Várias páginas de desafio seguidas → a primeira é IUAM, a segunda é Turnstile; resolva as duas em sequência.

Caso comum: workers rodando em sa-east-1 (São Paulo) veem o desafio repetir mais do que em uma máquina local, porque o IP de saída do provedor muda entre chamadas ou é compartilhado. Fixar o IP de saída resolve a maior parte desses casos.

Antes de reportar bug: confira se IP e User-Agent bateram entre a resolução e o uso do cookie. É a causa raiz na maioria dos tickets.


O cookie cookie_qa_validacao evita resolver o desafio de novo a cada requisição. Vale por ~30 minutos (configurável pelo operador), cobre o domínio inteiro, fica vinculado ao par IP + User-Agent, e só é reutilizável enquanto ambos permanecem os mesmos.

Se esse cookie for gravado junto com dados de navegação do usuário, considere as obrigações da LGPD (ou RGPD, em Portugal) sobre retenção e finalidade — este texto não substitui orientação jurídica.

Estratégia de gerenciamento de sessão

import requests
import time

class IUAMSessionManager:
    """Manage cookie_qa_validacao cookies for IUAM-protected sites."""

    def __init__(self, api_key, target_url, user_agent=None):
        self.api_key = api_key
        self.target_url = target_url
        self.user_agent = user_agent or (
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
            "AppleWebKit/537.36 Chrome/120.0.0.0"
        )
        self.session = requests.Session()
        self.session.headers["User-Agent"] = self.user_agent
        self.clearance_time = 0
        self.clearance_lifetime = 1800  # 30 minutes default

    def needs_refresh(self):
        """Check if clearance cookie needs refreshing."""
        return time.time() - self.clearance_time > self.clearance_lifetime - 60

    def solve_challenge(self):
        """Solve IUAM challenge and update session cookies."""
        submit = requests.post("https://ocr.captchaai.com/in.php", data={
            "key": self.api_key,
            "method": "turnstile_staging",
            "sitekey": "managed",
            "pageurl": self.target_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": self.api_key,
                "action": "get",
                "id": task_id,
                "json": 1,
            }).json()

            if result.get("status") == 1:
                # Apply clearance to session
                self.clearance_time = time.time()
                return result["request"]

        raise TimeoutError("IUAM solve timed out")

    def get(self, url, **kwargs):
        """Make a GET request, solving IUAM if needed."""
        if self.needs_refresh():
            self.solve_challenge()
        return self.session.get(url, **kwargs)

Perguntas frequentes

IUAM e Cloudflare Turnstile em staging são a mesma proteção?

Não exatamente. O IUAM desafia todo mundo, sempre com HTTP 503 e o desafio JS de 5 segundos. Já o Turnstile costuma aparecer como widget dentro de um Desafio Gerenciado, acionado só para tráfego suspeito.

Por que um servidor na nuvem recebe o desafio com mais frequência do que meu notebook?

Geralmente é o IP de saída. Provedores de nuvem reaproveitam faixas de IP entre clientes, e um IP com histórico de tráfego automatizado é desafiado com mais frequência. Um IP estável e o cookie_qa_validacao reaproveitado reduzem bastante isso.

Se eu navegar para outra página do mesmo site, preciso resolver o IUAM de novo?

Não, contanto que o cookie_qa_validacao ainda seja válido: ele vale para o domínio inteiro, não só para a página onde foi obtido. Mantenha o mesmo IP e User-Agent para que o cookie siga sendo aceito.

Preciso automatizar um navegador para resolver o IUAM?

Não é obrigatório. O caminho mais simples é resolver via API (Método 1) e reaproveitar o cookie nas chamadas seguintes — sem manter um navegador headless rodando o tempo todo.


Resumo

O IUAM da Cloudflare cria um desafio JavaScript obrigatório para todo visitante, respondendo com HTTP 503 e uma exigência de cálculo de 5 segundos. Resolva-o com o solucionador Cloudflare Turnstile em staging da CaptchaAI, reaproveite o cookie cookie_qa_validacao dentro da janela de 30 minutos, e mantenha sempre o mesmo IP e User-Agent entre a resolução e o uso do cookie.

Artigos relacionados

Os comentários estão desativados para este artigo.