Un seul paramètre sépare les deux intégrations : enterprise=1. Si la page charge enterprise.js, vous l'ajoutez à votre requête vers l'API CaptchaAI ; si elle charge api.js?render=, vous l'omettez. Le reste est identique : même sitekey, même paramètre action, même polling sur res.php, même injection dans g-recaptcha-response.
La difficulté est ailleurs : les deux variantes sont invisibles, et rien ne les distingue à l'écran. Une équipe qui code en dur la mauvaise variante ne le découvre qu'au moment où le taux de réussite de son pipeline chute, sans erreur explicite.
Ce que le drapeau enterprise=1 change vraiment
Enterprise n'est pas une v4 : c'est le même score de risque (0,0 à 1,0) livré dans l'écosystème Google Cloud, avec codes de motif, seuils par action et Account Defender. Ces fonctions concernent le site qui vérifie le token, pas le client qui le produit.
Côté résolution, seuls trois éléments changent :
- le fichier JS chargé ;
- la fonction appelée (
grecaptcha.enterprise.execute()) ; - le drapeau
enterprise=1.
Différences entre reCAPTCHA v3 standard et Enterprise
Les chiffres ci-dessous reposent sur des mesures observées et des retours d'utilisateurs ; les résultats varient selon l'environnement, le volume et le moment de la journée.
| Caractéristique | v3 standard | v3 Enterprise |
|---|---|---|
| Fonctionnement invisible | Oui | Oui |
| Score (0,0 à 1,0) | Oui | Oui |
Paramètre action |
Obligatoire | Obligatoire |
| Fichier JS | api.js?render=KEY |
enterprise.js?render=KEY |
| Fonction d'exécution | grecaptcha.execute() |
grecaptcha.enterprise.execute() |
| Codes de motif | Non | Oui (AUTOMATION, TOO_MUCH_TRAFFIC…) |
| Seuils par action | Non | Oui (via Cloud Console) |
| Détection de fuite de mot de passe | Non | Oui |
| Account Defender | Non | Oui |
| Endpoint de vérification | siteverify (gratuit) |
recaptchaenterprise.googleapis.com (payant) |
| Paramètres CaptchaAI | version=v3 |
version=v3 + enterprise=1 |
| Temps de résolution typique | 10–20 s | 10–20 s |
Repérer la version chargée par une page
Sans widget visible, la détection passe par le HTML et le JavaScript de la page.
En Python :
import requests
import re
def detect_v3_type(url):
resp = requests.get(url)
html = resp.text
# Check for enterprise.js
if "enterprise.js" in html:
version = "enterprise_v3"
execute_fn = "grecaptcha.enterprise.execute"
elif "recaptcha/api.js" in html and "render=" in html:
version = "standard_v3"
execute_fn = "grecaptcha.execute"
else:
return None
# Extract sitekey from render parameter
key_match = re.search(r'render[=:]\s*["\']?([A-Za-z0-9_-]{40})', html)
sitekey = key_match.group(1) if key_match else None
# Extract action parameter
action_match = re.search(r'action["\']?\s*[:=]\s*["\'](\w+)', html)
action = action_match.group(1) if action_match else "unknown"
return {
"version": version,
"sitekey": sitekey,
"action": action,
"execute_fn": execute_fn
}
info = detect_v3_type("https://example.com/login")
print(info)
En Node.js :
const axios = require("axios");
async function detectV3Type(url) {
const { data: html } = await axios.get(url);
let version, executeFn;
if (html.includes("enterprise.js")) {
version = "enterprise_v3";
executeFn = "grecaptcha.enterprise.execute";
} else if (html.includes("recaptcha/api.js") && html.includes("render=")) {
version = "standard_v3";
executeFn = "grecaptcha.execute";
} else {
return null;
}
const keyMatch = html.match(/render[=:]\s*['"]?([A-Za-z0-9_-]{40})/);
const actionMatch = html.match(/action['"]?\s*[:=]\s*['"](\w+)/);
return {
version,
sitekey: keyMatch?.[1] || null,
action: actionMatch?.[1] || "unknown",
executeFn,
};
}
Contrôle rapide dans la console du navigateur :
// Paste in DevTools console
if (document.querySelector('script[src*="enterprise.js"]')) {
console.log("Enterprise v3");
console.log("Execute:", typeof grecaptcha?.enterprise?.execute);
} else if (document.querySelector('script[src*="api.js"][src*="render="]')) {
console.log("Standard v3");
console.log("Execute:", typeof grecaptcha?.execute);
}
Un réflexe utile : ne gardez pas le HTML complet des pages auditées dans vos logs. Il contient souvent des identifiants de session, et cette minimisation limite la collecte de données personnelles au regard du RGPD.
Résoudre les deux versions avec l'API CaptchaAI
v3 standard
Soumettez la tâche sur in.php avec method=userrecaptcha, version=v3, la sitekey et l'action, puis interrogez res.php.
import requests
import time
# Submit
resp = requests.get("https://ocr.captchaai.com/in.php", params={
"key": "YOUR_API_KEY",
"method": "userrecaptcha",
"version": "v3",
"googlekey": sitekey,
"action": "login",
"pageurl": page_url
})
task_id = resp.text.split("|")[1]
# Poll
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
v3 Enterprise
Même requête, plus enterprise=1. L'interrogation du résultat est strictement identique : inutile de dupliquer votre couche de polling.
import requests
import time
# Submit — add enterprise=1
resp = requests.get("https://ocr.captchaai.com/in.php", params={
"key": "YOUR_API_KEY",
"method": "userrecaptcha",
"version": "v3",
"enterprise": 1, # Required for Enterprise
"googlekey": sitekey,
"action": "login",
"pageurl": page_url
})
task_id = resp.text.split("|")[1]
# Polling is identical to standard
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
Détection et résolution dans une seule classe
En production, la détection ne doit pas rester manuelle. Cette classe lit la page, choisit la variante, extrait la sitekey et l'action, puis résout : une migration vers Enterprise devient transparente.
import requests
import time
import re
class RecaptchaV3Solver:
def __init__(self, api_key):
self.api_key = api_key
def detect_and_solve(self, page_url, action=None):
"""Auto-detect standard vs enterprise and solve."""
html = requests.get(page_url).text
is_enterprise = "enterprise.js" in html
key_match = re.search(r'render[=:]\s*["\']?([A-Za-z0-9_-]{40})', html)
if not key_match:
raise Exception("No v3 sitekey found")
sitekey = key_match.group(1)
if not action:
action_match = re.search(r'action["\']?\s*[:=]\s*["\'](\w+)', html)
action = action_match.group(1) if action_match else "verify"
params = {
"key": self.api_key,
"method": "userrecaptcha",
"version": "v3",
"googlekey": sitekey,
"action": action,
"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 result.text.split("|")[1]
if result.text != "CAPCHA_NOT_READY":
raise Exception(f"Solve failed: {result.text}")
raise Exception("Timed out")
solver = RecaptchaV3Solver("YOUR_API_KEY")
token = solver.detect_and_solve("https://example.com/login", action="login")
print(f"Token: {token[:40]}...")
Extraire le paramètre action avant de soumettre
L'action pèse directement sur le score. Une valeur devinée (verify sur un formulaire qui déclare login) produit un score bas et un token refusé, sans erreur côté API. Extrayez la chaîne exacte du JavaScript.
import re
def find_v3_actions(html):
"""Extract all action parameters from page JavaScript."""
# Look for grecaptcha.execute(key, {action: '...'})
pattern = r"(?:grecaptcha\.(?:enterprise\.)?execute|action)\s*[(:]\s*['\"](\w+)"
actions = re.findall(pattern, html)
return list(set(actions))
# Common actions: "login", "submit", "register", "checkout", "homepage"
Erreurs de paramétrage qui font rejeter un token
| Erreur | Résultat | Correctif |
|---|---|---|
enterprise=1 envoyé sur du v3 standard |
Token potentiellement invalide | Vérifier enterprise.js avant d'ajouter le drapeau |
enterprise=1 oublié sur du v3 Enterprise |
Token rejeté par le backend | L'ajouter dès que enterprise.js est présent |
Mauvais paramètre action |
Score bas, token rejeté | Extraire la chaîne exacte du JavaScript de la page |
version=v3 omis |
Tâche traitée comme du v2 | Toujours envoyer version=v3 pour le reCAPTCHA à score |
| Sitekey v2 utilisée en v3 | ERROR_WRONG_GOOGLEKEY |
Les sitekeys v3 viennent de render=KEY |
Injecter le token dans le formulaire
L'injection ne dépend pas de la variante : le champ cible reste g-recaptcha-response.
# For browser-based workflows (Selenium)
driver.execute_script(
f'document.getElementById("g-recaptcha-response").value = "{token}";'
)
# For pure HTTP workflows
requests.post(page_url, data={
"g-recaptcha-response": token,
"username": "user",
"password": "pass"
})
// Puppeteer
await page.evaluate((tok) => {
document.getElementById("g-recaptcha-response").value = tok;
}, token);
// Pure HTTP (axios)
await axios.post(pageUrl, new URLSearchParams({
"g-recaptcha-response": token,
username: "user",
password: "pass",
}));
Volume, threads et budget
CaptchaAI facture des threads simultanés, pas des résolutions : un thread est une résolution en vol, avec des résolutions illimitées par thread. Le v3 Enterprise ne coûte donc pas plus cher que le standard ; c'est votre parallélisme qui détermine le plan.
Exemple : une équipe QA française lance chaque nuit une campagne Playwright depuis une instance Scaleway à Paris, avec 8 parcours de connexion en parallèle sur une recette protégée par v3 Enterprise. Ces 8 résolutions simultanées tiennent dans STANDARD ($30/mois, 15 threads) ; à 40 scénarios parallèles, ADVANCE ($90/mois, 50 threads) absorbe la charge sans changer une ligne de code. Le plan d'entrée reste BASIC ($15/mois, 5 threads).
FAQ
Faut-il un compte Google Cloud pour résoudre du reCAPTCHA v3 Enterprise ?
Non. Le projet Google Cloud et l'endpoint recaptchaenterprise.googleapis.com concernent le site qui vérifie le token ; côté client, la sitekey publique, l'action et votre clé API suffisent à résoudre.
Comment détecter Enterprise v3 par programmation ?
Cherchez enterprise.js dans la source de la page ; avec un navigateur piloté, la source complète suffit :
page_source = driver.page_source
is_enterprise = "enterprise.js" in page_source
Le token est accepté mais le score reste bas : que vérifier ?
L'action d'abord : elle doit correspondre exactement à celle déclarée par la page. Vérifiez ensuite la cohérence de la session : même IP, mêmes en-têtes, même enchaînement jusqu'à l'envoi du formulaire.
CaptchaAI prend-il en charge hCaptcha si le site bascule ?
Non — hCaptcha n'est pas pris en charge, pas plus que FunCaptcha (Arkose Labs) : un site qui bascule sort du périmètre couvert. GeeTest v4 est à venir ; GeeTest v3, Cloudflare Turnstile et Cloudflare Challenge sont pris en charge.
Combien de threads prévoir pour une campagne nocturne ?
Comptez un thread par résolution simultanée, jamais par test. Si la file d'attente s'allonge, augmentez les threads.