Troubleshooting

Erreurs et correctifs courants de reCAPTCHA Invisible

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

  1. grecaptcha.execute() déclenche le défi invisible
  2. Une fois le défi résolu, Google appelle la fonction définie dans data-callback
  3. 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
  • siteverify côté serveur renvoie timeout-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=1 présent, token soumis dans les 120 secondes — ces quatre vérifications résolvent la grande majorité des échecs de reCAPTCHA Invisible.


Prochaines étapes

Articles connexes

Les commentaires sont désactivés pour cet article.