Quand un reCAPTCHA Invisible refuse de passer, la cause n'est presque jamais un mauvais sitekey : dans la majorité des cas, c'est le callback JavaScript qui n'a jamais été déclenché après l'injection du token. reCAPTCHA Invisible retire la case à cocher, mais introduit son propre lot de pièges pour l'automatisation :
- Widget non détecté sur la page
- Callback ignoré après l'injection du token
- Token expiré avant la soumission
- Paramètres de la v2 standard réutilisés à tort sur un flux invisible
Point clé : si le token est accepté mais que le formulaire ne bouge pas, vérifiez toujours le callback JavaScript en premier — c'est la cause la plus fréquente, loin devant un mauvais sitekey.
Ce guide détaille chaque schéma d'erreur avec son correctif exact. Pour comprendre d'abord le mécanisme, consultez Comment fonctionne reCAPTCHA Invisible et comment le résoudre.
Tableau de référence : erreurs et correctifs
| Erreur | Cause | Correctif |
|---|---|---|
ERROR_WRONG_GOOGLEKEY |
Sitekey incorrect, ou sitekey provenant d'un autre domaine | Extrayez le sitekey depuis le div du widget invisible ou l'appel grecaptcha.render() |
ERROR_PAGEURL |
URL envoyée = page parente au lieu de l'URL de l'iframe | Utilisez l'URL exacte où le widget invisible se charge |
ERROR_CAPTCHA_UNSOLVABLE |
Google a marqué la tâche comme impossible à résoudre | Relancez avec un proxy et des cookies neufs ; vérifiez si le site est passé en v3 |
ERROR_BAD_TOKEN_OR_PAGEURL |
Token refusé par le site cible | Vérifiez la correspondance exacte du pageurl ; injectez via le callback, jamais via un champ caché |
CAPCHA_NOT_READY |
La tâche est encore en cours de traitement | Continuez à interroger toutes les 5 secondes ; une résolution invisible prend 10 à 30 s |
ERROR_KEY_DOES_NOT_EXIST |
Clé API CaptchaAI invalide | Vérifiez la clé sur captchaai.com/account |
| Token accepté mais le formulaire ne réagit pas | Callback jamais exécuté après l'injection du token | Repérez et appelez la fonction data-callback avec le token |
Identifier le bon widget : détection et sitekey
Deux erreurs partagent la même origine : votre code ne cible pas le widget invisible exact que la page a chargé.
Erreur 1 : le widget invisible n'est pas détecté sur la page
Un reCAPTCHA Invisible ne montre aucune case à cocher. Si votre scraper ne le détecte pas, les requêtes protégées par CAPTCHA échouent en silence :
- Formulaire qui ne se soumet jamais
- Redirection inattendue vers la page précédente
- Aucun message d'erreur explicite à se mettre sous la dent
Comment repérer un reCAPTCHA Invisible dans le HTML
Recherchez ces trois schémas dans le code de la page :
<!-- Pattern 1: div with data-size="invisible" -->
<div class="g-recaptcha" data-sitekey="6LdKlZEU..."
data-size="invisible"
data-callback="onSubmit"></div>
<!-- Pattern 2: button with data-sitekey and invisible size -->
<button class="g-recaptcha"
data-sitekey="6LdKlZEU..."
data-callback="onSubmit"
data-action="submit">Submit</button>
<!-- Pattern 3: programmatic render with size: invisible -->
<script>
grecaptcha.render('submit-btn', {
sitekey: '6LdKlZEU...',
callback: onSubmit,
size: 'invisible'
});
</script>
Script de détection (Python) :
import requests
from bs4 import BeautifulSoup
import re
def detect_invisible_recaptcha(url):
resp = requests.get(url)
soup = BeautifulSoup(resp.text, "html.parser")
# Check for data-size="invisible"
widget = soup.find("div", {"data-size": "invisible", "class": "g-recaptcha"})
if widget:
return {
"type": "invisible",
"sitekey": widget.get("data-sitekey"),
"callback": widget.get("data-callback")
}
# Check for programmatic render with invisible
scripts = soup.find_all("script")
for script in scripts:
if script.string and "size" in str(script.string) and "invisible" in str(script.string):
key_match = re.search(r"sitekey['\"]?\s*[:=]\s*['\"]([^'\"]+)", script.string)
if key_match:
return {
"type": "invisible-programmatic",
"sitekey": key_match.group(1),
"callback": "check grecaptcha.render() call"
}
return None
Script de détection (Node.js) :
const axios = require("axios");
const cheerio = require("cheerio");
async function detectInvisibleRecaptcha(url) {
const { data } = await axios.get(url);
const $ = cheerio.load(data);
// Check for data-size="invisible"
const widget = $(".g-recaptcha[data-size='invisible']");
if (widget.length) {
return {
type: "invisible",
sitekey: widget.attr("data-sitekey"),
callback: widget.attr("data-callback"),
};
}
// Check script tags for programmatic invisible render
const scriptContent = $("script")
.map((_, el) => $(el).html())
.get()
.join("\n");
if (scriptContent.includes("invisible")) {
const keyMatch = scriptContent.match(/sitekey['"]?\s*[:=]\s*['"]([^'"]+)/);
if (keyMatch) {
return {
type: "invisible-programmatic",
sitekey: keyMatch[1],
callback: "check grecaptcha.render() call",
};
}
}
return null;
}
Erreur 2 : sitekey incorrect — ERROR_WRONG_GOOGLEKEY
Cette erreur survient quand le sitekey envoyé ne correspond pas au widget reCAPTCHA Invisible de la page cible. Causes fréquentes :
- Sitekey copié depuis une case à cocher v2 présente sur une autre page
- Sitekey extrait depuis l'URL d'ancrage d'une autre version de reCAPTCHA
- La page contient plusieurs widgets reCAPTCHA, et le mauvais a été sélectionné
Correctif : extraire le bon sitekey invisible
import requests
from bs4 import BeautifulSoup
def get_invisible_sitekey(url):
resp = requests.get(url)
soup = BeautifulSoup(resp.text, "html.parser")
# Priority 1: invisible widget
widget = soup.find(attrs={"data-size": "invisible", "class": "g-recaptcha"})
if widget:
return widget["data-sitekey"]
# Priority 2: any g-recaptcha div (may be invisible without data-size)
widget = soup.find(class_="g-recaptcha")
if widget and widget.get("data-sitekey"):
return widget["data-sitekey"]
return None
sitekey = get_invisible_sitekey("https://example.com/login")
print(f"Sitekey: {sitekey}")
Déclencher la résolution : callback et paramètres de requête
Une fois le bon widget identifié, reste à déclencher correctement le traitement côté page.
Erreur 3 : le callback n'est jamais exécuté — le formulaire ne réagit pas
C'est l'erreur invisible la plus fréquente, et la plus facile à manquer. Sur la case à cocher v2, injecter le token dans g-recaptcha-response suffit. Sur reCAPTCHA Invisible, ce n'est presque jamais le cas : le widget appelle une fonction JavaScript callback, et si le token est injecté sans déclencher ce callback, le formulaire ne sera jamais traité — même avec un token parfaitement valide.
Comment fonctionne le flux du callback
grecaptcha.execute()déclenche le défi invisible- Une fois le défi résolu, Google appelle la fonction définie dans
data-callback - Cette fonction callback soumet le formulaire ou déclenche l'appel API
Correctif : identifier et exécuter le callback
Étape 1 — repérez le nom du callback :
# From HTML: data-callback="onSubmit"
# From JS: callback: onSubmit
# From grecaptcha.render: second argument with callback property
Étape 2 — injectez le token ET appelez le callback (Selenium) :
from selenium import webdriver
import requests
import time
driver = webdriver.Chrome()
driver.get("https://example.com/form")
# Get sitekey
sitekey = driver.find_element("css selector", ".g-recaptcha").get_attribute("data-sitekey")
callback_name = driver.find_element("css selector", ".g-recaptcha").get_attribute("data-callback")
# Solve with CaptchaAI
task_id = requests.get("https://ocr.captchaai.com/in.php", params={
"key": "YOUR_API_KEY",
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": driver.current_url,
"invisible": 1
}).text.split("|")[1]
# Poll for result
token = None
for _ in range(60):
time.sleep(5)
resp = requests.get("https://ocr.captchaai.com/res.php", params={
"key": "YOUR_API_KEY",
"action": "get",
"id": task_id
}).text
if resp.startswith("OK|"):
token = resp.split("|")[1]
break
# Inject token into the response field
driver.execute_script(
f'document.getElementById("g-recaptcha-response").value = "{token}";'
)
# CRITICAL: Call the callback function
driver.execute_script(f'{callback_name}("{token}");')
Étape 2 — injectez le token ET appelez le callback (Puppeteer) :
const puppeteer = require("puppeteer");
const axios = require("axios");
(async () => {
const browser = await puppeteer.launch({ headless: "new" });
const page = await browser.newPage();
await page.goto("https://example.com/form");
// Get sitekey and callback
const { sitekey, callback } = await page.evaluate(() => {
const el = document.querySelector(".g-recaptcha[data-size='invisible']");
return {
sitekey: el?.getAttribute("data-sitekey"),
callback: el?.getAttribute("data-callback"),
};
});
// Submit to CaptchaAI
const submitResp = await axios.get("https://ocr.captchaai.com/in.php", {
params: {
key: "YOUR_API_KEY",
method: "userrecaptcha",
googlekey: sitekey,
pageurl: page.url(),
invisible: 1,
},
});
const taskId = submitResp.data.split("|")[1];
// Poll for result
let token;
for (let i = 0; i < 60; i++) {
await new Promise((r) => setTimeout(r, 5000));
const result = await axios.get("https://ocr.captchaai.com/res.php", {
params: { key: "YOUR_API_KEY", action: "get", id: taskId },
});
if (result.data.startsWith("OK|")) {
token = result.data.split("|")[1];
break;
}
}
// Inject token and fire callback
await page.evaluate(
(tok, cb) => {
document.getElementById("g-recaptcha-response").value = tok;
if (cb && typeof window[cb] === "function") {
window[cb](tok);
}
},
token,
callback,
);
await browser.close();
})();
Erreur 4 : paramètre invisible=1 manquant
Lorsque vous résolvez un reCAPTCHA Invisible avec CaptchaAI, le paramètre invisible=1 est obligatoire. Sans lui, l'API traite la tâche comme un défi v2 standard, ce qui déclenche souvent ERROR_CAPTCHA_UNSOLVABLE ou renvoie un token que le site cible refuse.
Requête incorrecte vs requête correcte
# WRONG — missing invisible=1
params = {
"key": "YOUR_API_KEY",
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": page_url
}
# CORRECT — includes invisible=1
params = {
"key": "YOUR_API_KEY",
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": page_url,
"invisible": 1 # Required for invisible reCAPTCHA
}
response = requests.get("https://ocr.captchaai.com/in.php", params=params)
Après la résolution : validation, délais et widgets multiples
Le token est émis — reste à le faire accepter avant expiration ou rejet.
Erreur 5 : le token expire avant la soumission
Les tokens de reCAPTCHA Invisible expirent au bout de 120 secondes, comme en v2 standard. Mais un flux invisible ajoute souvent des étapes de traitement entre la résolution et la soumission — ce qui rend l'expiration plus probable qu'en v2.
Symptômes
- Le formulaire renvoie une erreur générique après l'injection du token
siteverifycôté serveur renvoietimeout-or-duplicate- Le token était valide, mais a mis trop de temps à atteindre l'étape de soumission
Correctif : ne résolvez qu'au moment de soumettre
Ne demandez la résolution que lorsque vous êtes prêt à soumettre immédiatement :
import requests
import time
def solve_invisible_recaptcha(api_key, sitekey, page_url):
# Submit task
resp = requests.get("https://ocr.captchaai.com/in.php", params={
"key": api_key,
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": page_url,
"invisible": 1
})
if not resp.text.startswith("OK|"):
raise Exception(f"Submit failed: {resp.text}")
task_id = resp.text.split("|")[1]
# Poll for result
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
})
if result.text.startswith("OK|"):
return result.text.split("|")[1]
if result.text != "CAPCHA_NOT_READY":
raise Exception(f"Solve failed: {result.text}")
raise Exception("Solve timed out after 5 minutes")
# Usage: solve JUST before you need to submit
# 1. Navigate to page and prepare form data first
# 2. THEN solve the captcha
# 3. Inject token and submit immediately
token = solve_invisible_recaptcha("YOUR_API_KEY", sitekey, page_url)
# Submit within 120 seconds of receiving the token
Erreur 6 : token refusé — ERROR_BAD_TOKEN_OR_PAGEURL
Le site cible a vérifié le token auprès de Google, et la vérification a échoué. Causes fréquentes :
| Cause | Comment la repérer | Correctif |
|---|---|---|
Mauvais pageurl |
L'URL ne correspond pas au domaine enregistré pour le sitekey | Utilisez l'URL exacte où le widget se charge |
| Token utilisé sur un domaine différent | Réutilisation du token entre domaines | Résolvez avec le pageurl du bon domaine |
| Token déjà utilisé | Le même token est soumis deux fois | Demandez une nouvelle résolution à chaque soumission |
| Incompatibilité d'IP | L'IP de votre serveur diffère de celle utilisée pour la résolution | Ajoutez le paramètre proxy pour faire correspondre l'IP de la session |
| Drapeau invisible manquant | Résolu en mode v2 standard, utilisé sur une page invisible | Ajoutez invisible=1 à la requête de résolution |
Cas particulier : workers hébergés en Europe
L'incompatibilité d'IP touche particulièrement les équipes qui hébergent leurs workers sur un datacenter européen. C'est une cause récurrente de ERROR_BAD_TOKEN_OR_PAGEURL en production, alors que le même code fonctionne sans problème en local :
- Un serveur OVHcloud à Roubaix n'a pas la même IP publique que le pool utilisé pour la résolution
- Une instance Scaleway à Paris rencontre le même écart d'IP entre la session et le solveur
Checklist de débogage
def debug_invisible_solve(api_key, sitekey, page_url, proxy=None):
"""Run a diagnostic solve with detailed logging."""
print(f"Sitekey: {sitekey}")
print(f"Page URL: {page_url}")
print(f"Proxy: {proxy or 'none'}")
params = {
"key": api_key,
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": page_url,
"invisible": 1
}
if proxy:
params["proxy"] = proxy
params["proxytype"] = "HTTP"
# Submit
resp = requests.get("https://ocr.captchaai.com/in.php", params=params)
print(f"Submit response: {resp.text}")
if not resp.text.startswith("OK|"):
return None
task_id = resp.text.split("|")[1]
print(f"Task ID: {task_id}")
# Poll with timing
start = time.time()
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
})
elapsed = time.time() - start
print(f" [{elapsed:.0f}s] {result.text[:50]}")
if result.text.startswith("OK|"):
token = result.text.split("|")[1]
print(f"Token received after {elapsed:.0f}s")
print(f"Token length: {len(token)} characters")
print(f"Token starts with: {token[:30]}...")
return token
if result.text != "CAPCHA_NOT_READY":
print(f"FAILED: {result.text}")
return None
print("TIMEOUT after 5 minutes")
return None
Erreur 7 : plusieurs widgets reCAPTCHA sur une même page
Certaines pages combinent une case à cocher v2 visible ET un reCAPTCHA Invisible. Si le mauvais widget est résolu, le token est valide mais ne correspond pas à celui qui protège l'action recherchée.
Correctif : cibler le bon widget
from bs4 import BeautifulSoup
def find_all_recaptcha_widgets(html):
soup = BeautifulSoup(html, "html.parser")
widgets = []
for el in soup.find_all(class_="g-recaptcha"):
widgets.append({
"sitekey": el.get("data-sitekey"),
"size": el.get("data-size", "normal"),
"callback": el.get("data-callback"),
"tag": el.name,
"id": el.get("id")
})
return widgets
# Example output:
# [
# {"sitekey": "6LdA...", "size": "normal", "callback": None, "tag": "div", "id": "recaptcha-login"},
# {"sitekey": "6LdB...", "size": "invisible", "callback": "onRegister", "tag": "div", "id": "recaptcha-register"}
# ]
# Use the widget with size="invisible" for the invisible solve
Solveur reCAPTCHA Invisible complet, avec gestion des erreurs
Ce wrapper prêt pour la production gère l'ensemble des erreurs ci-dessus :
import requests
import time
import logging
logger = logging.getLogger(__name__)
class InvisibleRecaptchaSolver:
def __init__(self, api_key, max_retries=3):
self.api_key = api_key
self.max_retries = max_retries
self.base_url = "https://ocr.captchaai.com"
def solve(self, sitekey, page_url, proxy=None):
"""Solve invisible reCAPTCHA with automatic retry on transient errors."""
for attempt in range(1, self.max_retries + 1):
try:
token = self._attempt_solve(sitekey, page_url, proxy)
if token:
return token
except Exception as e:
logger.warning(f"Attempt {attempt} failed: {e}")
if attempt < self.max_retries:
time.sleep(2 ** attempt)
raise Exception(f"Failed to solve after {self.max_retries} attempts")
def _attempt_solve(self, sitekey, page_url, proxy):
params = {
"key": self.api_key,
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": page_url,
"invisible": 1
}
if proxy:
params["proxy"] = proxy
params["proxytype"] = "HTTP"
# Submit task
resp = requests.get(f"{self.base_url}/in.php", params=params)
if "ERROR" in resp.text:
error = resp.text.strip()
if error in ("ERROR_WRONG_GOOGLEKEY", "ERROR_KEY_DOES_NOT_EXIST"):
raise Exception(f"Configuration error (do not retry): {error}")
if error == "ERROR_ZERO_BALANCE":
raise Exception("Account balance is zero — add funds")
raise Exception(f"Submit error: {error}")
if not resp.text.startswith("OK|"):
raise Exception(f"Unexpected submit response: {resp.text}")
task_id = resp.text.split("|")[1]
# Poll for result
for _ in range(60):
time.sleep(5)
result = requests.get(f"{self.base_url}/res.php", params={
"key": self.api_key,
"action": "get",
"id": task_id
})
if result.text.startswith("OK|"):
return result.text.split("|")[1]
if result.text == "CAPCHA_NOT_READY":
continue
if result.text == "ERROR_CAPTCHA_UNSOLVABLE":
logger.warning("Captcha unsolvable — will retry with new task")
return None
raise Exception(f"Poll error: {result.text}")
raise Exception("Solve timed out after 5 minutes")
# Usage
solver = InvisibleRecaptchaSolver("YOUR_API_KEY")
token = solver.solve(
sitekey="6LdKlZEU...",
page_url="https://example.com/login"
)
print(f"Token: {token[:50]}...")
const axios = require("axios");
class InvisibleRecaptchaSolver {
constructor(apiKey, maxRetries = 3) {
this.apiKey = apiKey;
this.maxRetries = maxRetries;
this.baseUrl = "https://ocr.captchaai.com";
}
async solve(sitekey, pageUrl, proxy) {
for (let attempt = 1; attempt <= this.maxRetries; attempt++) {
try {
const token = await this._attemptSolve(sitekey, pageUrl, proxy);
if (token) return token;
} catch (err) {
console.warn(`Attempt ${attempt} failed: ${err.message}`);
if (attempt < this.maxRetries) {
await new Promise((r) => setTimeout(r, 2 ** attempt * 1000));
}
}
}
throw new Error(`Failed to solve after ${this.maxRetries} attempts`);
}
async _attemptSolve(sitekey, pageUrl, proxy) {
const params = {
key: this.apiKey,
method: "userrecaptcha",
googlekey: sitekey,
pageurl: pageUrl,
invisible: 1,
};
if (proxy) {
params.proxy = proxy;
params.proxytype = "HTTP";
}
// Submit task
const submitResp = await axios.get(`${this.baseUrl}/in.php`, { params });
if (submitResp.data.includes("ERROR")) {
const error = submitResp.data.trim();
if (["ERROR_WRONG_GOOGLEKEY", "ERROR_KEY_DOES_NOT_EXIST"].includes(error)) {
throw new Error(`Configuration error (do not retry): ${error}`);
}
throw new Error(`Submit error: ${error}`);
}
const taskId = submitResp.data.split("|")[1];
// Poll for result
for (let i = 0; i < 60; i++) {
await new Promise((r) => setTimeout(r, 5000));
const result = await axios.get(`${this.baseUrl}/res.php`, {
params: { key: this.apiKey, action: "get", id: taskId },
});
if (result.data.startsWith("OK|")) {
return result.data.split("|")[1];
}
if (result.data === "CAPCHA_NOT_READY") continue;
if (result.data === "ERROR_CAPTCHA_UNSOLVABLE") return null;
throw new Error(`Poll error: ${result.data}`);
}
throw new Error("Solve timed out after 5 minutes");
}
}
// Usage
const solver = new InvisibleRecaptchaSolver("YOUR_API_KEY");
solver.solve("6LdKlZEU...", "https://example.com/login").then((token) => {
console.log(`Token: ${token.substring(0, 50)}...`);
});
Checklist de dépannage reCAPTCHA Invisible
Parcourez cette liste quand une résolution de reCAPTCHA Invisible échoue :
| Étape | Vérifier | Commande / action |
|---|---|---|
| 1 | Confirmer qu'il s'agit bien d'invisible, pas de v2 standard | Recherchez data-size="invisible" ou size: 'invisible' dans l'appel de rendu |
| 2 | Vérifier que le sitekey est correct | Comparez avec data-sitekey sur le widget invisible spécifiquement |
| 3 | Confirmer invisible=1 dans la requête API |
Vérifiez vos paramètres in.php |
| 4 | Vérifier que pageurl correspond exactement |
Utilisez l'URL DevTools du navigateur, pas une URL de redirection |
| 5 | Retrouver le nom de la fonction callback | Recherchez l'attribut data-callback ou callback dans grecaptcha.render() |
| 6 | Vérifier l'injection du token + l'appel du callback | Les deux étapes sont nécessaires : le token seul ne suffit pas |
| 7 | Vérifier la fraîcheur du token | Le token doit être utilisé dans les 120 secondes |
| 8 | Tester avec un proxy si l'IP compte | Ajoutez les paramètres proxy et proxytype |
FAQ
Le callback reCAPTCHA Invisible ne se déclenche jamais : par où commencer ?
Vérifiez d'abord que le widget porte bien un attribut data-callback, ou un argument callback dans grecaptcha.render(). Si l'attribut existe, injectez le token dans g-recaptcha-response puis appelez explicitement la fonction JavaScript correspondante — sur un widget invisible, l'injection seule ne déclenche jamais le traitement du formulaire, contrairement à la v2 standard.
Quel plan CaptchaAI choisir pour absorber un pic de trafic sur reCAPTCHA Invisible ?
Cela dépend du nombre de résolutions simultanées, pas du volume total : chaque plan facture des threads, avec un nombre illimité de résolutions par thread.
- Script de test ou petit crawler : BASIC ($15/mois, 5 threads) suffit largement
- Pic ponctuel sur un formulaire à fort trafic : passez temporairement sur ADVANCE ($90/mois, 50 threads) ou PREMIUM ($170/mois, 100 threads), puis redescendez une fois le pic passé
Pourquoi le token fonctionne en test, mais est rejeté en production ?
Le plus souvent, une incompatibilité d'IP. En test, votre poste et le solveur peuvent partager une IP proche. En production, le token remonté par CaptchaAI provient d'une IP différente de celle de votre serveur ou de votre worker — un cas fréquent pour les équipes hébergées sur un datacenter européen. Ajoutez le paramètre proxy pour faire correspondre l'IP de la session à celle utilisée pour la résolution.
Combien de temps prend la résolution d'un reCAPTCHA Invisible via l'API CaptchaAI ?
En général 10 à 30 secondes. Un défi invisible se résout souvent plus vite qu'une case à cocher v2, car il repose sur une analyse de risque côté Google plutôt que sur la reconnaissance d'image.
Un reCAPTCHA Invisible peut-il se déclencher plusieurs fois sur la même page ?
Oui. Si le formulaire appelle grecaptcha.execute() à chaque tentative — par exemple après une erreur de mot de passe sur un login — chaque appel génère un nouveau token avec sa propre fenêtre de validité de 120 secondes. Ne réutilisez jamais le token d'un appel précédent, même si le sitekey n'a pas changé : réinjectez-le et rappelez le callback à chaque nouvelle tentative.
À retenir : callback exécuté, sitekey du bon widget,
invisible=1présent, token soumis dans les 120 secondes — ces quatre vérifications résolvent la grande majorité des échecs de reCAPTCHA Invisible.
Prochaines étapes
- Comment fonctionne reCAPTCHA Invisible et comment le résoudre — le mécanisme complet avant de dépanner
- Comment résoudre reCAPTCHA v2 avec l'API — la résolution standard v2, pour comparaison
- Erreurs courantes de résolution reCAPTCHA v2 — les mêmes pièges côté v2 standard
- Codes d'erreur CaptchaAI : la référence complète — tous les codes d'erreur au même endroit
Articles connexes
- Résoudre reCAPTCHA Invisible en Python
- Erreurs courantes du CAPTCHA en grille d'images
- reCAPTCHA v2 face à Invisible