Tutoriais de API

Como resolver Cloudflare Turnstile pela API

O Cloudflare Turnstile é uma alternativa a CAPTCHAs focada em privacidade que roda silenciosamente em segundo plano. Diferente dos CAPTCHAs tradicionais, ele raramente exibe um desafio visível: coleta sinais do navegador e emite um token que o backend do site verifica.

Este guia explica como resolver o Turnstile programaticamente usando a API da CaptchaAI. Se você ainda não leu o Quickstart da CaptchaAI, comece por ele — descreve o fluxo geral em 4 passos.


Requisitos

Item Valor
API key da CaptchaAI No painel em captchaai.com
Sitekey do Turnstile Extraído da página (começa com 0x)
URL da página URL completa onde o Turnstile aparece
Linguagem Python 3.7+ ou Node.js 14+

Passo 1: encontre o sitekey

O sitekey costuma estar no HTML da página, dentro de uma div ou script:

<div class="cf-turnstile" data-sitekey="0x4AAAAAAAC3DHQFLr1GavNl"></div>

Ou renderizado por JavaScript:

turnstile.render('#widget', {
  sitekey: '0x4AAAAAAAC3DHQFLr1GavNl',
  callback: function(token) { /* ... */ }
});

Três formas de extrair:

  1. DevTools do navegador — aba Elements, busque data-sitekey ou cf-turnstile.
  2. Código-fonteCtrl+U e procure strings que comecem com 0x.
  3. Aba Network — filtre por challenges.cloudflare.com; o sitekey vai nos parâmetros da requisição.

O sitekey do Turnstile sempre começa com 0x e geralmente tem 22 caracteres. Isso o diferencia das chaves de reCAPTCHA, que começam com 6L.


Passo 2: envie a tarefa

POST para https://ocr.captchaai.com/in.php com method=turnstile:

import requests

API_KEY = "YOUR_CAPTCHAAI_KEY"
SITEKEY = "0x4AAAAAAAC3DHQFLr1GavNl"
PAGEURL = "https://staging.example.com/qa-login"

r = requests.post("https://ocr.captchaai.com/in.php", data={
    "key": API_KEY,
    "method": "turnstile",
    "sitekey": SITEKEY,
    "pageurl": PAGEURL,
    "json": 1,
})
data = r.json()
if data["status"] != 1:
    raise RuntimeError(f"submit failed: {data}")
task_id = data["request"]
print("task id:", task_id)

Equivalente em Node.js:

const axios = require("axios");

const { data } = await axios.post("https://ocr.captchaai.com/in.php", null, {
  params: {
    key: process.env.CAPTCHAAI_KEY,
    method: "turnstile",
    sitekey: "0x4AAAAAAAC3DHQFLr1GavNl",
    pageurl: "https://staging.example.com/qa-login",
    json: 1,
  },
});
if (data.status !== 1) throw new Error(`submit failed: ${JSON.stringify(data)}`);
const taskId = data.request;

Resposta de sucesso: {"status": 1, "request": "<task_id>"}. Guarde o task_id para o polling.


Passo 3: faça polling do resultado

O Turnstile costuma resolver em 10–25 segundos. Espere 10 segundos e depois faça polling a cada 5 segundos, no máximo 40 iterações:

import time

time.sleep(10)
for _ in range(40):
    r = requests.get("https://ocr.captchaai.com/res.php", params={
        "key": API_KEY,
        "action": "get",
        "id": task_id,
        "json": 1,
    })
    res = r.json()
    if res["status"] == 1:
        token = res["request"]
        break
    if res["request"] != "CAPCHA_NOT_READY":
        raise RuntimeError(f"solver error: {res}")
    time.sleep(5)
else:
    raise TimeoutError("turnstile solving timed out")

print("token (60 primeiros caracteres):", token[:60])

O token devolvido é uma string Base64 que normalmente começa com 0. e tem 400–600 caracteres.


Passo 4: injete o token na página

Com o token em mãos, coloque-o no campo oculto cf-turnstile-response do formulário e envie.

Selenium:

driver.execute_script(
    "document.querySelector('[name=cf-turnstile-response]').value = arguments[0];",
    token,
)
driver.find_element("css selector", "form").submit()

Playwright:

page.evaluate(
    "(t) => document.querySelector('[name=cf-turnstile-response]').value = t",
    token,
)
page.click("button[type=submit]")

HTTP puro: adicione cf-turnstile-response=<token> no corpo application/x-www-form-urlencoded.

O token do Turnstile vale por 120–300 segundos. Use logo após recebê-lo, ou o backend retornará timeout-or-duplicate.


Exemplo completo em Python

import os, time, requests

API = "https://ocr.captchaai.com"
KEY = os.environ["CAPTCHAAI_KEY"]

def solve_turnstile(sitekey: str, pageurl: str) -> str:
    r = requests.post(f"{API}/in.php", data={
        "key": KEY, "method": "turnstile",
        "sitekey": sitekey, "pageurl": pageurl, "json": 1,
    }, timeout=30)
    j = r.json()
    if j["status"] != 1:
        raise RuntimeError(f"submit: {j}")
    tid = j["request"]

    time.sleep(10)
    for _ in range(40):
        r = requests.get(f"{API}/res.php", params={
            "key": KEY, "action": "get", "id": tid, "json": 1,
        }, timeout=30)
        j = r.json()
        if j["status"] == 1:
            return j["request"]
        if j["request"] != "CAPCHA_NOT_READY":
            raise RuntimeError(f"poll: {j}")
        time.sleep(5)
    raise TimeoutError("timeout")

if __name__ == "__main__":
    print(solve_turnstile("0x4AAAAAAAC3DHQFLr1GavNl", "https://staging.example.com/qa-login"))

Erros comuns

Código Significado Ação
ERROR_WRONG_USER_KEY Formato de API key inválido Verifique se CAPTCHAAI_KEY está completo
ERROR_KEY_DOES_NOT_EXIST API key não encontrada Copie novamente do painel
ERROR_ZERO_BALANCE Saldo zero Recarregue e tente de novo
ERROR_PAGEURL Falta o pageurl Envie a URL completa com https://
ERROR_CAPTCHA_UNSOLVABLE Falhou após várias tentativas Verifique se sitekey e pageurl batem; tente uma vez mais

Mais detalhes no guia de reCAPTCHA v2.


Quando não funciona

  1. Sitekey dinâmico. Alguns sites Cloudflare emitem novo sitekey a cada visita. Refaça o scraping antes de cada tarefa.
  2. pageurl exato. O backend do Turnstile compara a URL de forma estrita: envie o caminho exato, sem query string.
  3. Impressão TLS. A Cloudflare pode bloquear clientes pela assinatura TLS. Use curl_cffi, Playwright ou um navegador real.
  4. Token expirado. Use em menos de 2 minutos ou terá que resolver de novo.
  5. Qualidade do proxy. IPs datacenter baratas costumam disparar desafios extras. Prefira proxies residenciais ou móveis.

Próximos passos

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