Solver de captcha com Selenium em Python: exemplo funcional (2026)
O Selenium roda um navegador real, então a página é renderizada e os scripts são executados como fariam para uma pessoa. A única etapa que ele não consegue fazer é resolver o widget PopularCaptcha. Este guia acrescenta essa etapa: ler o sitekey da página renderizada, obter um token com uma chamada de API, colocar o token no formulário e enviar.
Ele cobre o widget PopularCaptcha, que a Scarnox resolve hoje em modo proxyless. Comece com crédito de teste grátis, sem cartão e teste o script em um formulário de teste antes de tudo.
O que o Selenium precisa fazer
O fluxo tem quatro partes:
- Carregar a página e esperar o widget ser renderizado.
- Ler o atributo
data-sitekeydo widget. - Obter um token da API e colocá-lo no formulário.
- Enviar o formulário antes que o token expire.
A terceira etapa é a única que toca no captcha. Todo o resto é trabalho normal com Selenium.
Instale os pacotes
pip install selenium requests
O Selenium 4.6 e versões posteriores encontram um ChromeDriver compatível por conta própria, então você não precisa baixar o driver manualmente.
O script completo
import requests
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
API_KEY = "scarnox_YOURAPIKEY"
API_URL = "https://api.scarnox.com/api/tasks/create"
PAGE_URL = "https://example.com/signup"
def solve(sitekey: str, page_url: str, invisible: bool = False) -> str:
body = {
"captcha_type": "PopularCaptchaTaskProxyless",
"site_key": sitekey,
"site_url": page_url,
}
if invisible:
body["is_invisible"] = True
r = requests.post(
API_URL,
headers={"Authorization": f"Bearer {API_KEY}"},
json=body,
timeout=185, # 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"]
INJECT_TOKEN_JS = """
const token = arguments[0];
let field = document.querySelector('[name="h-captcha-response"]');
if (!field) {
field = document.createElement("textarea");
field.name = "h-captcha-response";
field.style.display = "none";
document.querySelector("form").appendChild(field);
}
field.value = token;
let extra = document.querySelector('[name="g-recaptcha-response"]');
if (!extra) {
extra = document.createElement("textarea");
extra.name = "g-recaptcha-response";
extra.style.display = "none";
document.querySelector("form").appendChild(extra);
}
extra.value = token;
"""
def main() -> None:
driver = webdriver.Chrome()
try:
driver.get(PAGE_URL)
widget = WebDriverWait(driver, 15).until(
EC.presence_of_element_located((By.CSS_SELECTOR, "[data-sitekey]"))
)
sitekey = widget.get_attribute("data-sitekey")
invisible = widget.get_attribute("data-size") == "invisible"
token = solve(sitekey, driver.current_url, invisible=invisible)
# Preencha os outros campos antes, depois injete o token logo antes do envio,
# porque o token expira em cerca de dois minutos.
driver.find_element(By.NAME, "email").send_keys("you@example.com")
driver.execute_script(INJECT_TOKEN_JS, token)
driver.find_element(By.CSS_SELECTOR, "form button[type=submit]").click()
WebDriverWait(driver, 15).until(EC.url_changes(PAGE_URL))
print("Submitted. Now at:", driver.current_url)
finally:
driver.quit()
if __name__ == "__main__":
main()
O script não precisa de proxy para uma resolução proxyless do PopularCaptcha. Deixe de fora o campo de proxy e deixe o site ver a sua conexão normal.
A ordem das operações é a parte que mais dá errado. Preencha o restante do formulário primeiro, depois resolva, depois injete, depois clique. Se você resolver antes de digitar nos outros campos, uma página ou um formulário lento pode fazer o envio passar da validade do token. Mantenha a diferença entre a resolução e o clique o mais curta possível, e verifique a página de resultado por erros antes de presumir que o captcha passou.
Por que o token é inserido com JavaScript
A maioria dos widgets PopularCaptcha grava o token em um textarea oculto chamado h-captcha-response quando uma pessoa os resolve. Como o Selenium não tem uma pessoa, o script grava o mesmo campo por conta própria. O trecho INJECT_TOKEN_JS faz duas coisas:
- Reutiliza o textarea caso o widget já tenha criado um.
- Cria o textarea caso a página não o tenha feito, e o acrescenta ao formulário.
Ele também preenche g-recaptcha-response, porque muitos sites leem esse nome por compatibilidade.
Widgets invisíveis
Um widget invisível não tem caixa de marcação. Ele roda em segundo plano e costuma ser disparado no envio do formulário. O script verifica data-size="invisible" e envia is_invisible: true quando o encontra. Alguns sites também associam uma função de callback JavaScript ao widget. Se o formulário continuar parado depois que você injeta o token, procure um atributo data-callback e chame essa função com o token. Nosso guia sobre captcha invisível cobre esse caso.
Usando em testes
O Selenium também é a ferramenta usual para testes end-to-end. Se o seu site de homologação exibe um captcha, o mesmo código permite que um teste passe por ele. Mantenha o ambiente de teste separado da produção, e não rode testes contra sites que você não controla. A configuração para suítes de teste está em captcha em testes automatizados.
Problemas comuns
- O widget nunca aparece. Aumente a espera, ou verifique se o widget está dentro de um iframe. Se estiver, mude para o frame primeiro com
driver.switch_to.frame(...). - O formulário é enviado, mas o site rejeita o token. Confira se você enviou o token para a página em que o widget foi exibido. O
driver.current_urlprecisa corresponder à URL real da página, incluindo a query string. - O token expirou. Aproxime a chamada de
solveda etapa de envio. O token dura cerca de dois minutos. - Erro de timeout da API. Use um timeout de cerca de 185 segundos, como no script. A lógica de novas tentativas está em tratamento de erros do solver de captcha.
Preços
Você paga por resolução bem-sucedida. Resoluções que falham não são cobradas. Veja a página de preços para as tarifas, e comece com crédito de teste grátis, sem cartão.