Comparisons

Différences entre les solveurs Standard et Enterprise reCAPTCHA v2

enterprise=1 : ce paramètre est la seule différence entre résoudre un reCAPTCHA v2 standard et un reCAPTCHA v2 Enterprise avec l'API CaptchaAI. Case « Je ne suis pas un robot », grilles d'images, format du token, polling : le reste est identique. Tout se joue donc en amont, sur la détection — et l'erreur ne lève aucune exception : vous obtenez un token bien formé, que le site refuse ensuite sans explication.

Détecter reCAPTCHA v2 Enterprise avant d'envoyer la tâche

Rien à l'écran ne sépare les deux versions. Le seul signal fiable est le fichier JavaScript chargé.

Le src de la balise script

<!-- Standard v2 -->
<script src="https://www.google.com/recaptcha/api.js"></script>

<!-- Enterprise v2 -->
<script src="https://www.google.com/recaptcha/enterprise.js"></script>

La détection automatisée en Python

import requests
from bs4 import BeautifulSoup

def detect_recaptcha_version(url):
    resp = requests.get(url)
    soup = BeautifulSoup(resp.text, "html.parser")

    enterprise_script = soup.find("script", src=lambda s: s and "enterprise.js" in s)
    standard_script = soup.find("script", src=lambda s: s and "recaptcha/api.js" in s)

    widget = soup.find(class_="g-recaptcha")
    sitekey = widget["data-sitekey"] if widget else None

    if enterprise_script:
        return {"version": "enterprise_v2", "sitekey": sitekey}
    elif standard_script:
        return {"version": "standard_v2", "sitekey": sitekey}
    return None

info = detect_recaptcha_version("https://example.com/login")
print(info)

Le même contrôle en Node.js

const axios = require("axios");
const cheerio = require("cheerio");

async function detectRecaptchaVersion(url) {
  const { data } = await axios.get(url);
  const $ = cheerio.load(data);

  const hasEnterprise = $('script[src*="enterprise.js"]').length > 0;
  const hasStandard = $('script[src*="recaptcha/api.js"]').length > 0;
  const sitekey = $(".g-recaptcha").attr("data-sitekey");

  if (hasEnterprise) return { version: "enterprise_v2", sitekey };
  if (hasStandard) return { version: "standard_v2", sitekey };
  return null;
}

Le contrôle manuel dans la console DevTools

// Quick check in DevTools
if (document.querySelector('script[src*="enterprise.js"]')) {
  console.log("Enterprise v2");
} else if (document.querySelector('script[src*="recaptcha/api.js"]')) {
  console.log("Standard v2");
}
  • Widget injecté après le chargement : le HTML brut ne contient alors aucun des deux fichiers. Attendez .g-recaptcha en navigateur headless, puis relisez le DOM.
  • Journalisez la version détectée : le jour où un site bascule vers enterprise.js, vos logs vous préviennent avant vos tickets de support.

Ce qui change réellement entre les deux versions

  • Côté défi : rien ne bouge, mêmes images, même token.
  • Côté éditeur : seuils par action, codes de motif, facturation par projet Google Cloud.
  • Côté code client : la seule variable est enterprise=1, mais la vérification serveur sait quelle clé a produit le token.
Caractéristique Standard v2 Enterprise v2
Fichier JS chargé api.js enterprise.js
Fonction d'exécution grecaptcha.execute() grecaptcha.enterprise.execute()
API de vérification siteverify (gratuite) recaptchaenterprise.googleapis.com (payante)
Codes de motif Non Oui (AUTOMATION, TOO_MUCH_TRAFFIC, etc.)
Règles personnalisées Non Oui (seuils par action)
Google Cloud Console Non Oui (gestion par projet)
Paramètre CaptchaAI enterprise=1
Temps de résolution < 60 s < 60 s

Résoudre les deux versions avec l'API CaptchaAI

Standard v2 : la requête de référence

import requests
import time

# Submit task
resp = requests.get("https://ocr.captchaai.com/in.php", params={
    "key": "YOUR_API_KEY",
    "method": "userrecaptcha",
    "googlekey": sitekey,
    "pageurl": page_url
})
task_id = resp.text.split("|")[1]

# Poll for token
for _ in range(60):
    time.sleep(5)
    result = requests.get("https://ocr.captchaai.com/res.php", params={
        "key": "YOUR_API_KEY", "action": "get", "id": task_id
    })
    if result.text.startswith("OK|"):
        token = result.text.split("|")[1]
        break

Enterprise v2 : un paramètre de plus

import requests
import time

# Submit task — only difference is enterprise=1
resp = requests.get("https://ocr.captchaai.com/in.php", params={
    "key": "YOUR_API_KEY",
    "method": "userrecaptcha",
    "googlekey": sitekey,
    "pageurl": page_url,
    "enterprise": 1  # Required for Enterprise
})
task_id = resp.text.split("|")[1]

# Polling is identical
for _ in range(60):
    time.sleep(5)
    result = requests.get("https://ocr.captchaai.com/res.php", params={
        "key": "YOUR_API_KEY", "action": "get", "id": task_id
    })
    if result.text.startswith("OK|"):
        token = result.text.split("|")[1]
        break

Endpoint, méthode et token renvoyé ne bougent pas : maintenir deux chemins de code séparés ne crée que des occasions de divergence.

Une classe unique qui choisit toute seule

import requests
import time
from bs4 import BeautifulSoup

class RecaptchaV2Solver:
    def __init__(self, api_key):
        self.api_key = api_key

    def detect_and_solve(self, page_url, page_html=None):
        if not page_html:
            page_html = requests.get(page_url).text

        soup = BeautifulSoup(page_html, "html.parser")
        is_enterprise = bool(soup.find("script", src=lambda s: s and "enterprise.js" in s))
        widget = soup.find(class_="g-recaptcha")
        sitekey = widget["data-sitekey"] if widget else None

        if not sitekey:
            raise Exception("No reCAPTCHA sitekey found on page")

        params = {
            "key": self.api_key,
            "method": "userrecaptcha",
            "googlekey": sitekey,
            "pageurl": page_url
        }
        if is_enterprise:
            params["enterprise"] = 1

        resp = requests.get("https://ocr.captchaai.com/in.php", params=params)
        if not resp.text.startswith("OK|"):
            raise Exception(f"Submit failed: {resp.text}")

        task_id = resp.text.split("|")[1]

        for _ in range(60):
            time.sleep(5)
            result = requests.get("https://ocr.captchaai.com/res.php", params={
                "key": self.api_key, "action": "get", "id": task_id
            })
            if result.text.startswith("OK|"):
                return {
                    "token": result.text.split("|")[1],
                    "is_enterprise": is_enterprise,
                    "sitekey": sitekey
                }
            if result.text != "CAPCHA_NOT_READY":
                raise Exception(f"Solve failed: {result.text}")

        raise Exception("Solve timed out")


solver = RecaptchaV2Solver("YOUR_API_KEY")
result = solver.detect_and_solve("https://example.com/login")
print(f"Enterprise: {result['is_enterprise']}, Token: {result['token'][:40]}...")

Un seul chemin de code, donc un seul endroit à corriger. Traitez CAPCHA_NOT_READY comme une attente normale, tout autre retour comme une erreur.


Injecter le token : rigoureusement identique

Le champ cible reste g-recaptcha-response, et le callback se déclenche de la même façon dans les deux cas.

# Selenium injection — works for both standard and enterprise
driver.execute_script(
    f'document.getElementById("g-recaptcha-response").value = "{token}";'
)

# If the page uses a callback function
callback = driver.find_element("css selector", ".g-recaptcha").get_attribute("data-callback")
if callback:
    driver.execute_script(f'{callback}("{token}");')
// Puppeteer injection — works for both
await page.evaluate((token) => {
  document.getElementById("g-recaptcha-response").value = token;
  // Find and call callback if present
  const widget = document.querySelector(".g-recaptcha");
  const cb = widget?.getAttribute("data-callback");
  if (cb && typeof window[cb] === "function") {
    window[cb](token);
  }
}, token);

Pièges fréquents et correctifs

  • enterprise=1 envoyé à une page standard. Le token revient bien formé, mais peut être invalide à la vérification. Confirmez enterprise.js avant d'ajouter le paramètre.
  • enterprise=1 oublié sur une page Enterprise. Le backend du site rejette le token.
  • Mauvais sitekey transmis. Vous recevez ERROR_WRONG_GOOGLEKEY : relisez data-sitekey dans le DOM.
  • v2 Enterprise confondue avec v3 Enterprise. La v2 affiche une case à cocher, la v3 reste invisible : les paramètres de la tâche diffèrent.
  • Script injecté après le chargement. Aucun fichier reCAPTCHA dans le HTML : passez par un navigateur headless.

Budget et capacité : ce que la version ne change pas

Cas concret : une équipe QA à Lyon valide chaque nuit un tunnel d'inscription hébergé chez OVHcloud, workers en eu-west-3 (Paris). Le staging est en reCAPTCHA v2 standard, la préproduction du partenaire en Enterprise. La facturation CaptchaAI se fait en dollars US et repose sur les threads — les résolutions simultanées — jamais sur le type de widget.

  • BASIC ($15/mois, 5 threads) suffit à des tests nocturnes.
  • STANDARD ($30/mois, 15 threads) couvre plusieurs environnements en parallèle.
  • ADVANCE ($90/mois, 50 threads) vise les exécutions continues.

Un défi occupe un thread puis le libère : dimensionnez sur le pic simultané, pas sur le total quotidien. Côté RGPD, ne consignez aucune donnée personnelle issue des formulaires testés.


FAQ

Le sitekey change-t-il quand un site passe en reCAPTCHA v2 Enterprise ?

Le plus souvent oui : la clé Enterprise vit dans un projet Google Cloud distinct. Relisez-la dans le DOM à chaque exécution.

Un token accepté par CaptchaAI est refusé par le site : que vérifier ?

Le paramètre enterprise d'abord : un token obtenu sans lui sur une page enterprise.js, ou l'inverse, échoue à la vérification serveur. Contrôlez ensuite le pageurl.

reCAPTCHA v2 Enterprise et reCAPTCHA v3 Enterprise, est-ce la même intégration ?

Non. La v2 Enterprise reste un défi visible ; la v3 Enterprise s'exécute sans interaction et renvoie un score lié à une action.

CaptchaAI prend-il en charge hCaptcha pour les sites qui ont migré ?

Non — hCaptcha n'est pas pris en charge, pas plus que FunCaptcha (Arkose Labs) ; GeeTest v4 est à venir. Sont couverts : reCAPTCHA v2 et v3, Cloudflare Turnstile et Challenge, GeeTest v3, les CAPTCHA image/texte, plus CaptchaFox (bêta), Friendly Captcha (bêta) et Lemin (bêta).


Guides associés

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