Ihre Node.js-Integration läuft seit Monaten stabil gegen reCAPTCHA v2 – und dann liefert ausgerechnet die Login-Seite eines Kunden nur noch abgelehnte Tokens zurück. Meist liegt das nicht am Code, sondern an der Variante: Die Seite setzt reCAPTCHA v2 Enterprise ein. Die Antwort darauf ist ein einziger zusätzlicher Parameter – enterprise=1 in derselben userrecaptcha-Anfrage, die Sie ohnehin schon senden.
Alles andere bleibt vertraut: Sie übergeben Sitekey und Page-URL an CaptchaAI, fragen das Ergebnis ab und schreiben das gelöste Token in das Feld g-recaptcha-response. Dieser Leitfaden zeigt den vollständigen Ablauf in Node.js – vom Auslesen des Sitekeys in den DevTools über Übermittlung und Polling bis zum abgesendeten Formular, inklusive der Fehlercodes, die dabei am häufigsten auftreten.
Kurzfassung: Gleicher Endpunkt, gleiche Methode – zusätzlich
enterprise=1und, falls vorhanden,action.
Enterprise v2 und Standard v2 im direkten Vergleich
| Merkmal | reCAPTCHA v2 | reCAPTCHA v2 Enterprise |
|---|---|---|
| Widget | Kontrollkästchen „Ich bin kein Roboter“ | optisch identisch |
| Skript- und Anker-Pfad | /recaptcha/api2/ |
/recaptcha/enterprise/ |
| Sitekey | Parameter k= |
Parameter k= |
| Aktion | nicht vorhanden | Parameter sa=, falls gesetzt |
| CaptchaAI-Methode | userrecaptcha |
userrecaptcha plus enterprise=1 |
| Feld im Formular | g-recaptcha-response |
g-recaptcha-response |
Der praktisch wichtigste Unterschied liegt hinter den Kulissen: Enterprise-Tokens werden über das Enterprise-Backend von Google mit strengerer Prüfung validiert und sind an den User-Agent gebunden, mit dem gelöst wurde. Wer diesen Wert ignoriert, bekommt ein technisch gültiges Token, das die Zielseite trotzdem verwirft.
Voraussetzungen für die Integration
- CaptchaAI-API-Schlüssel – 32 Zeichen, abrufbar im Dashboard unter captchaai.com
- Node.js 14 oder neuer – mit eingebautem
fetchoder mitnode-fetch - Sitekey – der Wert des Parameters
k=aus der Enterprise-Anker-URL - Page-URL – die vollständige Adresse der Seite, auf der das CAPTCHA erscheint
- Aktion (optional) – der Wert des Parameters
sa=, sofern die Anker-URL ihn enthält
Schritt 1: Enterprise v2 in den DevTools erkennen
Rufen Sie die Zielseite auf, wechseln Sie in den DevTools in den Netzwerk-Tab und filtern Sie nach anchor. Eine Enterprise-Integration zeigt eine Anfrage dieser Form:
https://www.google.com/recaptcha/enterprise/anchor?ar=1&k=6LdxxXXxAAAAAAcX...&sa=LOGIN&...
Daran erkennen Sie die Variante eindeutig:
- Der Pfad enthält
/recaptcha/enterprise.jsoder/enterprise/anchorstatt/recaptcha/api2/ k=liefert den Sitekey, den CaptchaAI alsgooglekeyerwartetsa=liefert die Aktion – im Beispiel obenLOGIN
Prüfen Sie das vor jeder Integration: enterprise=1 gehört ausschließlich zu Enterprise-Seiten. Bei Standard v2 lassen Sie den Parameter weg.
Schritt 2: Die Aufgabe an CaptchaAI übermitteln
Die Übermittlung geht an in.php. Pflichtfelder sind key, method, googlekey und pageurl; enterprise=1 markiert die Variante, json=1 liefert eine auswertbare JSON-Antwort statt einer Klartextzeile. Die Aktion setzen Sie nur, wenn die Anker-URL sie mitliefert:
const API_KEY = "YOUR_API_KEY";
async function submitTask(sitekey, pageurl, action) {
const params = new URLSearchParams({
key: API_KEY,
method: "userrecaptcha",
googlekey: sitekey,
pageurl: pageurl,
enterprise: "1",
json: "1",
});
if (action) {
params.set("action", action);
}
const response = await fetch(
`https://ocr.captchaai.com/in.php?${params}`
);
const data = await response.json();
if (data.status !== 1) {
throw new Error(`Submit failed: ${data.request}`);
}
console.log(`Task submitted. ID: ${data.request}`);
return data.request;
}
Bei status: 1 enthält das Feld request die Task-ID. Mit ihr fragen Sie im nächsten Schritt das Ergebnis ab.
Schritt 3: Das Ergebnis abfragen
Enterprise-Abfragen brauchen Zeit: CaptchaAI nennt für reCAPTCHA v2 Enterprise eine Lösungszeit von unter 60 Sekunden. Fragen Sie deshalb nicht sofort ab, sondern warten Sie 20 Sekunden und fragen Sie danach im 5-Sekunden-Takt nach. CAPCHA_NOT_READY heißt „läuft noch“; jede andere Antwort ist ein echter Fehler und sollte die Schleife sofort beenden:
function delay(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function pollResult(taskId) {
await delay(20000);
for (let attempt = 0; attempt < 30; attempt++) {
const params = new URLSearchParams({
key: API_KEY,
action: "get",
id: taskId,
json: "1",
});
const response = await fetch(
`https://ocr.captchaai.com/res.php?${params}`
);
const data = await response.json();
if (data.status === 1) {
console.log(`Solved. Token: ${data.request.substring(0, 60)}...`);
return {
token: data.request,
userAgent: data.user_agent || "",
};
}
if (data.request !== "CAPCHA_NOT_READY") {
throw new Error(`Solve failed: ${data.request}`);
}
console.log(`Attempt ${attempt + 1}: not ready, waiting 5s...`);
await delay(5000);
}
throw new Error("Solve timed out");
}
Speichern Sie neben dem Token unbedingt den Wert user_agent aus der Antwort – im nächsten Schritt entscheidet er darüber, ob die Zielseite das Token akzeptiert.
Schritt 4: Das Token in das Formular einfügen
Das gelöste Token gehört in das Feld g-recaptcha-response, genau wie bei Standard v2. Hat die API einen user_agent zurückgegeben, senden Sie die Anfrage mit exakt diesem Header, damit Token und Client zusammenpassen:
async function submitForm(token, userAgent) {
const headers = { "Content-Type": "application/x-www-form-urlencoded" };
if (userAgent) {
headers["User-Agent"] = userAgent;
}
const response = await fetch("https://example.com/api/login", {
method: "POST",
headers,
body: new URLSearchParams({
username: "user",
password: "pass",
"g-recaptcha-response": token,
}),
});
console.log(`Response status: ${response.status}`);
return response;
}
Tokens sind kurzlebig – nach rund 120 Sekunden verfallen sie. Lösen Sie das CAPTCHA deshalb direkt vor dem Absenden des Formulars und nicht auf Vorrat.
Das vollständige Skript
Zusammengesetzt ergeben die vier Schritte ein eigenständiges Skript, das Sie mit node solve.js starten können:
const API_KEY = "YOUR_API_KEY";
const SITE_KEY = "6LdxxXXxAAAAAAcXxxXxxX91xxxxxxxx8xxOx7A";
const PAGE_URL = "https://example.com/login";
const ACTION = "LOGIN"; // optional — omit if not in anchor URL
function delay(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function solveRecaptchaV2Enterprise() {
// Submit task
const submitParams = new URLSearchParams({
key: API_KEY,
method: "userrecaptcha",
googlekey: SITE_KEY,
pageurl: PAGE_URL,
enterprise: "1",
action: ACTION,
json: "1",
});
const submitRes = await fetch(
`https://ocr.captchaai.com/in.php?${submitParams}`
);
const submitData = await submitRes.json();
if (submitData.status !== 1) {
throw new Error(`Submit error: ${submitData.request}`);
}
const taskId = submitData.request;
console.log(`Task ID: ${taskId}`);
// Poll for result
await delay(20000);
for (let i = 0; i < 30; i++) {
const pollParams = new URLSearchParams({
key: API_KEY,
action: "get",
id: taskId,
json: "1",
});
const pollRes = await fetch(
`https://ocr.captchaai.com/res.php?${pollParams}`
);
const pollData = await pollRes.json();
if (pollData.status === 1) {
return {
token: pollData.request,
userAgent: pollData.user_agent || "",
};
}
if (pollData.request !== "CAPCHA_NOT_READY") {
throw new Error(`Solve error: ${pollData.request}`);
}
await delay(5000);
}
throw new Error("Solve timed out");
}
(async () => {
const { token, userAgent } = await solveRecaptchaV2Enterprise();
console.log(`Token: ${token.substring(0, 60)}...`);
if (userAgent) console.log(`User-Agent: ${userAgent}`);
})();
Erwartete Ausgabe:
Task ID: 73849562810
Token: 03AGdBq24PBCqLmOx2V4pGHJjkR2xZ1r...
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)...
Fehlercodes und ihre Ursachen
| Fehler | Ursache | Lösung |
|---|---|---|
ERROR_WRONG_USER_KEY |
Format des API-Schlüssels ungültig | Die 32 Zeichen aus dem Dashboard exakt übernehmen |
ERROR_KEY_DOES_NOT_EXIST |
Schlüssel unbekannt | Schlüssel im Dashboard erneut kopieren |
ERROR_ZERO_BALANCE |
Guthaben aufgebraucht | Konto aufladen |
ERROR_BAD_TOKEN_OR_PAGEURL |
Sitekey und Page-URL passen nicht zusammen | k=-Wert erneut aus der Anker-URL übernehmen |
ERROR_CAPTCHA_UNSOLVABLE |
Aufgabe nicht lösbar | Prüfen, ob wirklich Enterprise v2 vorliegt, dann erneut senden |
| Token wird von der Seite verworfen | User-Agent weicht ab | user_agent aus der Antwort als Request-Header setzen |
Durchsatz planen: Threads statt Abrechnung pro Lösung
Ein typisches Szenario aus der DACH-Praxis: Ein Entwicklungsteam fährt seine End-to-End-Tests nachts in der GitLab CI auf einem Hetzner-Server. 40 Login-Szenarien laufen parallel gegen die eigene Staging-Umgebung, jedes davon trifft auf ein Enterprise-v2-Widget. Entscheidend ist dabei nicht die Gesamtzahl der Lösungen, sondern die Gleichzeitigkeit.
CaptchaAI rechnet Thread-basiert ab, nicht pro Lösung: Ein Thread ist ein CAPTCHA, das gerade in Bearbeitung ist, und jeder Tarif enthält unbegrenzt viele Lösungen pro Thread. Für einen einzelnen Nightly-Job genügt BASIC (15 $/Monat, 5 Threads); die 40 parallelen Tests aus dem Beispiel brauchen deutlich mehr Gleichzeitigkeit, etwa ADVANCE (90 $/Monat, 50 Threads). Bei einer Lösungszeit von unter 60 Sekunden verarbeitet ein Thread rechnerisch rund 60 Enterprise-Abfragen pro Stunde – der Durchsatz wächst also mit der Zahl der Threads, nicht mit einem Kontingent.
Hinweis: Alle genannten Preise sind US-Dollar-Beträge, nicht in Euro umgerechnet.
Häufige Fragen
Reicht enterprise=1 wirklich, oder brauche ich einen anderen Endpunkt?
Der Endpunkt bleibt derselbe. Sie übermitteln an in.php, holen das Ergebnis von res.php und verwenden weiterhin die Methode userrecaptcha. Enterprise unterscheidet sich nur durch enterprise=1 und – falls in der Anker-URL vorhanden – den Parameter action.
Wie lange ist ein gelöstes Enterprise-Token gültig?
Rund zwei Minuten. Danach verfällt es und die Zielseite weist es ab. Planen Sie den Lösungsaufruf deshalb als letzten Schritt vor dem Absenden ein; ein Vorrat gelöster Tokens bringt nichts.
Kann ich mehrere Enterprise-CAPTCHAs gleichzeitig lösen?
Ja. Die Zahl der gleichzeitig laufenden Lösungen entspricht der Zahl Ihrer Threads: Sobald eine Aufgabe fertig ist, nimmt derselbe Thread die nächste. In Node.js bilden Sie das mit Promise.all über einen begrenzten Stapel paralleler Aufrufe ab – die Stapelgröße richtet sich nach Ihrer Thread-Anzahl, damit keine Anfrage unnötig wartet.
Funktioniert der Ablauf auch mit Puppeteer oder Playwright?
Ja. Lesen Sie den Sitekey aus dem DOM, lösen Sie ihn über die API und schreiben Sie das Token per page.evaluate() in document.getElementById('g-recaptcha-response').innerHTML. Den zurückgegebenen user_agent setzen Sie beim Start des Browser-Kontexts, damit Token und Browser zusammenpassen.
Welche Daten verlassen dabei mein System?
Für die Lösung übermittelt Ihr Skript den Sitekey, die Page-URL und optional die Aktion – keine Formularinhalte und keine Zugangsdaten. Wer in der EU entwickelt, sollte die eigenen Datenflüsse trotzdem dokumentieren: Sobald im selben Workflow IP-Adressen oder Nutzerdaten verarbeitet werden, gelten dafür die üblichen DSGVO-Pflichten Ihrer Anwendung.
Jetzt mit CaptchaAI starten
Holen Sie sich Ihren API-Schlüssel auf captchaai.com, ergänzen Sie Ihre bestehende v2-Integration um enterprise=1 und lassen Sie den ersten Enterprise-Login-Test gegen Ihre Staging-Umgebung laufen.