API-Tutorials

reCAPTCHA Data-S-Parameter erklärt

Der Solver liefert ein Token, die Zielseite weist es ab, und im Log steht nur invalid-input-response: Bei CAPTCHAs auf Google-Domains steckt dahinter fast immer ein fehlender data-s-Parameter. data-s ist ein Sitzungstoken, das Google zusätzlich zum Sitekey in das reCAPTCHA-Widget schreibt. Wer es beim Lösen weglässt, bekommt ein formal korrektes, für diese Sitzung aber wertloses Token. Kurz gefasst:

  • data-s erscheint fast ausschließlich auf Google-Domains, allen voran auf der /sorry-Seite der Google-Suche.
  • Ist das Attribut im Widget vorhanden, gehört es in die Solver-Anfrage; fehlt es, bleibt das Feld weg.
  • Der Wert gilt nur für einen Seitenaufruf und wird unmittelbar vor der Übermittlung frisch ausgelesen.

Wann reCAPTCHA einen data-s-Parameter mitschickt

Zuerst die Entwarnung: Die meisten reCAPTCHA-Integrationen kennen kein data-s. Der Parameter ist ein Google-Hausmittel und begegnet Ihnen vor allem hier:

Seite Häufigkeit Hinweis
Google-Suche (/sorry, „ungewöhnlicher Datenverkehr“) immer ohne data-s kein gültiges Token
YouTube gelegentlich bei bestimmten Verifizierungs-Flows
Google Play gelegentlich Prüfung von App-Einträgen
Google Formulare selten nur einzelne Implementierungen
Fremdseiten mit reCAPTCHA so gut wie nie Standardintegrationen kommen ohne aus

Daraus folgen zwei Praxisregeln:

  • Außerhalb der Google-Domains genügen sitekey und pageurl.
  • Kommen ausgerechnet bei einer Google-Suchseite ungültige Token zurück, prüfen Sie zuerst das Widget auf data-s.

Ein typisches Szenario aus dem DACH-Raum: Ein Rank-Tracking-Dienst betreibt seine Worker auf VPS-Instanzen bei Hetzner, netcup oder IONOS. Rechenzentrums-IPs fallen schneller auf als Büroanschlüsse, entsprechend häufig landet eine Anfrage auf der /sorry-Seite – also bei einem reCAPTCHA mit data-s. Bildet der Client diesen Fall nicht ab, sinkt die Erfolgsquote, obwohl der Sitekey stimmt.

Hinweis: Prüfen Sie vor automatisierten Abrufen die Nutzungsbedingungen der Zielseite. Werden dabei personenbezogene Daten wie IP-Adressen verarbeitet, klären Sie die DSGVO-Grundlage vorab.


Was der Parameter technisch ist

data-s ist ein serverseitig erzeugtes Sitzungstoken, das direkt im HTML des Widgets steht. Es bindet die CAPTCHA-Abfrage an genau eine Server-Sitzung und verhindert die Wiederverwendung eines gelösten Tokens in anderem Kontext.

So sieht das Widget im Quelltext aus

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

Das Attribut steht im selben <div> wie data-sitekey.

Eigenschaften auf einen Blick

  • Format: Base64-Zeichenkette, 200–500 Zeichen
  • Lebensdauer: einmalig, gebunden an den aktuellen Seitenaufruf
  • Gültigkeitsbereich: sitzungsspezifisch, nicht über mehrere Aufrufe hinweg nutzbar
  • Pflichtfeld: ja, sobald vorhanden – sonst schlägt die Lösung fehl
  • Erneuerung: neuer Wert bei jedem Laden oder Neuladen der Seite

Sitzungsbindung: der Ablauf im Detail

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

Funktional ist data-s eine Nonce: Der Solver muss den Wert bereits beim Erzeugen des Tokens kennen. Fehlt er, entsteht ein g-recaptcha-response-Token, das die Validierung verwirft – meist ohne aussagekräftige Fehlermeldung.


data-s aus der Seite auslesen

Mit Python und BeautifulSoup

Liefert der Server das Widget bereits im HTML aus, genügt ein GET-Request: Der Helfer liest Sitekey, data-s und Callback in einem Durchgang aus.

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
# }

Mit Node.js und Cheerio

Dieselbe Logik im Node.js-Stack – Cheerio übernimmt hier die Rolle von BeautifulSoup.

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);

Mit Selenium bei dynamisch aufgebauten Seiten

Baut die Seite das Widget erst per JavaScript auf, fehlt das Attribut im ausgelieferten HTML. Selenium liest den Wert dann nach dem Rendern aus dem DOM.

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"}

reCAPTCHA mit data-s über CaptchaAI lösen

Der Ablauf bleibt der gewohnte Dreischritt; neu ist allein ein Feld in der Payload:

  1. Sitekey und data-s aus dem Widget extrahieren.
  2. Aufgabe an in.php übermitteln – mit data-s im Formular.
  3. Ergebnis über res.php abfragen, bis das Token vorliegt.

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");
}

Das zurückgegebene Token gehört danach zügig in das Formularfeld der geladenen Seite – reCAPTCHA-Token sind nur rund 120 Sekunden gültig.


Ein Extractor für beide Fälle

Zwei Codepfade – einen mit, einen ohne Sitzungstoken – pflegt niemand gern. Die folgende Klasse liest die Parameter einmal aus und hängt data-s nur an, wenn es im Widget steht.

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

Fünf Fehler, die immer wieder auftreten

Fehler Symptom Lösung
data-s weggelassen, obwohl vorhanden Token wird stillschweigend abgelehnt vor jedem Absenden prüfen
data-s mitgeschickt, obwohl nicht vorhanden Fehler oder abgewiesene Anfrage nur setzen, wenn es im Widget steht
Denselben Wert mehrfach genutzt ungültiges Token pro Seitenaufruf frisch extrahieren
Wert zusätzlich URL-codiert fehlerhafter Parameter rohen Base64-Wert übergeben
Veralteter Wert, Seite vor Minuten geladen Token passt nicht zur Sitzung direkt vor der Übermittlung extrahieren

Häufige Fragen

Wie erkenne ich, ob eine Seite data-s verwendet?

Suchen Sie im gerenderten HTML nach data-s= innerhalb des g-recaptcha-Containers. Zuverlässiger als der Blick in den Browser ist eine Prüfung im Code: Attribut auslesen und pro Aufruf protokollieren – dann ist im Log sofort sichtbar, woran ein Fehlerbild hängt.

Gilt data-s auch für reCAPTCHA v3 oder Enterprise?

In der Regel nein. Das Attribut gehört zum Widget-Markup von reCAPTCHA v2; v3 arbeitet mit action und Score. CaptchaAI löst v2, v2 Invisible, v2 Callback, v2 Enterprise, v3 und v3 Enterprise über dieselbe Methode userrecaptcha – nur die Zusatzfelder unterscheiden sich.

Muss ich den Wert vor dem Senden codieren?

Nein. Übergeben Sie die Base64-Zeichenkette exakt so, wie sie im Attribut steht. Bibliotheken wie requests oder axios kodieren Formularfelder ohnehin selbst; eine zusätzliche Runde URL-Encoding erzeugt einen Wert, den die Gegenseite nicht mehr zuordnen kann.

Kostet eine Lösung mit data-s mehr als ein einfaches reCAPTCHA?

Nein. CaptchaAI rechnet Thread-basiert ab, nicht pro Lösung: Bezahlt werden gleichzeitig laufende Threads, jeder löst im Abrechnungsmonat unbegrenzt viele CAPTCHAs. Von BASIC (15 $/Monat, 5 Threads) bis VIP-3 (7.500 $/Monat, 5.000 Threads) ändert sich allein die Parallelität; Aufschläge nach CAPTCHA-Typ gibt es nicht. (Preise in US-Dollar.)


Fazit

data-s begegnet Ihnen praktisch nur auf Google-eigenen Domains. Ist das Attribut vorhanden, lesen Sie es aus dem Widget-HTML aus und schicken es mit der Anfrage an CaptchaAI; fehlt es, lassen Sie das Feld weg. Diese eine Fallunterscheidung sauber im Client abzubilden, erspart die häufigste Fehlersuche rund um Google-Such-CAPTCHAs.

Verwandte Leitfäden

Kommentare sind für diesen Artikel deaktiviert.