Como resolver PopularCaptcha em Python (exemplo funcional, 2026)
Se o seu script Python esbarrou em um PopularCaptcha, você não precisa de uma fazenda de navegadores nem de um modelo próprio. Você precisa do sitekey da página, de uma requisição POST e do token que volta.
Este guia leva você do zero a um token funcionando em cerca de cinco minutos: obter uma chave de API, encontrar o sitekey, pedir o token, enviá-lo ao formulário e tratar os casos de falha que aparecem quando um script roda sem supervisão. Resoluções que falham são gratuitas, então uma nova tentativa custa apenas tempo.
A Scarnox resolve o PopularCaptcha hoje, com ou sem proxy próprio. Outros tipos de captcha, como reCAPTCHA, Cloudflare Turnstile e AWS WAF, estão em breve, então todos os exemplos aqui usam o PopularCaptcha. A visão geral dos tipos de captcha explica como os outros diferem.
1. Obtenha uma chave de API
Crie uma conta e comece com crédito de teste grátis, sem cartão. Sua chave de API está no painel. Mantenha-a fora do código-fonte e leia-a de uma variável de ambiente:
export SCARNOX_KEY="scarnox_YOURAPIKEY"
2. Encontre o sitekey
Abra a página com o captcha, abra o DevTools e procure por data-sitekey no painel Elements. Os sitekeys do PopularCaptcha são UUIDs:
<div class="h-captcha" data-sitekey="10000000-ffff-ffff-ffff-000000000001"></div>
Não há data-sitekey no HTML? O widget provavelmente é renderizado pelo JavaScript. Confira na aba Network a requisição de configuração do widget; o parâmetro de consulta sitekey é o que você precisa. Outras formas de encontrá-lo cobrem a URL do iframe e os widgets invisíveis.
Envie como site_url a URL da página que exibe o widget. O host é o mais importante, mas a URL completa da página é a escolha segura.
3. Peça um token
import os
import requests
API_URL = "https://api.scarnox.com/api/tasks/create"
API_KEY = os.environ["SCARNOX_KEY"]
def solve_captcha(sitekey: str, page_url: str) -> str:
r = requests.post(
API_URL,
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"captcha_type": "PopularCaptchaTaskProxyless",
"site_key": sitekey,
"site_url": page_url,
},
timeout=185, # a chamada bloqueia até o token estar pronto
)
data = r.json()
if data.get("errorId") != 0:
raise RuntimeError(f"{data.get('errorCode')}: {data.get('errorDescription')}")
return data["solution"]["token"]
if __name__ == "__main__":
token = solve_captcha("10000000-ffff-ffff-ffff-000000000001", "https://example.com/signup")
print(token[:40], "...")
É toda a integração. Não há loop de polling nem uma segunda chamada de "obter resultado". A requisição retorna quando o token está pronto, então a única configuração que importa é um timeout longo o suficiente para cobrir uma resolução lenta. Use cerca de 185 segundos.
Uma resposta de sucesso tem errorId igual a 0, com o token em solution.token. Qualquer outro errorId significa que a resolução falhou, e a resposta traz um errorCode e um errorDescription que explicam o motivo.
4. Envie o token
O token vai para onde o site espera a resposta do captcha. Para o PopularCaptcha, quase sempre é um campo de formulário chamado h-captcha-response. Muitos sites também aceitam g-recaptcha-response, então envie os dois:
import requests
def sign_up(session: requests.Session, form_url: str, email: str, sitekey: str) -> requests.Response:
token = solve_captcha(sitekey, form_url)
return session.post(form_url, data={
"email": email,
"h-captcha-response": token,
"g-recaptcha-response": token,
}, timeout=30)
Dois detalhes importam aqui. Sites reais geralmente também verificam os cookies de sessão do carregamento da página, então carregue o formulário com o mesmo requests.Session antes de enviar o POST. E envie o POST para a action do formulário, que nem sempre é a URL da página.
Resolva logo antes de enviar. O token expira em cerca de dois minutos, então não o busque no início de um trabalho longo e o guarde. Se o site rejeitar o token, abra o formulário no DevTools e confirme os nomes dos campos ocultos.
5. Trate as falhas
Resoluções que falham são gratuitas, então uma nova tentativa custa apenas tempo. Alguns erros nunca vão funcionar em uma nova tentativa, então não entre em loop cegamente. Verifique o errorId sempre, registre o errorCode e o errorDescription e tente de novo apenas as falhas transitórias.
Erros de rede precisam de tratamento próprio, porque o requests levanta a exceção antes de existir qualquer resposta:
import requests
try:
token = solve_captcha(sitekey, page_url)
except requests.RequestException as exc:
print("network problem, retry later:", exc)
except RuntimeError as exc:
print("solve rejected:", exc)
O guia de tratamento de erros tem uma política completa de novas tentativas com backoff e jitter.
Erros comuns
- **
site_urlerrada.** Envie a página que exibe o widget, e não a página inicial. - Token velho. Um token usado depois de cerca de dois minutos é rejeitado. Resolva logo antes de enviar.
- Sessão ausente. Um POST sem os cookies da página pode falhar, mesmo com um token válido.
- **Alguns sites precisam de
rqdata.** Se a página fornece um valorrqdatapara o widget, passe-o na requisição no campo opcionalrqdata. - Widget invisível. Se não há caixa de marcação e o site inicia o widget pelo próprio código, adicione
"is_invisible": trueà requisição. O guia de captcha invisível mostra como devolver o token.
Teste grátis
Crie uma conta e comece com crédito de teste grátis, sem cartão. Rode o exemplo acima em um formulário seu antes de integrá-lo a um trabalho maior. Para saber quanto custa a resolução em volume, veja a página de preços.
Registrando cada resolução
Registre uma linha por resolução: o sitekey, o host da página, o errorId, o errorCode em caso de falha e quanto tempo a chamada levou. Deixe de fora a chave de API e qualquer senha de proxy. Essas linhas mostram se uma execução lenta é lenta por causa da página, do proxy ou do solver. Também são a primeira coisa de que você vai precisar se abrir um chamado de suporte.
Resolvendo em loop
Se o seu script resolve muitos captchas em sequência, mantenha o laço simples. Resolva, envie, verifique o resultado e só então siga em frente. Não resolva antecipadamente nem enfileire tokens, porque cada um expira em cerca de dois minutos. Uma pequena pausa entre as resoluções no mesmo site mantém a sua taxa de requisições próxima do que um humano produziria.