Tous les CAPTCHA ne sont pas présents lors du premier chargement de la page. De nombreux sites affichent les CAPTCHA paresseusement - après un clic sur un bouton, un focus sur un formulaire, un défilement ou une minuterie. Si votre automatisation récupère immédiatement la source de la page, le CAPTCHA n'est pas encore là. Ce guide explique comment détecter et attendre les CAPTCHA chargés dynamiquement.
Déclencheurs courants de chargement différé
| Déclencheur | Exemple | Comment activer |
|---|---|---|
| Clic sur le bouton | "Envoyer" ajoute reCAPTCHA au formulaire | Cliquez d'abord sur le bouton |
| Focus sur le formulaire | CAPTCHA apparaît lorsque la saisie est ciblée | Focus sur le champ email/password |
| Position de défilement | CAPTCHA se charge lorsque la section est visible | Faites défiler jusqu'au formulaire |
| Minuterie | CAPTCHA se charge après 3 secondes | Attendez le retard |
| Condition JavaScript | CAPTCHA se charge après la réponse AJAX | Déclencher la demande de prérequis |
Méthode 1 : MutationObserver
Regardez le DOM pour les éléments CAPTCHA ajoutés :
Marionnettiste
const puppeteer = require('puppeteer');
const browser = await puppeteer.launch({ headless: false });
const page = await browser.newPage();
await page.goto('https://example.com/login');
// Set up MutationObserver before triggering the CAPTCHA
const captchaInfo = await page.evaluate(() => {
return new Promise((resolve) => {
// Check if already present
const existing = document.querySelector('.g-recaptcha, .cf-turnstile, .h-captcha');
if (existing) {
resolve({
type: existing.className,
sitekey: existing.getAttribute('data-sitekey'),
});
return;
}
// Watch for new elements
const observer = new MutationObserver((mutations) => {
for (const mutation of mutations) {
for (const node of mutation.addedNodes) {
if (node.nodeType !== 1) continue;
const captcha = node.matches?.('.g-recaptcha, .cf-turnstile, .h-captcha')
? node
: node.querySelector?.('.g-recaptcha, .cf-turnstile, .h-captcha');
if (captcha) {
observer.disconnect();
resolve({
type: captcha.className,
sitekey: captcha.getAttribute('data-sitekey'),
});
return;
}
}
}
});
observer.observe(document.body, { childList: true, subtree: true });
// Timeout after 30 seconds
setTimeout(() => {
observer.disconnect();
resolve(null);
}, 30000);
});
});
console.log('Detected CAPTCHA:', captchaInfo);
Déclenchement de la charge
// Click the submit button to trigger CAPTCHA
await page.click('#submit-btn');
// Or focus the input
await page.focus('#email');
// Or scroll to the form
await page.evaluate(() => {
document.querySelector('#signup-form').scrollIntoView();
});
Méthode 2 : attendre l'injection du script
Les CAPTCHA nécessitent leur bibliothèque JavaScript. Surveillez cela :
// Wait for reCAPTCHA script to load
await page.waitForFunction(() => {
return typeof window.grecaptcha !== 'undefined'
&& typeof window.grecaptcha.render === 'function';
}, { timeout: 30000 });
// Now extract parameters
const sitekey = await page.evaluate(() => {
const el = document.querySelector('.g-recaptcha');
return el?.getAttribute('data-sitekey');
});
Pour tourniquet
await page.waitForFunction(() => {
return typeof window.turnstile !== 'undefined';
}, { timeout: 30000 });
const sitekey = await page.evaluate(() => {
const el = document.querySelector('.cf-turnstile');
return el?.getAttribute('data-sitekey');
});
Méthode 3 : intercepter les appels de rendu
Connectez-vous à la bibliothèque CAPTCHA avant le rendu :
// Inject before page scripts run
await page.evaluateOnNewDocument(() => {
window.__captchaDetected = null;
// Hook grecaptcha.render
let _grecaptcha;
Object.defineProperty(window, 'grecaptcha', {
set(val) {
_grecaptcha = val;
const origRender = val.render;
val.render = function(container, params) {
window.__captchaDetected = {
type: 'recaptcha',
sitekey: params.sitekey,
callback: params.callback?.name,
container: typeof container === 'string' ? container : container.id,
};
return origRender.apply(this, arguments);
};
},
get() { return _grecaptcha; },
});
});
await page.goto('https://example.com/signup');
// Trigger the CAPTCHA (click, scroll, etc.)
await page.click('#show-form');
// Wait for detection
await page.waitForFunction(() => window.__captchaDetected !== null, {
timeout: 30000,
});
const detected = await page.evaluate(() => window.__captchaDetected);
console.log('Detected:', detected);
// { type: 'recaptcha', sitekey: '6Le-wvkS...', callback: 'onCaptcha', container: 'recaptcha-box' }
Python (Selenium) : En attente de CAPTCHA paresseux
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Chrome()
driver.get("https://example.com/login")
# Trigger the CAPTCHA loading
submit = driver.find_element(By.ID, "submit-btn")
submit.click()
# Wait for CAPTCHA to appear
try:
captcha_el = WebDriverWait(driver, 30).until(
EC.presence_of_element_located((
By.CSS_SELECTOR,
".g-recaptcha, .cf-turnstile, .h-captcha"
))
)
sitekey = captcha_el.get_attribute("data-sitekey")
captcha_class = captcha_el.get_attribute("class")
if "g-recaptcha" in captcha_class:
captcha_type = "recaptcha"
elif "cf-turnstile" in captcha_class:
captcha_type = "turnstile"
else:
captcha_type = "hcaptcha"
print(f"Type: {captcha_type}, Sitekey: {sitekey}")
except Exception:
print("No CAPTCHA appeared within 30 seconds")
En attente d'une iframe (reCAPTCHA)
# reCAPTCHA loads an iframe even when the div exists but the script is still loading
WebDriverWait(driver, 30).until(
EC.presence_of_element_located((
By.CSS_SELECTOR,
"iframe[src*='recaptcha'], iframe[src*='challenges.cloudflare.com']"
))
)
print("CAPTCHA iframe loaded")
Détection complète + flux de résolution
import requests
import time
def detect_and_solve(driver, api_key, trigger_action=None):
"""Detect a lazy-loaded CAPTCHA, solve it, and inject the token."""
# 1. Trigger the CAPTCHA
if trigger_action:
trigger_action(driver)
# 2. Wait for it to appear
captcha_el = WebDriverWait(driver, 30).until(
EC.presence_of_element_located((
By.CSS_SELECTOR,
".g-recaptcha, .cf-turnstile, .h-captcha"
))
)
sitekey = captcha_el.get_attribute("data-sitekey")
page_url = driver.current_url
captcha_class = captcha_el.get_attribute("class")
# 3. Determine type and method
if "g-recaptcha" in captcha_class:
method, key_param, token_field = "userrecaptcha", "googlekey", "g-recaptcha-response"
elif "cf-turnstile" in captcha_class:
method, key_param, token_field = "turnstile", "sitekey", "cf-turnstile-response"
else:
method, key_param, token_field = "hcaptcha", "sitekey", "h-captcha-response"
# 4. Solve with CaptchaAI
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": api_key, "method": method,
key_param: sitekey, "pageurl": page_url, "json": "1",
}).json()
task_id = resp["request"]
for _ in range(24):
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["status"] == 1:
token = result["request"]
break
# 5. Inject
driver.execute_script(f"""
const el = document.querySelector('textarea[name="{token_field}"], input[name="{token_field}"]');
if (el) el.value = arguments[0];
""", token)
return token
Dépannage
| Problème | Parce que | Corriger |
|---|---|---|
| CAPTCHA n'apparaît jamais | Mauvaise action de déclenchement | Inspectez la page pour trouver ce qui déclenche le CAPTCHA |
| La clé du site est nulle | L'élément existe mais le script ne s'est pas exécuté | Attendez l'iframe CAPTCHA, pas seulement le div |
| L'observateur le manque | CAPTCHA était déjà là | Vérifiez les éléments existants avant de configurer l'observateur |
| Délai d'attente | CAPTCHA se charge uniquement pour les vrais utilisateurs | Utilisez un navigateur complet avec une empreinte digitale réaliste |
FAQ
Comment savoir si un CAPTCHA est chargé paresseux ?
Afficher la source de la page (Ctrl+U). Si le div ou le script CAPTCHA n'est pas là mais apparaît lorsque vous interagissez avec la page, il est chargé paresseux.
Est-ce que cela fonctionne avec les navigateurs sans tête ?
Oui, avec des réserves. Certains sites chargent uniquement des CAPTCHA pour les navigateurs non-headless. Utilisez headless: 'new' dans Puppeteer ou des plugins furtifs.
Résolvez n'importe quel CAPTCHA avec CaptchaAI
Obtenez votre clé API surcaptchaai.com.
Guides associés
- Détection CAPTCHA de la console du navigateur
- Gestion de plusieurs CAPTCHA sur une seule page
- Extraction des paramètres reCAPTCHA