Vergleiche

reCAPTCHA v2 vs. Invisible reCAPTCHA erklärt

Checkbox oder unsichtbar – für das Lösen mit CaptchaAI macht das kaum einen Unterschied: Sie hängen lediglich invisible=1 an Ihre Anfrage an. Der eigentliche Aufwand steckt an einer anderen Stelle, nämlich darin, das gelöste Token sauber in die Seite zurückzuspielen. Denn beide sind Varianten von reCAPTCHA v2, teilen sich dieselbe Technik und denselben Sitekey. Die Checkbox-Variante zeigt das bekannte „Ich bin kein Roboter"-Feld und blendet bei Verdacht ein Bildraster ein. Die unsichtbare Variante läuft ohne sichtbares Widget und wird automatisch durch eine Nutzeraktion ausgelöst – einen Klick, ein Formular-Absenden oder das Laden der Seite. Dieser Artikel zeigt, wie Sie beide im HTML auseinanderhalten und jede zuverlässig verarbeiten.


So sieht jede reCAPTCHA-v2-Variante im HTML aus

v2-Checkbox

<!-- Standard checkbox widget -->
<div class="g-recaptcha"
     data-sitekey="6Le-wvkSAAAAAPBMRTvw..."
     data-callback="onSubmit">
</div>

<!-- Widget renders as: -->
<!-- [✓] I'm not a robot     reCAPTCHA logo -->

Der Nutzer sieht die Checkbox und klickt sie an. Hält Google die Sitzung für verdächtig, erscheint direkt darunter ein Bildraster als zusätzliche Abfrage.

v2 Invisible

<!-- Pattern 1: Invisible widget on a button -->
<button class="g-recaptcha"
        data-sitekey="6Le-wvkSAAAAAPBMRTvw..."
        data-callback="onSubmit"
        data-size="invisible">
  Submit
</button>

<!-- Pattern 2: Invisible div (programmatic trigger) -->
<div class="g-recaptcha"
     data-sitekey="6Le-wvkSAAAAAPBMRTvw..."
     data-size="invisible"
     data-callback="onSubmit">
</div>

<!-- Pattern 3: Programmatic render -->
<script>
  grecaptcha.render('submit-btn', {
    sitekey: '6Le-wvkSAAAAAPBMRTvw...',
    callback: onSubmit,
    size: 'invisible'
  });
</script>

Kein sichtbares Widget: reCAPTCHA wird erst aktiv, wenn der Nutzer das hinterlegte Element auslöst oder grecaptcha.execute() aufgerufen wird.


reCAPTCHA v2 Checkbox oder Invisible: der Unterschied auf einen Blick

Verhalten und Nutzererlebnis

Merkmal v2-Checkbox v2 Invisible
Sichtbares Widget Ja – „Ich bin kein Roboter"-Feld Nein – für Nutzer unsichtbar
Auslöser Nutzer klickt das Feld an Klick, Formular-Absenden oder Seitenaufruf
Bild-Abfrage Erscheint, wenn Google einen Bot vermutet Popup unten rechts bei Verdacht
Nutzererlebnis Spürbare Reibung Kaum bis keine Reibung

Einbindung und Lösung

Merkmal v2-Checkbox v2 Invisible
Einbindung g-recaptcha-div auf der Seite data-callback am Button oder grecaptcha.execute()
Sitekey-Format Identisch mit Invisible Identisch mit Checkbox
Token-Feld g-recaptcha-response g-recaptcha-response
Callback Optional Fast immer Pflicht
CaptchaAI-Methode method=userrecaptcha method=userrecaptcha + invisible=1
Token-Lebensdauer 120 Sekunden 120 Sekunden
Lösungszeit 10–30 Sekunden 10–25 Sekunden

Variante zuverlässig im Code erkennen

In der Praxis wissen Sie oft nicht im Voraus, welche Variante Sie erwartet – und viele DACH-Portale sind in den letzten Jahren stillschweigend von der sichtbaren Checkbox auf Invisible umgestiegen, vom Shopware-Login bis zum Registrierungsformular. Ermitteln Sie die Variante deshalb immer dynamisch aus dem HTML. Diese vier Signale trennen die Varianten:

Erkennungssignal v2-Checkbox v2 Invisible
data-size="invisible" Fehlt Vorhanden
Sichtbare Checkbox auf der Seite Ja Nein
grecaptcha.execute() wird aufgerufen Nein (Nutzerklick) Ja (programmatisch)
Position des Challenge-Popups Inline, unter der Checkbox Unten rechts auf der Seite

Erkennung mit Python

import requests
from bs4 import BeautifulSoup
import re

def detect_recaptcha_variant(url):
    resp = requests.get(url)
    soup = BeautifulSoup(resp.text, "html.parser")

    # Check for invisible indicators
    invisible_widget = soup.find(attrs={"data-size": "invisible", "class": "g-recaptcha"})
    if invisible_widget:
        return {
            "variant": "invisible",
            "sitekey": invisible_widget.get("data-sitekey"),
            "callback": invisible_widget.get("data-callback")
        }

    # Check for programmatic invisible in scripts
    for script in soup.find_all("script"):
        if script.string and "invisible" in str(script.string):
            key_match = re.search(r"sitekey['\"]?\s*[:=]\s*['\"]([^'\"]+)", script.string)
            if key_match:
                return {
                    "variant": "invisible-programmatic",
                    "sitekey": key_match.group(1),
                    "callback": "check grecaptcha.render() call"
                }

    # Check for standard checkbox
    checkbox_widget = soup.find(class_="g-recaptcha")
    if checkbox_widget:
        return {
            "variant": "checkbox",
            "sitekey": checkbox_widget.get("data-sitekey"),
            "callback": checkbox_widget.get("data-callback")
        }

    return None

result = detect_recaptcha_variant("https://example.com/login")
print(result)

Erkennung mit Node.js

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

async function detectRecaptchaVariant(url) {
  const { data } = await axios.get(url);
  const $ = cheerio.load(data);

  // Check for invisible
  const invisible = $(".g-recaptcha[data-size='invisible']");
  if (invisible.length) {
    return {
      variant: "invisible",
      sitekey: invisible.attr("data-sitekey"),
      callback: invisible.attr("data-callback"),
    };
  }

  // Check scripts for programmatic invisible
  const scripts = $("script")
    .map((_, el) => $(el).html())
    .get()
    .join("\n");
  if (scripts.includes("invisible")) {
    const keyMatch = scripts.match(/sitekey['"]?\s*[:=]\s*['"]([^'"]+)/);
    if (keyMatch) {
      return {
        variant: "invisible-programmatic",
        sitekey: keyMatch[1],
        callback: "check render call",
      };
    }
  }

  // Check for standard checkbox
  const checkbox = $(".g-recaptcha");
  if (checkbox.length) {
    return {
      variant: "checkbox",
      sitekey: checkbox.attr("data-sitekey"),
      callback: checkbox.attr("data-callback"),
    };
  }

  return null;
}

Schnellprüfung in der Browser-Konsole

const el = document.querySelector('[data-size="invisible"]');
console.log(el ? "Invisible reCAPTCHA" : "Checkbox reCAPTCHA");

Beide Varianten mit CaptchaAI lösen

Auf der API-Seite ist der Unterschied ein einziger Parameter. Sie senden die Aufgabe an in.php und fragen das Ergebnis von res.php ab – bei Invisible kommt lediglich invisible=1 hinzu.

v2-Checkbox

import requests
import time

resp = requests.get("https://ocr.captchaai.com/in.php", params={
    "key": "YOUR_API_KEY",
    "method": "userrecaptcha",
    "googlekey": "6Le-wvkSAAAA...",
    "pageurl": "https://example.com/form"
})
task_id = resp.text.split("|")[1]

for _ in range(60):
    time.sleep(5)
    result = requests.get("https://ocr.captchaai.com/res.php", params={
        "key": "YOUR_API_KEY", "action": "get", "id": task_id
    })
    if result.text.startswith("OK|"):
        token = result.text.split("|")[1]
        break

v2 Invisible

import requests
import time

resp = requests.get("https://ocr.captchaai.com/in.php", params={
    "key": "YOUR_API_KEY",
    "method": "userrecaptcha",
    "googlekey": "6Le-wvkSAAAA...",
    "pageurl": "https://example.com/form",
    "invisible": 1  # Only parameter difference
})
task_id = resp.text.split("|")[1]

for _ in range(60):
    time.sleep(5)
    result = requests.get("https://ocr.captchaai.com/res.php", params={
        "key": "YOUR_API_KEY", "action": "get", "id": task_id
    })
    if result.text.startswith("OK|"):
        token = result.text.split("|")[1]
        break

Token einfügen – hier trennen sich die Varianten

v2-Checkbox: das versteckte Feld genügt meist

# Selenium — inject into hidden field
driver.execute_script(
    f'document.getElementById("g-recaptcha-response").value = "{token}";'
)

# If the page uses a callback, also call it
callback = driver.find_element("css selector", ".g-recaptcha").get_attribute("data-callback")
if callback:
    driver.execute_script(f'{callback}("{token}");')

v2 Invisible: der Callback ist Pflicht

# Selenium — inject AND call the callback
driver.execute_script(
    f'document.getElementById("g-recaptcha-response").value = "{token}";'
)

# CRITICAL: Invisible reCAPTCHA almost always requires calling the callback
callback_name = driver.find_element(
    "css selector", ".g-recaptcha[data-size='invisible']"
).get_attribute("data-callback")

driver.execute_script(f'{callback_name}("{token}");')

Dasselbe mit Puppeteer

// Puppeteer — invisible callback injection
await page.evaluate((tok) => {
  // Set the hidden field
  document.getElementById("g-recaptcha-response").value = tok;

  // Find and call the callback function
  const widget = document.querySelector("[data-size='invisible']");
  const cbName = widget?.getAttribute("data-callback");
  if (cbName && typeof window[cbName] === "function") {
    window[cbName](tok);
  }
}, token);

Der springende Punkt: Bei der Checkbox reicht oft das versteckte Feld allein, weil der Klick des Nutzers den Callback bereits registriert hat. Invisible reCAPTCHA kennt diesen Klick nie – hier müssen Sie den Callback selbst aufrufen, sonst wird ein technisch gültiges Token von der Seite ignoriert.


Fehlerbehebung

Token wird nicht akzeptiert

Checkbox: in g-recaptcha-response schreiben. Invisible: schreiben UND den data-callback aufrufen.

Widget nicht gefunden

Checkbox: nach .g-recaptcha suchen. Invisible: nach data-size="invisible" oder Skript-Render-Aufrufen.

Formular sendet, schlägt aber fehl

Checkbox: prüfen, ob ein Callback erwartet wird. Invisible: Callback finden und aufrufen.

Seite lädt nach dem Einfügen neu

Checkbox: JavaScript-Validierung fehlgeschlagen. Invisible: Callback aufrufen, bevor das Formular absendet.


Universeller Löser für beide Varianten

Wenn Sie beide Fälle über einen einzigen Codepfad abdecken wollen, erkennen Sie die Variante zur Laufzeit und setzen invisible=1 nur, wenn es nötig ist:

import requests
import time
from bs4 import BeautifulSoup

class RecaptchaV2UniversalSolver:
    def __init__(self, api_key):
        self.api_key = api_key

    def detect_and_solve(self, page_url, page_html=None):
        if not page_html:
            page_html = requests.get(page_url).text

        soup = BeautifulSoup(page_html, "html.parser")

        # Detect variant
        invisible = soup.find(attrs={"data-size": "invisible", "class": "g-recaptcha"})
        widget = invisible or soup.find(class_="g-recaptcha")

        if not widget:
            raise Exception("No reCAPTCHA widget found")

        sitekey = widget.get("data-sitekey")
        is_invisible = invisible is not None
        callback = widget.get("data-callback")

        params = {
            "key": self.api_key,
            "method": "userrecaptcha",
            "googlekey": sitekey,
            "pageurl": page_url
        }
        if is_invisible:
            params["invisible"] = 1

        resp = requests.get("https://ocr.captchaai.com/in.php", params=params)
        if not resp.text.startswith("OK|"):
            raise Exception(f"Submit failed: {resp.text}")

        task_id = resp.text.split("|")[1]
        for _ in range(60):
            time.sleep(5)
            result = requests.get("https://ocr.captchaai.com/res.php", params={
                "key": self.api_key, "action": "get", "id": task_id
            })
            if result.text.startswith("OK|"):
                return {
                    "token": result.text.split("|")[1],
                    "variant": "invisible" if is_invisible else "checkbox",
                    "callback": callback,
                    "sitekey": sitekey
                }
            if result.text != "CAPCHA_NOT_READY":
                raise Exception(f"Solve error: {result.text}")

        raise Exception("Timed out")

# Usage
solver = RecaptchaV2UniversalSolver("YOUR_API_KEY")
result = solver.detect_and_solve("https://example.com/login")
print(f"Variant: {result['variant']}, Callback: {result['callback']}")

Häufige Fragen

Kostet das Lösen von Invisible mehr als von der Checkbox?

Nein. CaptchaAI rechnet Thread-basiert ab, nicht pro Lösung: Jeder Plan enthält unbegrenzte Lösungen pro Thread, und es gibt keinen Aufpreis nach CAPTCHA-Typ. Ob Checkbox oder Invisible spielt für die Kosten also keine Rolle – der Tarif richtet sich allein nach der Zahl paralleler Threads, ab BASIC (15 $/Monat, 5 Threads).

Warum wird mein gültiges Token bei Invisible abgelehnt?

Weil das versteckte Feld allein nicht ausreicht. Bei Invisible fehlt der Nutzerklick, der sonst den Callback anstößt. Schreiben Sie das Token in g-recaptcha-response und rufen Sie zusätzlich die in data-callback hinterlegte Funktion auf – erst danach akzeptiert die Seite das Token.

Woran erkenne ich die Variante direkt im Browser?

Öffnen Sie die Konsole und prüfen Sie mit document.querySelector('[data-size="invisible"]'), ob ein unsichtbares Widget existiert. Fehlt es und ist stattdessen eine „Ich bin kein Roboter"-Checkbox sichtbar, handelt es sich um die Checkbox-Variante.

Kann eine Seite je nach Gerät zwischen beiden umschalten?

Ja. Es ist derselbe Sitekey mit unterschiedlicher Einbindung – manche Seiten zeigen am Desktop eine Checkbox und laufen mobil unsichtbar. Verlassen Sie sich nie auf eine feste Annahme, sondern erkennen Sie die Variante bei jedem Aufruf neu.

Brauche ich für Invisible einen anderen CaptchaAI-Endpunkt?

Nein. Sie nutzen denselben in.php/res.php-Ablauf und dieselbe Methode userrecaptcha. Der einzige Zusatz ist der Parameter invisible=1 in der Anfrage an in.php; alles Weitere bleibt identisch.


Verwandte Leitfäden

Kommentare sind für diesen Artikel deaktiviert.