Explainers

Руководство по извлечению якорей reCAPTCHA и URL-адресов Bframe

reCAPTCHA визуализируется внутри двух вложенных iframe: iframe anchor (содержащий виджет флажка) и iframe bframe (содержащего запрос изображения). Эти iframe содержат закодированные параметры, которые необходимо извлечь в некоторых расширенных рабочих процессах автоматизации. В этом руководстве объясняется архитектура iframe, формат параметров и методы извлечения.


reCAPTCHA архитектура iframe

Target page (https://staging.example.com/qa-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)

Привязка iframe

Якорь iframe содержит виджет флажка и первоначальный анализ рисков:

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

Бфрейм iframe

iframe bframe содержит запрос изображения (загружается только тогда, когда щелчок флажка запускает вызов):

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

Параметры URL-адреса привязки

Параметр Имя Описание
k Ключ сайта Ключ сайта reCAPTCHA
co Закодированное происхождение Источник в кодировке Base64 (протокол + домен + порт)
v Версия Хэш версии пакета JavaScript reCAPTCHA
hl Язык Языковой код вызова
size Размер normal, compact или invisible
cb Перезвонить Уникальный идентификатор функции обратного вызова
theme Тема light или dark
ar Соотношение сторон Флаг соотношения сторон дисплея

Расшифровка параметра co

Параметр co содержит начало координат в кодировке Base64:

import base64

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

Это покажет исходный домен, для которого была настроена reCAPTCHA.


Извлечение URL-адресов привязки и bframe

Извлечение Python из исходного кода страницы

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://https://staging.example.com/qa-login")
print(f"Site key: {iframes['site_key']}")
print(f"Origin: {iframes['origin']}")
print(f"Anchor URL: {iframes['anchor_url']}")

Извлечение Node.js

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://https://staging.example.com/qa-login").then(console.log);

Извлечение селена (динамические страницы)

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

Когда вам нужны URL-адреса привязки/bframe

Большинству рабочих процессов автоматизации НЕ нужны URL-адреса привязки или bframe. Стандартный API CaptchaAI требует только sitekey и pageurl. Однако URL-адреса якоря/bframe полезны для:

1. Проверка правильного ключа сайта

Если на странице имеется несколько экземпляров reCAPTCHA или ключ сайта загружается динамически:

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

2. Определение версии reCAPTCHA

# 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. Сопоставление источника для реализаций со строгим доменным доступом

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

4. Отладка и устранение сбоев

Когда токены отклоняются, сравнение параметров URL-адреса привязки с запросом решателя может выявить несоответствия:

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

Стандартное решение (рекомендуется)

В большинстве случаев пропустите извлечение iframe и решите напрямую с помощью 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://https://staging.example.com/qa-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

Извлечение Anchor/bframe необходимо только в том случае, если стандартное решение не удается из-за проблем с ключом сайта или домена, которые требуют более глубокого исследования.


Часто задаваемые вопросы

Нужно ли мне предоставлять URL-адреса привязки или bframe для CaptchaAI?

Нет. CaptchaAI нужны только sitekey и pageurl. Решатель внутренне обрабатывает взаимодействие привязки и bframe. Извлечение этих URL-адресов полезно для отладки, но не обязательно для решения.

Почему iframe bframe не отображается в исходном коде страницы?

iframe bframe создается динамически с помощью JavaScript reCAPTCHA, когда пользователь нажимает флажок и запускается запрос. Его нет в исходном HTML. Вам понадобится Selenium или Puppeteer для взаимодействия с виджетом и захвата URL-адреса bframe.

Что такое параметр v в URL-адресе привязки?

Параметр v — это хеш версии пакета JavaScript reCAPTCHA. Он периодически меняется, когда Google обновляет reCAPTCHA. Для решения это не требуется — CaptchaAI автоматически обрабатывает различия версий.

Может ли параметр co помочь в устранении проблем с доменом?

Да. Параметр co — это источник в кодировке Base64 (протокол + домен + порт). Расшифровка показывает, на каком именно домене, по мнению reCAPTCHA, он работает. Если он не соответствует домену, в который вы отправляете токен, вы обнаружили несоответствие домена, вызывающее отклонение токена.


Краткое содержание

reCAPTCHA использует два iframe: якорь (виджет флажка) и bframe (вызов изображения). URL-адрес привязки содержит ключ сайта, закодированное происхождение и хэш версии. Для стандартного решения сCaptchaAI, вам нужны только sitekey и pageurl — извлечение URL-адреса iframe не требуется. Используйте методы извлечения iframe для устранения сбоев проверки домена или извлечения ключей сайта из динамически загружаемых страниц.

Похожие статьи

Комментарии для этой статьи отключены.