Explainers

reCAPTCHA Anchor ve Bframe URL Çıkarma Kılavuzu

CaptchaAI'ye normalde yalnızca sitekey ve pageurl yeterlidir; anchor veya bframe URL'sini çıkarmanıza gerek yoktur. Ama token'ınız sürekli reddediliyorsa, sayfada birden fazla reCAPTCHA widget'ı çalışıyorsa ya da sitekey JavaScript ile sonradan enjekte ediliyorsa, sorunun kaynağını görmek için bu iki iframe'in içine bakmanız gerekir.

Hızlı özet:

  • Anchor iframe onay kutusunu, bframe görsel sorgulamayı taşır.
  • CaptchaAI'ye günlük kullanımda yalnızca sitekey ve pageurl yeterlidir.
  • Bu URL'leri çıkarmak yalnızca sitekey/domain hata ayıklaması için gereklidir.

reCAPTCHA neden iki ayrı iframe kullanır

reCAPTCHA, birbirinin içine yerleşmiş iki iframe render eder: onay kutusu widget'ını taşıyan anchor ve görsel sorgulamayı taşıyan bframe. Anchor her zaman sayfa yüklendiğinde oluşur; bframe ise yalnızca kullanıcı kutuya tıklayıp bir sorgulama tetiklendiğinde devreye girer — bu yüzden ilk HTML'de hiç görünmeyebilir. Aşağıdaki şema iki iframe'in ilişkisini gösterir:

Target page (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)

Anchor iframe'in kendi URL'si, onay kutusu widget'ını ve ilk risk analizini taşıyan kodlanmış parametreler içerir. Gerçek bir anchor URL'si şöyle görünür:

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 URL'si daha az parametre taşır çünkü anchor tarafından zaten doğrulanmış bir oturumu devralır; yalnızca sorgulama tetiklendiğinde oluşur:

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

Anchor URL'sindeki parametreler: hangisi ne işe yarar

Parametre Anlamı Açıklama
k Sitekey reCAPTCHA sitekey değeri
co Kodlanmış origin Base64 ile kodlanmış origin (protokol + alan adı + port)
v Sürüm reCAPTCHA JavaScript paketinin sürüm karması (hash)
hl Dil Sorgulamanın gösterileceği dil kodu
size Boyut normal, compact veya invisible
cb Callback Benzersiz callback fonksiyon kimliği
theme Tema light veya dark
ar En-boy oranı Widget'ın görüntü oranı bayrağı

Sekiz parametrenin çoğu çözüm için önemsizdir; hata ayıklarken gerçekten işinize yarayacak olanlar k ve co'dur — sitekey uyuşmazlığını ve domain uyuşmazlığını bu ikisi ele verir.

co parametresini çözme: origin'i base64 ile kodlanmış halde taşır:

import base64

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

Bu tek satır, reCAPTCHA'nın hangi origin için yapılandırıldığını ortaya çıkarır — token'ınız reddediliyorsa ilk bakmanız gereken yer burasıdır.


Anchor ve bframe URL'lerini üç yöntemle çıkarma

Üç yöntem aynı işi farklı ortamlarda yapar: statik sayfa kaynağı, headless tarayıcı olmadan hızlı bir istek ve dinamik olarak yüklenen widget'lar için tam tarayıcı otomasyonu.

Yöntem 1 — Python, sayfa kaynağından:

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

Yöntem 2 — Node.js: aynı mantığı bir Node.js hattına entegre etmeniz gerekiyorsa:

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

Yöntem 3 — Selenium, dinamik sayfalar için: bframe iframe ilk HTML'de yoktur, onay kutusuna tıklanmadan oluşmaz; yakalamak için gerçek bir tarayıcıya ihtiyacınız var:

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

Bu tekniklere ne zaman gerçekten ihtiyacınız var

Çoğu otomasyon iş akışı anchor veya bframe URL'sine hiç dokunmaz — CaptchaAI API'sine yalnızca sitekey ve pageurl yeterlidir. Dört durumda işinize yarar:

Durum Ne zaman ortaya çıkar
Birden fazla widget Sayfada birden fazla reCAPTCHA olduğunda doğru sitekey'i bulma
Sürüm belirsizliği v2 mi Enterprise mi çalıştığını anlama
Domain-strict entegrasyon pageurl origin'inin reCAPTCHA'nın beklediği origin'le eşleşmesi gerektiğinde
Token reddi Solver isteğinizle anchor parametrelerini karşılaştırıp uyumsuzluğu bulma

İpucu: Prod ortamda bu çıkarma işlemini her istekte tekrarlamayın. Sitekey ve origin değerlerini önbelleğe alın, yalnızca sayfa yapısı değiştiğinde yeniden çıkarın — aksi halde gereksiz gecikme eklersiniz.

Sayfada birden fazla widget varken doğru sitekey'i bulma: bir e-ticaret ödeme adımında hem ödeme formunda hem kupon alanında ayrı reCAPTCHA widget'ları çalışabilir; sayfa kaynağında sitekey görünmüyorsa ya da JavaScript ile sonradan enjekte ediliyorsa doğru değeri anchor URL'inden okumak en güvenilir yoldur. Örneğin İstanbul merkezli bir freelance otomasyon geliştiricisinin bir müşteri için kurduğu QA test paketinde, staging.example.com/qa-checkout sayfasında iki widget aynı anda yüklendiğinde script yanlış sitekey'i CaptchaAI'ye gönderiyor ve token her seferinde reddediliyordu; anchor URL'lerini tek tek çıkarıp co değerini çözerek eşleştirmek, hangi widget'ın hangi forma ait olduğunu netleştirdi.

# 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

Sitede hangi reCAPTCHA sürümünün çalıştığını anlama: anchor URL'sindeki yol farkı sürümü ele verir:

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

Domain'e sıkı bağlı entegrasyonlarda origin eşleştirme: co parametresini çözüp solver'a pageurl olarak geçireceğiniz origin ile karşılaştırmak, domain-strict yapılandırmalarda token reddini önler:

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

Token reddini hata ayıklarken kaynağı bulma: sitekey doğru görünüyor ama token yine de reddediliyorsa, anchor URL parametrelerini solver isteğinizle programatik olarak karşılaştırmak dakikalar içinde sorunu izole eder:

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

Varsayılan yol: iframe'e hiç dokunmadan çözün

Yukarıdaki tüm teknikler hata ayıklama içindir — günlük kullanımda hiçbirine ihtiyacınız yok. sitekey ve pageurl'ü doğrudan CaptchaAI'ye gönderin, anchor/bframe etkileşimini solver sizin yerinize halleder:

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://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 çıkarma işlemine yalnızca standart çözüm sitekey ya da domain uyuşmazlığı yüzünden başarısız olduğunda, daha derin bir araştırma gerektiğinde başvurun.


Özet

reCAPTCHA iki iframe üzerinden çalışır: onay kutusunu barındıran anchor ve görsel sorgulamayı barındıran bframe.

  • Anchor URL'si sitekey'i, kodlanmış origin'i ve sürüm karmasını taşır.
  • Bframe URL'si yalnızca sorgulama tetiklendiğinde oluşur, ilk HTML'de yoktur.
  • Günlük kullanımda CaptchaAI ile çözüm için tek ihtiyacınız sitekey ve pageurl'dür.

Bu rehberdeki iframe çıkarma tekniklerini yalnızca domain uyuşmazlığı, sitekey belirsizliği veya token reddi hata ayıklaması gibi durumlarda kullanın; günlük entegrasyonda iframe URL'sinin çıkarılmasına gerek yoktur.


Sık sorulan sorular

Anchor/bframe çıkarmayla ilgili en sık karşılaşılan sorular:

CaptchaAI'ye anchor veya bframe URL'i göndermem gerekiyor mu?

Hayır. CaptchaAI yalnızca sitekey ve pageurl ister; anchor/bframe etkileşimini solver dahili olarak yönetir. Bu URL'leri çıkarmak yalnızca hata ayıklama içindir, çözüm için şart değildir.

Aynı sayfada birden fazla reCAPTCHA widget'ı varsa hangi sitekey'i göndermeliyim?

Her widget'ın kendi anchor iframe'i ve kendi k parametresi vardır. Doğru olanı bulmak için:

  • İlgili anchor URL'sini tek tek çıkarın.
  • co değerini çözüp origin ile eşleştirin — genel sayfa kaynağına değil, o widget'ın kendi iframe'ine bakın.

Bframe iframe neden sayfa kaynağında hiç görünmüyor?

Bframe, kullanıcı onay kutusuna tıklayıp bir sorgulama tetiklendiğinde reCAPTCHA'nın JavaScript'i tarafından anlık olarak oluşturulur; ilk HTML'de yoktur. Yakalamak için Selenium veya Puppeteer ile widget'a gerçekten tıklamanız gerekir.

co parametresinin sonundaki nokta neden var, kodu çözerken hata alıyorum?

Google'ın base64 kodlamasında padding karakteri olarak = yerine bazen tek bir nokta bırakılıyor.

Kodu çözmeden önce noktayı kaldırıp == eklemeniz gerekir — yukarıdaki Python örneğindeki co_value.rstrip(".") + "==" satırı tam olarak bunu yapar.

reCAPTCHA Enterprise kullanan bir sitede anchor URL'ini nasıl ayırt ederim?

Anchor URL'nin yol kısmına bakın: standart reCAPTCHA v2 /recaptcha/api2/anchor kullanırken reCAPTCHA v2 Enterprise /recaptcha/enterprise/anchor yolunu kullanır. Bu ayrım, hangi CaptchaAI method değerini göndereceğinizi doğrulamak için de işinize yarar.


İlgili Makaleler

Bu makale için yorumlar devre dışı bırakılmıştır.