API Tutorials

Parâmetro reCAPTCHA Data-S explicado

Se a sua integração devolve invalid-input-response em um reCAPTCHA aparentemente comum, a resposta costuma estar em um atributo que quase ninguém procura: data-s. É um token de sessão que o Google injeta no widget em algumas páginas e que precisa viajar junto na requisição. A regra cabe em três linhas:

  • Leia o atributo data-s no widget antes de enviar a tarefa.
  • Se ele existir, inclua o campo na requisição para in.php.
  • Se não existir, envie só sitekey e pageurl — nada de campo vazio.

Em quais páginas o data-s aparece

Delimitar o escopo economiza horas de depuração: o data-s não existe na maioria das integrações de reCAPTCHA.

Onde Frequência Observação
Google Search (página de "tráfego incomum") Sempre Sem data-s a resolução não fecha
YouTube Às vezes Aparece em alguns fluxos de verificação
Google Play Às vezes Verificação de listagem de aplicativos
Google Forms Raramente Implementações pontuais
Sites de terceiros com reCAPTCHA Praticamente nunca A integração padrão usa só sitekey e pageurl

Se o seu pipeline de QA roda contra formulários próprios em staging.example.com, você provavelmente nunca verá o parâmetro. Ele vira assunto quando a requisição esbarra em uma propriedade do Google.


O que é o parâmetro data-s

Um token gerado pelo servidor e embutido no HTML do widget. Amarra o desafio a uma sessão, como um nonce. Cinco características definem o comportamento dele:

  • Formato: string em Base64, de 200 a 500 caracteres.
  • Validade: uso único, atrelado ao carregamento atual.
  • Escopo: específico da sessão, nunca reaproveitável.
  • Obrigatoriedade: vale sempre que o atributo existir no widget.
  • Renovação: valor novo a cada refresh.

Onde ele fica no HTML

<!-- reCAPTCHA widget with data-s parameter -->
<div class="g-recaptcha"
     data-sitekey="6LcR_RsTAAAAAN_r0GEkGBfq3L7KmU5JbPHJtwNp"
     data-s="AB2grfE8_kyMp3XYRuJo5c..."
     data-callback="onCaptchaSolved">
</div>

O atributo fica ao lado do data-sitekey, no mesmo <div> do widget.


Como o data-s se encaixa no fluxo de resolução

O caminho abaixo mostra por onde o valor passa até a validação no Google.

User triggers CAPTCHA (e.g., Google flags unusual search traffic)
    ↓
Google serves a CAPTCHA page with:

  - data-sitekey (site key, same for all Google search CAPTCHAs)
  - data-s (session token, unique per page load)
    ↓
reCAPTCHA widget initializes with both parameters
    ↓
Challenge completion generates a g-recaptcha-response token
    ↓
Token is submitted alongside the session reference
    ↓
Google validates token + session binding
    ↓
If data-s was not used during solving: "invalid-input-response" or silent failure

A linha final é a que importa: sem o data-s, o token é gerado mas não corresponde à sessão esperada. A falha é silenciosa e o sintoma engana — parece problema de sitekey.


Cinco erros que geram falha silenciosa

Erro Sintoma Correção
Omitir o data-s quando ele existe O token é aceito pela API, mas falha na validação Verifique o atributo antes de montar a requisição
Enviar data-s quando o widget não tem o atributo Erro do solucionador ou requisição recusada Inclua o campo somente se o atributo existir
Reaproveitar o valor entre carregamentos Token inválido Extraia um valor novo a cada carregamento
Aplicar URL-encoding no valor Parâmetro malformado Envie a string Base64 crua, sem codificação extra
Usar um valor extraído minutos antes Incompatibilidade de sessão Extraia imediatamente antes de enviar a tarefa

Os dois primeiros respondem pela maior parte dos chamados de suporte.


Como extrair o data-s da página

Três caminhos, do mais barato ao mais caro: HTML bruto em Python, HTML bruto em Node.js e navegador automatizado.

Extração com Python

import requests
from bs4 import BeautifulSoup
import re

def extract_recaptcha_params(url):
    """Extract reCAPTCHA parameters including data-s from a page."""
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                      "AppleWebKit/537.36 (KHTML, like Gecko) "
                      "Chrome/120.0.0.0 Safari/537.36",
    }

    response = requests.get(url, headers=headers, timeout=15)
    soup = BeautifulSoup(response.text, "html.parser")

    # Find reCAPTCHA widget div
    widget = soup.find("div", class_="g-recaptcha")
    if not widget:
        # Try finding by data-sitekey attribute
        widget = soup.find(attrs={"data-sitekey": True})

    if not widget:
        return {"error": "No reCAPTCHA widget found"}

    params = {
        "sitekey": widget.get("data-sitekey"),
        "data_s": widget.get("data-s"),
        "callback": widget.get("data-callback"),
        "size": widget.get("data-size"),
        "has_data_s": widget.get("data-s") is not None,
    }

    return params

# Example: Google "unusual traffic" page
params = extract_recaptcha_params("https://www.google.com/sorry/index")
print(params)
# {
#   "sitekey": "6LfwuyUT...",
#   "data_s": "AB2grfE8_kyMp3...",
#   "has_data_s": True
# }

A chave has_data_s centraliza a decisão de incluir ou não o campo.

Extração com Node.js

const axios = require("axios");
const cheerio = require("cheerio");

async function extractRecaptchaParams(url) {
    const { data: html } = await axios.get(url, {
        headers: {
            "User-Agent":
                "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " +
                "AppleWebKit/537.36 (KHTML, like Gecko) " +
                "Chrome/120.0.0.0 Safari/537.36",
        },
        timeout: 15000,
    });

    const $ = cheerio.load(html);
    const widget = $(".g-recaptcha, [data-sitekey]").first();

    if (widget.length === 0) {
        return { error: "No reCAPTCHA widget found" };
    }

    return {
        sitekey: widget.attr("data-sitekey"),
        dataS: widget.attr("data-s") || null,
        callback: widget.attr("data-callback") || null,
        hasDataS: !!widget.attr("data-s"),
    };
}

extractRecaptchaParams("https://www.google.com/sorry/index")
    .then(console.log);

Extração com Selenium, para páginas dinâmicas

Quando a página monta o widget por JavaScript, ler o HTML bruto não basta. Abra a página no navegador automatizado e leia o valor depois da renderização.

from selenium import webdriver
from selenium.webdriver.common.by import By

def extract_data_s_selenium(driver, url):
    """Extract data-s from a dynamically loaded reCAPTCHA page."""
    driver.get(url)

    # Wait for reCAPTCHA widget to load
    import time
    time.sleep(3)

    try:
        widget = driver.find_element(By.CSS_SELECTOR, ".g-recaptcha, [data-sitekey]")
        return {
            "sitekey": widget.get_attribute("data-sitekey"),
            "data_s": widget.get_attribute("data-s"),
        }
    except Exception:
        return {"error": "Widget not found"}

Como enviar o data-s à API da CaptchaAI

Com o valor em mãos, o envio muda pouco: você acrescenta um campo à requisição para in.php e segue com o polling de sempre em res.php.

Python

import requests
import time

API_KEY = "YOUR_API_KEY"

# Step 1: Extract parameters from the CAPTCHA page
sitekey = "6LfwuyUTAAAAAOAmoS0fdqijC2PbbdH4kjq62Y1b"
data_s = "AB2grfE8_kyMp3XYRuJo5c..."  # Extracted from data-s attribute
page_url = "https://www.google.com/sorry/index?continue=..."

# Step 2: Submit to CaptchaAI WITH data-s
submit = requests.post("https://ocr.captchaai.com/in.php", data={
    "key": API_KEY,
    "method": "userrecaptcha",
    "googlekey": sitekey,
    "pageurl": page_url,
    "data-s": data_s,  # Include data-s parameter
    "json": 1,
})

task_id = submit.json()["request"]

# Step 3: Poll for result
for _ 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"Token: {token[:60]}...")
        # Submit this token to the Google CAPTCHA form
        break

Node.js

const axios = require("axios");

async function solveWithDataS(sitekey, dataS, pageUrl) {
    const API_KEY = "YOUR_API_KEY";

    // Submit with data-s
    const { data: submit } = await axios.post(
        "https://ocr.captchaai.com/in.php",
        new URLSearchParams({
            key: API_KEY,
            method: "userrecaptcha",
            googlekey: sitekey,
            pageurl: pageUrl,
            "data-s": dataS,
            json: 1,
        })
    );

    const taskId = submit.request;

    // Poll
    for (let i = 0; i < 60; i++) {
        await new Promise((r) => setTimeout(r, 5000));
        const { data: result } = await axios.get(
            "https://ocr.captchaai.com/res.php",
            {
                params: {
                    key: API_KEY,
                    action: "get",
                    id: taskId,
                    json: 1,
                },
            }
        );

        if (result.status === 1) {
            return result.request;
        }
    }

    throw new Error("Timeout");
}

Uma observação para times no Brasil: em workers em sa-east-1 (São Paulo), o RTT soma alguns milissegundos ao polling, mas não muda a regra. O que quebra é o intervalo entre extrair o atributo e enviar a tarefa, não a latência de rede.


Um extrator reutilizável para os dois casos

Em vez de espalhar if pelo código, isole a decisão em uma classe que monta o payload com ou sem data-s. O mesmo worker atende os dois cenários sem ramificação no chamador.

import requests
from bs4 import BeautifulSoup

class RecaptchaExtractor:
    """Extract reCAPTCHA parameters from any page."""

    def __init__(self, url, session=None):
        self.url = url
        self.session = session or requests.Session()
        self.params = None

    def extract(self):
        """Extract sitekey, data-s, and other parameters."""
        headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                          "AppleWebKit/537.36 (KHTML, like Gecko) "
                          "Chrome/120.0.0.0 Safari/537.36",
        }

        response = self.session.get(self.url, headers=headers, timeout=15)
        soup = BeautifulSoup(response.text, "html.parser")

        widget = soup.find(attrs={"data-sitekey": True})
        if not widget:
            raise ValueError("No reCAPTCHA widget found on page")

        self.params = {
            "sitekey": widget["data-sitekey"],
            "pageurl": self.url,
        }

        # Include data-s only if present
        data_s = widget.get("data-s")
        if data_s:
            self.params["data-s"] = data_s

        return self.params

    def build_solver_payload(self, api_key):
        """Build CaptchaAI submission payload with correct parameters."""
        if not self.params:
            self.extract()

        payload = {
            "key": api_key,
            "method": "userrecaptcha",
            "googlekey": self.params["sitekey"],
            "pageurl": self.params["pageurl"],
            "json": 1,
        }

        # Only include data-s when it exists
        if "data-s" in self.params:
            payload["data-s"] = self.params["data-s"]

        return payload


# Usage
extractor = RecaptchaExtractor("https://www.google.com/sorry/index?continue=...")
payload = extractor.build_solver_payload("YOUR_API_KEY")
# payload includes data-s only when present on the page

É o padrão que recomendamos para pipelines de QA autorizado: o extrator decide sozinho e o chamador nunca precisa saber se a página era do Google.


Perguntas frequentes

As dúvidas que mais aparecem quando o parâmetro entra no pipeline.

Como sei se a página exige data-s antes de escrever o código?

Abra o DevTools, inspecione o elemento com a classe g-recaptcha e procure o data-s ao lado do data-sitekey. Se não estiver lá, não existe nesse fluxo — uma checagem de dez segundos que evita horas de depuração.

O data-s expira junto com o token do reCAPTCHA?

Não são o mesmo relógio. O data-s vale para o carregamento em que foi gerado; o g-recaptcha-response tem sua própria janela depois de resolvido. Trate os dois como perecíveis: extraia, resolva e envie na mesma execução.

Preciso de um plano específico da CaptchaAI para enviar data-s?

Não. O campo faz parte da requisição padrão de userrecaptcha e está em todos os planos, do BASIC (US$ 15/mês, 5 threads) ao VIP-3 (US$ 7.500/mês, 5.000 threads). O plano define só quantas resoluções simultâneas você tem.

O data-s também existe no reCAPTCHA v3?

O parâmetro é específico do reCAPTCHA em propriedades do Google, e o fluxo do v3 não expõe um widget com esse atributo. Não transporte o campo entre tipos de desafio.

Posso guardar o data-s em cache para reduzir requisições?

Não vale a tentativa. Cada carregamento gera um valor novo, e um valor guardado é, por definição, de outra sessão. O ganho real vem de reduzir o intervalo entre extração e envio.


Em resumo

O data-s aparece em poucas implementações do reCAPTCHA, quase sempre em propriedades do Google. Quando está no widget, extraia o valor e inclua-o na requisição à CaptchaAI; quando não está, envie só sitekey e pageurl.

Artigos relacionados

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