Explainers

Leitfaden zur reCAPTCHA-Anker- und Bframe-URL-Extraktion

reCAPTCHA wird in zwei verschachtelten Iframes gerendert: dem Anker-Iframe (der das Kontrollkästchen-Widget enthält) und dem Bframe-Iframe (der die Bildherausforderung enthält). Diese Iframes enthalten codierte Parameter, die einige erweiterte Automatisierungsworkflows extrahieren müssen. In diesem Handbuch werden die Iframe-Architektur, das Parameterformat und die Extraktionstechniken erläutert.


reCAPTCHA-Iframe-Architektur

Target page (example.com/login)
    └── <iframe src="https://www.google.com/recaptcha/api2/anchor?...">
        │   ← Anchor iframe: "I'm not a robot" checkbox
        │
        └── <iframe src="https://www.google.com/recaptcha/api2/bframe?...">
                ← Bframe iframe: Image challenge grid (loads when clicked)

Anker-Iframe

Der Anker-Iframe enthält das Kontrollkästchen-Widget und die erste Risikoanalyse:

https://www.google.com/recaptcha/api2/anchor?
    ar=1
    &k=6LcR_RsTAAAAAN_r0GEkGBfq3L7KmU5JbPHJtwNp  ← site key
    &co=aHR0cHM6Ly9leGFtcGxlLmNvbTo0NDM.           ← encoded origin
    &hl=en                                           ← language
    &v=jF2Zb_rr_5sv8dMHoGIn-XxY                    ← reCAPTCHA version
    &size=normal                                     ← widget size
    &cb=89fu2pf0swif                                ← callback ID

Bframe-Iframe

Der Bframe-Iframe enthält die Bild-Challenge (wird nur geladen, wenn das Klicken auf das Kontrollkästchen eine Challenge auslöst):

https://www.google.com/recaptcha/api2/bframe?
    hl=en
    &v=jF2Zb_rr_5sv8dMHoGIn-XxY
    &k=6LcR_RsTAAAAAN_r0GEkGBfq3L7KmU5JbPHJtwNp

Anker-URL-Parameter

Parameter Name Beschreibung
k Site-Schlüssel Der reCAPTCHA-Site-Schlüssel
co Verschlüsselter Ursprung Base64-kodierter Ursprung (Protokoll + Domäne + Port)
v Version reCAPTCHA JavaScript-Bundle-Versions-Hash
hl Sprache Fordern Sie den Sprachcode heraus
size Größe normal, compact oder invisible
cb Rückruf Eindeutiger Rückruffunktionsbezeichner
theme Thema light oder dark
ar Seitenverhältnis Flag für Seitenverhältnis anzeigen

Dekodierung des co-Parameters

Der Parameter co enthält den Base64-codierten Ursprung:

import base64

co_value = "aHR0cHM6Ly9leGFtcGxlLmNvbTo0NDM."
# Remove trailing period (padding artifact)
decoded = base64.b64decode(co_value.rstrip(".") + "==").decode()
print(decoded)  # "https://example.com:443"

Dadurch wird die Ursprungsdomäne angezeigt, für die das reCAPTCHA konfiguriert wurde.


Extrahieren von Anker- und Bframe-URLs

Python-Extraktion aus der Seitenquelle

import requests
from bs4 import BeautifulSoup
from urllib.parse import urlparse, parse_qs
import re
import base64

def extract_recaptcha_iframes(url):
    """Extract reCAPTCHA anchor and bframe iframe URLs and 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 = requests.get(url, headers=headers, timeout=15)
    soup = BeautifulSoup(response.text, "html.parser")

    result = {
        "anchor_url": None,
        "bframe_url": None,
        "site_key": None,
        "origin": None,
        "version": None,
        "language": None,
    }

    # Find anchor iframe
    anchor_iframe = soup.find("iframe", src=re.compile(r"recaptcha.*anchor"))
    if anchor_iframe:
        anchor_url = anchor_iframe.get("src", "")
        result["anchor_url"] = anchor_url

        # Parse parameters
        parsed = urlparse(anchor_url)
        params = parse_qs(parsed.query)

        result["site_key"] = params.get("k", [None])[0]
        result["version"] = params.get("v", [None])[0]
        result["language"] = params.get("hl", [None])[0]

        # Decode origin
        co = params.get("co", [None])[0]
        if co:
            try:
                padded = co.rstrip(".") + "=="
                result["origin"] = base64.b64decode(padded).decode()
            except Exception:
                result["origin"] = co

    # Find bframe iframe (may not be in source — loaded dynamically)
    bframe_iframe = soup.find("iframe", src=re.compile(r"recaptcha.*bframe"))
    if bframe_iframe:
        result["bframe_url"] = bframe_iframe.get("src", "")

    # Construct bframe URL from anchor parameters if not found
    if not result["bframe_url"] and result["site_key"] and result["version"]:
        result["bframe_url"] = (
            f"https://www.google.com/recaptcha/api2/bframe?"
            f"hl={result['language'] or 'en'}"
            f"&v={result['version']}"
            f"&k={result['site_key']}"
        )

    return result

iframes = extract_recaptcha_iframes("https://example.com/login")
print(f"Site key: {iframes['site_key']}")
print(f"Origin: {iframes['origin']}")
print(f"Anchor URL: {iframes['anchor_url']}")

Node.js-Extraktion

const axios = require("axios");
const cheerio = require("cheerio");
const { URL } = require("url");

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

    const $ = cheerio.load(html);
    const result = {
        anchorUrl: null,
        bframeUrl: null,
        siteKey: null,
        origin: null,
        version: null,
    };

    // Find anchor iframe
    const anchorIframe = $("iframe[src*='recaptcha'][src*='anchor']");
    if (anchorIframe.length) {
        const src = anchorIframe.attr("src");
        result.anchorUrl = src;

        const url = new URL(src);
        result.siteKey = url.searchParams.get("k");
        result.version = url.searchParams.get("v");

        // Decode origin
        const co = url.searchParams.get("co");
        if (co) {
            try {
                result.origin = Buffer.from(
                    co.replace(/\.$/, ""), "base64"
                ).toString();
            } catch {}
        }
    }

    // Construct bframe URL
    if (result.siteKey && result.version) {
        result.bframeUrl =
            `https://www.google.com/recaptcha/api2/bframe?` +
            `hl=en&v=${result.version}&k=${result.siteKey}`;
    }

    return result;
}

extractRecaptchaIframes("https://example.com/login").then(console.log);

Selenextraktion (dynamische Seiten)

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

def extract_iframes_selenium(url):
    """Extract reCAPTCHA iframe URLs from a dynamically loaded page."""
    driver = webdriver.Chrome()
    driver.get(url)
    time.sleep(3)  # Wait for reCAPTCHA to load

    result = {"anchor_url": None, "bframe_url": None}

    # Find all iframes
    iframes = driver.find_elements(By.TAG_NAME, "iframe")

    for iframe in iframes:
        src = iframe.get_attribute("src") or ""
        if "recaptcha" in src and "anchor" in src:
            result["anchor_url"] = src
        elif "recaptcha" in src and "bframe" in src:
            result["bframe_url"] = src

    driver.quit()
    return result

Wenn Sie Anchor/bframe-URLs benötigen

Die meisten Automatisierungsworkflows benötigen KEINE Anker- oder Bframe-URLs. Die Standard-CaptchaAI-API erfordert nur sitekey und pageurl. Anchor/bframe-URLs sind jedoch nützlich für:

1. Überprüfen des korrekten Site-Schlüssels

Wenn eine Seite über mehrere reCAPTCHA-Instanzen verfügt oder der Site-Schlüssel dynamisch geladen wird:

# Extract sitekey from anchor URL when it's not in the page HTML
iframes = extract_recaptcha_iframes(url)
sitekey = iframes["site_key"]  # Guaranteed correct from iframe URL

2. Ermittlung der reCAPTCHA-Version

# The anchor URL reveals the exact reCAPTCHA version
if "/api2/anchor" in anchor_url:
    recaptcha_type = "v2"
elif "/enterprise/anchor" in anchor_url:
    recaptcha_type = "enterprise"

3. Anpassen des Ursprungs für domänenstrikte Implementierungen

# Decode the origin from the co parameter
origin = decode_co_parameter(iframes["co"])
# Use this origin as the pageurl for the solver

4. Debuggen, Fehler beheben

Wenn Token abgelehnt werden, kann ein Vergleich der Anker-URL-Parameter mit Ihrer Solver-Anfrage Unstimmigkeiten aufdecken:

def debug_solve_params(anchor_url, solver_pageurl, solver_sitekey):
    """Compare anchor params with solver request to find mismatches."""
    parsed = urlparse(anchor_url)
    params = parse_qs(parsed.query)

    issues = []

    # Check sitekey
    anchor_key = params.get("k", [None])[0]
    if anchor_key != solver_sitekey:
        issues.append(f"Sitekey mismatch: anchor={anchor_key}, solver={solver_sitekey}")

    # Check origin
    co = params.get("co", [None])[0]
    if co:
        origin = base64.b64decode(co.rstrip(".") + "==").decode()
        solver_parsed = urlparse(solver_pageurl)
        solver_origin = f"{solver_parsed.scheme}://{solver_parsed.netloc}"
        if origin != solver_origin:
            issues.append(f"Origin mismatch: anchor={origin}, solver={solver_origin}")

    return issues if issues else ["No mismatches found"]

Standardlösung (empfohlen)

Überspringen Sie in den meisten Anwendungsfällen die Iframe-Extraktion und lösen Sie sie direkt mit CaptchaAI:

import requests
import time

API_KEY = "YOUR_API_KEY"

# All you need: sitekey + pageurl
submit = requests.post("https://ocr.captchaai.com/in.php", data={
    "key": API_KEY,
    "method": "userrecaptcha",
    "googlekey": "6LcR_RsTAAAAAN_r0GEkGBfq3L7KmU5JbPHJtwNp",
    "pageurl": "https://example.com/login",
    "json": 1,
})

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

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[:50]}...")
        break

Die Extraktion von Anchor/bframe ist nur erforderlich, wenn die Standardlösung aufgrund von Sitekey- oder Domänenproblemen fehlschlägt, die eine eingehendere Untersuchung erfordern.


Häufig gestellte Fragen

Muss ich Anker- oder Bframe-URLs für CaptchaAI bereitstellen?

Nein. CaptchaAI benötigt nur sitekey und pageurl. Der Solver verarbeitet die Anker- und Bframe-Interaktion intern. Das Extrahieren dieser URLs ist zum Debuggen nützlich, für die Lösung jedoch nicht erforderlich.

Warum erscheint der Bframe-Iframe nicht in der Seitenquelle?

Der Bframe-Iframe wird dynamisch durch das JavaScript von reCAPTCHA erstellt, wenn der Benutzer auf das Kontrollkästchen klickt und eine Herausforderung ausgelöst wird. Es ist im ursprünglichen HTML nicht vorhanden. Sie benötigen Selenium oder Puppeteer, um mit dem Widget zu interagieren und die Bframe-URL zu erfassen.

Was ist der Parameter v in der Anker-URL?

Der Parameter v ist der Hash der reCAPTCHA-JavaScript-Bundle-Version. Es ändert sich regelmäßig, wenn Google reCAPTCHA aktualisiert. Für die Lösung wird es nicht benötigt – CaptchaAI verarbeitet Versionsunterschiede automatisch.

Kann der Parameter co beim Debuggen von Domänenproblemen helfen?

Ja. Der Parameter co ist der Base64-codierte Ursprung (Protokoll + Domäne + Port). Die Entschlüsselung zeigt genau, auf welcher Domain reCAPTCHA glaubt, dass es läuft. Wenn dies nicht mit der Domäne übereinstimmt, an die Sie das Token senden, haben Sie festgestellt, dass die Domäne nicht übereinstimmt und die Ablehnung des Tokens verursacht hat.


Zusammenfassung

reCAPTCHA verwendet zwei Iframes: Anchor (Kontrollkästchen-Widget) und Bframe (Bild-Challenge). Die Anchor-URL enthält den Site-Key, den codierten Ursprung und den Versions-Hash. Für die Standard-Lösung mit CaptchaAI werden nur sitekey und pageurl benötigt – keine Iframe-URL-Extraktion erforderlich. Iframe-Extraktionstechniken eignen sich zum Debuggen von Domain-Verifizierungsfehlern oder zur Extraktion von Site-Keys aus dynamisch geladenen Seiten.

Verwandte Leitfäden

  • reCAPTCHA v2 Callback-Mechanismus
  • reCAPTCHA v2 Turnstile: Gleiche Seite handhaben
  • reCAPTCHA Domain-Verifizierungsfehler beheben
Kommentare sind für diesen Artikel deaktiviert.

Verwandte Beiträge

Comparisons Headless vs. Headed Chrome für CAPTCHA-Tests in eigener QA
Wann sich Headless-Chrome und wann Headed-Chrome für CAPTCHA-Tests in eigenen CI- und QA-Pipelines eignet, und welche Auswirkungen die Wahl auf Stabilität und L...

Wann sich Headless-Chrome und wann Headed-Chrome für CAPTCHA-Tests in eigenen CI- und QA-Pipelines eignet, und...

Apr 17, 2026
Comparisons WebDriver vs. Chrome DevTools Protocol in eigener CAPTCHA-QA
Vergleich von Web Driver und Chrome Dev Tools Protocol für QA-Tests gegen die eigene CAPTCHA-Integration: Stärken, Grenzen und Einsatzempfehlungen.

Vergleich von Web Driver und Chrome Dev Tools Protocol für QA-Tests gegen die eigene CAPTCHA-Integration: Stär...

Apr 17, 2026