reCAPTCHA s'affiche dans deux iframes imbriquées : l'iframe anchor (contenant le widget de case à cocher) et l'iframe bframe (contenant le défi d'image). Ces iframes contiennent des paramètres codés que certains workflows d'automatisation avancés doivent extraire. Ce guide explique l'architecture iframe, le format des paramètres et les techniques d'extraction.
Architecture iframe reCAPTCHA
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)
Ancrer l'iframe
L'iframe d'ancrage contient le widget de case à cocher et l'analyse des risques initiale :
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 Bframe
L'iframe bframe contient le défi d'image (chargé uniquement lorsque le clic de la case à cocher déclenche un défi) :
https://www.google.com/recaptcha/api2/bframe?
hl=en
&v=jF2Zb_rr_5sv8dMHoGIn-XxY
&k=6LcR_RsTAAAAAN_r0GEkGBfq3L7KmU5JbPHJtwNp
Paramètres d'URL d'ancrage
| Paramètre | Nom | Descriptif |
|---|---|---|
k |
Clé du site | La clé du site reCAPTCHA |
co |
Origine codée | Origine codée en base64 (protocole + domaine + port) |
v |
Version | Hachage de la version du bundle JavaScript reCAPTCHA |
hl |
Langue | Code de langue du défi |
size |
Taille | normal, compact ou invisible |
cb |
Rappel | Identifiant unique de la fonction de rappel |
theme |
Thème | light ou dark |
ar |
Rapport hauteur/largeur | Afficher l'indicateur de rapport hauteur/largeur |
Décodage du paramètre co
Le paramètre co contient l'origine codée en base64 :
import base64
co_value = "aHR0cHM6Ly9leGFtcGxlLmNvbTo0NDM."
# Remove trailing period (padding artifact)
decoded = base64.b64decode(co_value.rstrip(".") + "==").decode()
print(decoded) # "https://example.com:443"
Cela révèle le domaine d'origine pour lequel reCAPTCHA a été configuré.
Extraction des URL d'ancrage et bframe
Extraction Python à partir de la source de la page
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']}")
Extraction 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://example.com/login").then(console.log);
Extraction du sélénium (pages dynamiques)
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
Quand vous avez besoin des URL Anchor/bframe
La plupart des flux de travail d'automatisation n'ont PAS besoin d'URL d'ancrage ou de bframe. L'API standard CaptchaAI nécessite uniquement sitekey et pageurl. Cependant, les URL Anchor/bframe sont utiles pour :
1. Vérifier la clé de site correcte
Lorsqu'une page comporte plusieurs instances reCAPTCHA ou que la clé du site est chargée dynamiquement :
# 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. Détermination de la version de 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. Faire correspondre l'origine pour les implémentations strictes de domaine
# Decode the origin from the co parameter
origin = decode_co_parameter(iframes["co"])
# Use this origin as the pageurl for the solver
4. Le débogage résout les échecs
Lorsque les jetons sont rejetés, la comparaison des paramètres de l'URL d'ancrage avec votre demande de solveur peut révéler des incohérences :
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"]
Résolution standard (recommandée)
Pour la plupart des cas d'utilisation, ignorez l'extraction d'iframe et résolvez directement avec 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
L'extraction Anchor/bframe n'est nécessaire que lorsque la résolution standard échoue en raison de problèmes de clé de site ou de domaine qui nécessitent une enquête plus approfondie.
Questions fréquemment posées
Dois-je fournir des URL d’ancrage ou bframe à CaptchaAI ?
Non. CaptchaAI n'a besoin que du sitekey et du pageurl. Le solveur gère l’interaction entre l’ancre et le bframe en interne. L'extraction de ces URL est utile pour le débogage mais n'est pas obligatoire pour la résolution.
Pourquoi l'iframe bframe n'apparaît-elle pas dans la source de la page ?
L'iframe bframe est créée dynamiquement par le JavaScript de reCAPTCHA lorsque l'utilisateur clique sur la case à cocher et qu'un défi est déclenché. Il n'est pas présent dans le HTML initial. Vous avez besoin de Selenium ou de Puppeteer pour interagir avec le widget et capturer l'URL bframe.
Qu'est-ce que le paramètre v dans l'URL d'ancrage ?
Le paramètre v est le hachage de la version du bundle JavaScript reCAPTCHA. Il change périodiquement lorsque Google met à jour reCAPTCHA. Ce n'est pas nécessaire pour la résolution - CaptchaAI gère automatiquement les différences de version.
Le paramètre co peut-il aider à déboguer les problèmes de domaine ?
Oui. Le paramètre co est l'origine codée en base64 (protocole + domaine + port). Son décodage révèle exactement sur quel domaine reCAPTCHA pense fonctionner. Si cela ne correspond pas au domaine auquel vous soumettez le jeton, vous avez trouvé une incompatibilité de domaine entraînant le rejet du jeton.
Résumé
reCAPTCHA utilise deux iframes : anchor (widget de case à cocher) et bframe (défi d'image). L'URL d'ancrage contient la clé du site, l'origine codée et le hachage de version. Pour la résolution standard avecCaptchaAI, vous n'avez besoin que des fichiers sitekey et pageurl — aucune extraction d'URL iframe n'est requise. Utilisez des techniques d'extraction iframe pour déboguer les échecs de vérification de domaine ou extraire les clés de site à partir de pages chargées dynamiquement.
Articles connexes
- Comment résoudre le rappel Recaptcha V2 à l'aide de l'API
- Gestion du tourniquet Recaptcha V2 sur le même site
- Mécanisme de rappel Recaptcha V2