Toda requisição de resolução de reCAPTCHA enviada à API da CaptchaAI depende de dois dados mínimos: a sitekey certa (a chave pública do widget) e a URL exata da página testada.
Errar a versão do action, esquecer o data-s ou não marcar a flag enterprise costuma causar falha de validação do lado do Google, não da CaptchaAI — e o sintoma é sempre o mesmo: a task não resolve. Este guia reúne os quatro métodos práticos para extrair esses parâmetros do código-fonte, do script de carregamento ou da renderização em JavaScript, fechando com uma função Python completa para o seu pipeline de QA.
Use estes métodos apenas em páginas que você tem autorização para testar — ambiente próprio, staging ou contas de QA.
Os quatro métodos, em ordem de prioridade
Nem todo site expõe a sitekey do mesmo jeito. Use esta ordem como checklist — é a mesma sequência que a função completa deste guia percorre automaticamente:
- Atributos HTML (
data-sitekey) — funciona sem navegador na maioria dos sites. - Tag de script — necessário para reCAPTCHA v3 e Enterprise.
- Src do iframe — cobre widgets montados manualmente, sem a biblioteca oficial do Google.
- Renderização via
grecaptcha.render()— para páginas que montam o widget de forma dinâmica.
Método 1: extrair pelos atributos HTML
Quando o widget do reCAPTCHA é renderizado no HTML estático, os atributos data-* já trazem tudo o que você precisa — nenhum navegador é necessário.
Pelo atributo data-sitekey. O caminho mais direto é buscar data-sitekey no HTML com requests e regex, conferindo também se o widget é invisível e se há callback configurado:
import re
import requests
url = "https://staging.example.com/qa-login"
html = requests.get(url).text
# Find data-sitekey
match = re.search(r'data-sitekey=["\']([A-Za-z0-9_-]+)["\']', html)
if match:
sitekey = match.group(1)
print(f"Sitekey: {sitekey}")
# Check if invisible
invisible_match = re.search(r'data-size=["\']invisible["\']', html)
is_invisible = bool(invisible_match)
print(f"Invisible: {is_invisible}")
# Find callback
callback_match = re.search(r'data-callback=["\'](\w+)["\']', html)
callback = callback_match.group(1) if callback_match else None
print(f"Callback: {callback}")
# Check for data-s (Google-owned sites)
data_s_match = re.search(r'data-s=["\']([^"\']+)["\']', html)
data_s = data_s_match.group(1) if data_s_match else None
print(f"data-s: {data_s}")
Via Puppeteer, quando o JavaScript monta o widget. Se a página monta o widget depois do carregamento inicial — comum em React ou Vue —, o HTML bruto não mostra nada. Use o Puppeteer para renderizar a página e ler os atributos direto do DOM:
const puppeteer = require('puppeteer');
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://staging.example.com/qa-login', { waitUntil: 'networkidle2' });
const params = await page.evaluate(() => {
const widget = document.querySelector('.g-recaptcha');
if (!widget) return null;
return {
sitekey: widget.getAttribute('data-sitekey'),
size: widget.getAttribute('data-size'),
callback: widget.getAttribute('data-callback'),
dataS: widget.getAttribute('data-s'),
invisible: widget.getAttribute('data-size') === 'invisible',
};
});
console.log(params);
Método 2: extrair pela tag de script
reCAPTCHA v3 e Enterprise não desenham widget visível, então os atributos data-* não existem. A sitekey e o modo Enterprise aparecem na tag <script> que carrega a biblioteca do Google.
Sitekey de v3 e Enterprise. A sitekey do v3 vem embutida no parâmetro render da URL do script:
# Find sitekey from script src
v3_match = re.search(
r'recaptcha/(?:api|enterprise)\.js\?.*?render=([A-Za-z0-9_-]+)',
html
)
if v3_match:
sitekey = v3_match.group(1)
print(f"v3 Sitekey: {sitekey}")
# Check enterprise
is_enterprise = 'enterprise.js' in html
print(f"Enterprise: {is_enterprise}")
O parâmetro action. Ele não fica em nenhum atributo HTML — é passado como argumento na chamada grecaptcha.execute(), dentro do próprio JavaScript da página:
# Search for grecaptcha.execute calls
action_match = re.search(
r'grecaptcha\.execute\s*\([^,]+,\s*\{[^}]*action\s*:\s*["\']([^"\']+)',
html
)
if action_match:
action = action_match.group(1)
print(f"Action: {action}")
Método 3: extrair pelo src do iframe
Alguns sites incorporam o reCAPTCHA sem carregar a biblioteca oficial do Google, montando o iframe manualmente. Nesse caso, a sitekey aparece no parâmetro k da própria URL do iframe:
# Find reCAPTCHA iframe
iframe_match = re.search(
r'<iframe[^>]+src=["\']([^"\']*recaptcha/api2/anchor[^"\']*)["\']',
html
)
if iframe_match:
iframe_src = iframe_match.group(1)
sitekey_match = re.search(r'k=([A-Za-z0-9_-]+)', iframe_src)
if sitekey_match:
sitekey = sitekey_match.group(1)
print(f"Iframe sitekey: {sitekey}")
Método 4: extrair via renderização dinâmica em JavaScript
Sites que chamam grecaptcha.render() explicitamente passam a sitekey, o callback e o tamanho como um objeto de configuração no próprio JavaScript:
# Find grecaptcha.render calls
render_match = re.search(
r'grecaptcha\.render\s*\([^,]*,\s*\{([^}]+)\}',
html
)
if render_match:
config = render_match.group(1)
sk = re.search(r'sitekey\s*:\s*["\']([A-Za-z0-9_-]+)', config)
cb = re.search(r'callback\s*:\s*["\']?(\w+)', config)
sz = re.search(r'size\s*:\s*["\'](\w+)', config)
print(f"Sitekey: {sk.group(1) if sk else 'not found'}")
print(f"Callback: {cb.group(1) if cb else 'not found'}")
print(f"Size: {sz.group(1) if sz else 'not found'}")
Quais parâmetros o reCAPTCHA exige em cada versão
Use esta tabela como checklist final antes de montar a requisição — ela resume o que cada versão exige.
| Parâmetro | v2 padrão | v2 invisível | v3 | Enterprise |
|---|---|---|---|---|
googlekey (sitekey) |
Obrigatório | Obrigatório | Obrigatório | Obrigatório |
pageurl |
Obrigatório | Obrigatório | Obrigatório | Obrigatório |
invisible |
- | 1 |
- | - |
action |
- | - | Obrigatório | Às vezes |
data-s |
Às vezes | Às vezes | - | - |
enterprise |
- | - | - | 1 |
Função completa de extração
Raramente dá para saber de antemão qual método vai funcionar em um site novo. A função abaixo tenta todos na mesma ordem de prioridade até encontrar uma sitekey válida, e devolve tudo pronto para a chamada à API:
import re
import requests
def extract_recaptcha_params(url):
html = requests.get(url, timeout=15).text
params = {"pageurl": url}
# Sitekey from data-sitekey
sk = re.search(r'data-sitekey=["\']([A-Za-z0-9_-]+)', html)
if sk:
params["sitekey"] = sk.group(1)
# Sitekey from script render parameter (v3)
if "sitekey" not in params:
v3 = re.search(r'render=([A-Za-z0-9_-]{20,})', html)
if v3:
params["sitekey"] = v3.group(1)
# Sitekey from iframe
if "sitekey" not in params:
iframe = re.search(r'recaptcha.*?k=([A-Za-z0-9_-]+)', html)
if iframe:
params["sitekey"] = iframe.group(1)
# Sitekey from grecaptcha.render
if "sitekey" not in params:
render = re.search(r'sitekey\s*:\s*["\']([A-Za-z0-9_-]+)', html)
if render:
params["sitekey"] = render.group(1)
# Version detection
if re.search(r'data-size=["\']invisible', html):
params["invisible"] = True
if 'enterprise.js' in html:
params["enterprise"] = True
# Action (v3)
action = re.search(
r'action\s*:\s*["\']([^"\']+)',
html[html.find('grecaptcha.execute'):] if 'grecaptcha.execute' in html else ''
)
if action:
params["action"] = action.group(1)
# data-s
ds = re.search(r'data-s=["\']([^"\']+)', html)
if ds:
params["data_s"] = ds.group(1)
# Callback
cb = re.search(r'data-callback=["\'](\w+)', html)
if cb:
params["callback"] = cb.group(1)
return params
# Usage
params = extract_recaptcha_params("https://staging.example.com/qa-login")
for k, v in params.items():
print(f" {k}: {v}")
Resultado esperado:
pageurl: https://staging.example.com/qa-login
sitekey: 6Le-SITEKEY-abc123
invisible: True
callback: onCaptchaComplete
Como enviar os parâmetros extraídos para a CaptchaAI
Com params preenchido, monte o corpo da requisição para o endpoint in.php, incluindo só os campos que a versão detectada precisa:
data = {
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": params["sitekey"],
"pageurl": params["pageurl"],
"json": "1",
}
if params.get("invisible"):
data["invisible"] = "1"
if params.get("enterprise"):
data["enterprise"] = "1"
if params.get("action"):
data["action"] = params["action"]
if params.get("data_s"):
data["data-s"] = params["data_s"]
resp = requests.post("https://ocr.captchaai.com/in.php", data=data).json()
Problemas comuns na extração e como resolver
Estes são os erros mais frequentes ao automatizar essa extração em produção:
- Nenhuma sitekey encontrada — a página usa renderização dinâmica; use Puppeteer ou Selenium em vez de HTML estático.
- Sitekey errada — várias instâncias de reCAPTCHA na mesma página; confira qual widget corresponde ao formulário que você está enviando.
- Action não encontrado — definido em um arquivo JS externo; baixe e pesquise nos arquivos JavaScript vinculados.
data-smuda a cada requisição — o Google regenera o valor; extraia umdata-snovo antes de cada envio.
Contexto para quem testa a partir do Brasil
Se os workers de QA rodam a partir de sa-east-1 (São Paulo) na AWS, a latência extra para buscar HTML hospedado nos EUA ou na Europa fica na casa de poucas centenas de milissegundos — irrelevante perto do tempo de resolução do CAPTCHA.
O ponto que merece atenção é outro: ao salvar HTML capturado para depuração ou logs de teste, revise com cuidado o que está sendo armazenado e por quanto tempo.
A LGPD se aplica à coleta e retenção de dados de páginas de terceiros, sobretudo quando a página capturada tem formulários com campos de usuário. Trate HTML de QA como dado sensível.
Perguntas frequentes
Preciso abrir um navegador para extrair a sitekey?
Não. Na maioria dos sites a sitekey já vem no HTML estático — dá para extrair só com requests e regex. Um navegador headless com Puppeteer ou Selenium só entra em cena quando o widget é montado via JavaScript, como em single-page applications.
A sitekey é a mesma coisa que a chave de API da CaptchaAI?
Não. A sitekey é pública, pertence ao site que exibe o reCAPTCHA e fica visível no código-fonte. A chave de API é privada, pertence à sua conta na CaptchaAI e nunca deve aparecer em HTML nem em repositórios públicos.
Por que o data-s muda a cada carregamento da página?
O Google regenera esse valor a cada requisição em sites com reCAPTCHA vinculado à própria conta Google. Extraia um data-s novo logo antes de cada envio à CaptchaAI — reaproveitar um valor antigo derruba a taxa de sucesso.
Como sei se o site usa reCAPTCHA v3 ou Enterprise em vez do v2?
v3 e Enterprise não têm widget visível — não existe checkbox nem quebra-cabeça na tela. Procure na URL do script: recaptcha/enterprise.js indica Enterprise; o parâmetro render= na URL de recaptcha/api.js indica v3.
É seguro rodar essa extração contra páginas de terceiros?
Só em ambientes que você tem autorização para testar — staging, contas próprias de QA ou páginas configuradas para isso. Ao registrar HTML capturado, considere as obrigações da LGPD sobre retenção e descarte desses dados.
Envie os parâmetros para a CaptchaAI e resolva com confiança
Depois de extrair sitekey, action, data-s e a flag enterprise, monte a requisição para a API da CaptchaAI. Crie sua chave em captchaai.com — o plano BASIC (US$ 15/mês, 5 threads) já é suficiente para validar o fluxo antes de escalar.
Guias relacionados
- Detecção de CAPTCHA pelo console do navegador
- Como funciona o callback do reCAPTCHA v2
- reCAPTCHA v2 Invisível: como detectar o gatilho