So lösen Sie hCaptcha Enterprise in Node.js (capskip-SDK)

Um hCaptcha Enterprise in Node.js zu lösen, holen Sie sich von der Website einen neuen rqdata-Wert und übergeben ihn der Methode hcaptcha() des Pakets capskip als Option data, zusammen mit dem sitekey und der Seiten-URL. Die Methode sendet die Aufgabe an CapSkip, fragt ab, bis der Token bereit ist, und gibt ihn zurück. Senden Sie den Token dann mit dem User-Agent aus dem Ergebnis an das Formular. Laut CapSkip-Dokumentation stellt die Website jeden rqdata-Wert für eine Challenge aus, und er läuft schnell ab, daher braucht jede Aufgabe und jede Wiederholung einen frischen. Der folgende Code spricht mit dem CapSkip-hCaptcha-Löser auf Ihrem eigenen Windows-PC, ohne Gebühr pro Lösung.
Was Sie brauchen
- CapSkip in Version 4.0.0 oder höher, installiert auf Ihrem Windows-Rechner. Diese Version brachte das Lösen von hCaptcha, Enterprise eingeschlossen, im hier genutzten Format in.php und im JSON-Format createTask.
- Node.js 18 oder neuer und das Paket capskip in Version 1.6.0 oder höher, der ersten mit einer Methode hcaptcha. Das Paket deklariert Node.js 18 als Untergrenze und hat keine eigenen Abhängigkeiten, und der Formular-POST nutzt das eingebaute fetch. Ich habe den Code nur mit 20.11.1, 24.22.0 und 25.2.1 ausgeführt.
- Eine Website, die Ihnen gehört oder die Sie automatisieren dürfen und die ein hCaptcha-Widget zeigt, und der sitekey dieses Widgets.
- Ein Weg vom Skript zu CapSkip. Der Local-Modus hält CapSkip auf 127.0.0.1, erreichbar von diesem einen Gerät. Der Server-Modus lässt es zusätzlich auf Ihrer Netzwerkadresse oder öffentlichen IP lauschen, sodass auch ein Skript auf einem Windows-VPS, einem anderen PC oder einer gehosteten Plattform es nutzen kann, und er verlangt, dass CapSkip als Administrator läuft. Den Modus wählen Sie in den Verbindungseinstellungen.
Stand der Dinge: Ich habe den Code mit capskip 1.6.0 gegen zwei eigene Mock-Server ausgeführt, einen als Ersatz für CapSkip und einen für eine Enterprise-Website, die jeden rqdata-Wert nur einmal annimmt. Diese Regeln stammen von mir und sind aus der CapSkip-Dokumentation und dem Paketquelltext übernommen. Keine der öffentlichen hCaptcha-Dokumentationsseiten, die ich gelesen habe, beschreibt rqdata, daher stammt jede Tatsache zu rqdata hier aus der CapSkip-Dokumentation. Es fand keine echte Lösung statt, daher kann ich nicht sagen, wie lange eine dauert oder wie sich eine echte Enterprise-Website verhält.
Schritt 1: Den sitekey, das Invisible-Flag und rqdata finden
Führen Sie in einem leeren Ordner npm install capskip aus. Kopieren Sie dann die Blöcke der Schritte 1 bis 4 in der gezeigten Reihenfolge in eine Datei namens hcaptcha-demo.js in diesem Ordner. Bis Schritt 4 läuft nichts, es sei denn, Sie fügen am Ende von Schritt 2 die Testzeile hinzu. Die Option recaptchaTimeout ist das Abfragelimit des SDK für hCaptcha in Sekunden. Der Standardwert ist 300, und die kürzeren 120 habe ich selbst gewählt.
// npm install capskip
const { CapSkip, ApiException } = require("capskip");
const CAPSKIP = { host: "127.0.0.1", port: 8080 }; // Local mode; Server mode: your server
const SITE = "https://www.example.com"; // a site you may automate
const PAGE_URL = `${SITE}/login`; // the page the hCaptcha widget is on
// The SDK's default key. Use your own if API Key Validation is on in CapSkip.
const API_KEY = "capskip";
const PROXY = null; // for example "203.0.113.10:8080"; null means no proxy
const solver = new CapSkip({
...CAPSKIP,
apiKey: API_KEY,
recaptchaTimeout: 120, // poll limit in seconds for hCaptcha; the default is 300
});Der sitekey sitzt meist am Widget-Container als data-sitekey. Baut ein Skript das Widget, suchen Sie nach der Option sitekey von hcaptcha.render() oder nach dem Parameter sitekey= in der Adresse des hCaptcha-iframe. Der Leitfaden zum unsichtbaren hCaptcha-Widget kennzeichnet ein unsichtbares Widget mit data-size auf invisible, und laut CapSkip-Dokumentation senden Sie für ein solches Widget invisible=1.
Der rqdata-Wert ist der ungewöhnliche. Laut CapSkip-Dokumentation übergeben manche Enterprise-Websites vor dem Start einen rqdata-Wert über hcaptcha.setData() an das Widget, und wenn die Seite das tut, senden Sie den Wert als data. Tut sie es nicht, senden Sie kein Feld data. Woher der Wert kommt, entscheidet die Website. Er kann im HTML der Seite stehen oder von einer Anfrage zurückkommen, die die Seite macht, durchsuchen Sie daher die Skripte der Seite nach dem Aufruf, der ihn setzt, und verfolgen Sie die Zeichenfolge. Ich habe das an keiner echten Enterprise-Website ausprobiert, und die Funktion unten nutzt den Weg, den mein Mock bereitstellt.
// Ask the site for a new challenge. The route and the field names are the
// site's choice; these are the ones in my test mock, so adapt them.
// If the sitekey is fixed in the page, return it as a constant here.
// If the site puts the values in the page HTML, fetch PAGE_URL and
// extract them here instead.
async function getChallenge() {
const resp = await fetch(`${SITE}/api/challenge`);
if (!resp.ok) throw new Error(`challenge failed: HTTP ${resp.status}`);
const { sitekey, rqdata, invisible } = await resp.json();
return { sitekey, rqdata, invisible: Boolean(invisible) };
}Schritt 2: Die Aufgabe senden und den Token abholen
Ein Aufruf sendet die Aufgabe und fragt das Ergebnis ab. Die Methode hcaptcha() nimmt den sitekey, die Seiten-URL und ein Options-Objekt: data ist der rqdata-Wert, invisible ist true für ein unsichtbares Widget, und proxy ist der Proxy für die Lösung. Das SDK sendet sie als Formularfelder mit method=hcaptcha an /in.php und sendet invisible als 1. Es sendet keine Option userAgent: Laut Dokumentation nutzt CapSkip diese Option nur, wenn sie zu dem Browser passt, mit dem es löst, und das Ergebnis trägt den User-Agent, mit dem der Token ausgestellt wurde.
async function solve({ sitekey, rqdata, invisible }) {
const options = {};
// The Enterprise rqdata, fresh for this task. Skip it if the site has none.
if (rqdata) options.data = rqdata;
if (invisible) options.invisible = true; // data-size is invisible
if (PROXY) options.proxy = PROXY;
// Submits the task, polls until the token is ready, and returns the result.
return solver.hcaptcha(sitekey, PAGE_URL, options);
}Das SDK fragt /res.php für Sie ab. Die erste Abfrage geht sofort hinaus, und die Wartezeiten danach beginnen bei einer Viertelsekunde, verdoppeln sich jedes Mal und wachsen nicht über 5 Sekunden hinaus. Ein leerer Body gilt als noch nicht bereit: Laut Dokumentation bedeutet er, dass das Ergebnis schon gelesen wurde oder die ID nicht existiert, und der SDK-Quelltext ergänzt, dass CapSkip gleich nach dem Senden einen schickt. Wenn das Limit verstrichen ist, wirft der Aufruf eine TimeoutException.
Ein Ergebnis wird einmal geliefert, und das SDK behält alles davon für Sie. Die Felder code und token enthalten denselben String. Der respKey ist der zweite Wert, den hCaptcha dem Widget mit dem Token übergibt. Laut Dokumentation lesen die meisten Websites ihn nie, und das SDK setzt ihn auf einen leeren String, wenn CapSkip keinen sendet. Lesen Sie userAgent für den User-Agent, mit dem der Token ausgestellt wurde.
Um die Schritte 1 und 2 für sich auszuprobieren, fügen Sie getChallenge().then(solve).then(console.log) als letzte Zeile hinzu und führen node hcaptcha-demo.js aus. Sie sollten ein Objekt mit captchaId, code, userAgent, respKey und token sehen. Löschen Sie diese Zeile wieder, bevor Sie den nächsten Block hinzufügen.
Schritt 3: Den Token an das Formular übergeben
Ein Browser-Widget füllt von selbst zwei versteckte Textarea-Felder, h-captcha-response und eine Spiegelung namens g-recaptcha-response. Ein Skript hat kein Widget und sendet sie daher als Formularfelder. Laut CapSkip-Dokumentation heißt das: immer h-captcha-response, g-recaptcha-response, wenn das Formular auch dieses Feld hat, und der User-Agent aus der Antwort. Das Formular unten ist ein Platzhalter, weil Ihre Website eigene Felder und einen eigenen Weg hat.
Tokens sind nur einmal verwendbar, und laut CapSkip-Dokumentation laufen sie etwa zwei Minuten nach der Ausstellung ab. Die eigene Dokumentation von hCaptcha nennt 120 Sekunden als Standard für den Fehler expired-input-response. Lösen Sie also nicht im Voraus und halten Sie keinen Vorrat an Tokens. Lösen Sie, dann senden Sie, bei jedem Absenden eines Formulars.
async function postForm(solved) {
const form = new URLSearchParams({
username: "demo", // the form's own fields
"h-captcha-response": solved.token,
// delete the next line if the form has no g-recaptcha-response field
"g-recaptcha-response": solved.token,
});
// Send the User-Agent the reply names, not Node's default one.
return fetch(PAGE_URL, {
method: "POST",
headers: { "User-Agent": solved.userAgent },
body: form,
});
}Schritt 4: Das vollständige Beispiel mit einem frischen rqdata-Wert pro Versuch
Der letzte Block verdrahtet alles zu einer Wiederholungsschleife. Hängen Sie ihn an hcaptcha-demo.js an und starten Sie ihn mit node hcaptcha-demo.js. Jeder Versuch ruft zuerst getChallenge auf, daher trägt jede Aufgabe einen rqdata-Wert, der vor wenigen Augenblicken ausgestellt wurde. Die Schleife wiederholt nur ERROR_CAPTCHA_UNSOLVABLE, den Code für eine Aufgabe, die nicht gelöst werden konnte. Die CapSkip-Dokumentation nennt zwei Fehler, die sich bei einem erneuten Senden wiederholen würden: ERROR_RECAPTCHA_INVALID_SITEKEY bei einer Abfrage, was bedeutet, dass hCaptcha den sitekey für diese Seite abgelehnt hat, und ERROR_PROXY_CONNECT_REFUSED. Die Schleife wirft diese und jeden anderen Fehler unverändert erneut.
Die Schleife läuft auch erneut, wenn die Website außerhalb von 200 bis 299 antwortet, weil ein abgelehnter Token einen veralteten rqdata-Wert bedeuten kann. Eine 403 kann andere Ursachen haben, etwa ein falsches Passwort in einem Anmeldeformular, daher enden die Versuche bei drei.
// ERROR_CAPTCHA_UNSOLVABLE is the one failure where a new task can help.
async function login() {
for (let attempt = 1; attempt <= 3; attempt += 1) {
const challenge = await getChallenge(); // a new rqdata for every attempt
try {
const solved = await solve(challenge);
const resp = await postForm(solved);
if (resp.ok) return resp;
console.log(`attempt ${attempt}: the site answered HTTP ${resp.status}`);
} catch (err) {
// The message is the text of the app's reply: a bare code or small JSON.
const unsolvable = err instanceof ApiException
&& err.message.includes("ERROR_CAPTCHA_UNSOLVABLE");
if (!unsolvable) throw err;
console.log(`attempt ${attempt}: ERROR_CAPTCHA_UNSOLVABLE`);
}
}
throw new Error("hCaptcha not passed in 3 attempts");
}
login()
.then(async (resp) => console.log(resp.status, await resp.text()))
.catch((err) => {
console.error(`${err.name}: ${err.message}`);
if (err.cause) console.error(err.cause.code); // for example ECONNREFUSED
process.exitCode = 1;
});Das SDK bringt drei eigene Fehler mit. Eine ValidationException bedeutet, dass es den Aufruf ablehnte, bevor es etwas sendete: ein leerer sitekey, eine Seiten-URL, die kein absolutes http oder https ist, ein ungültiger invisible-Wert oder eine Option, die die hCaptcha-API von CapSkip nicht annimmt, etwa domain von 2Captcha. Eine NetworkException beim Senden bedeutet, dass an der Adresse von CapSkip nichts antwortete, und eine TimeoutException bedeutet, dass das Abfragelimit verstrichen ist. Eine neue Aufgabe ändert an keinem davon etwas, daher wirft die Schleife sie erneut. Die Meldung der ApiException enthält die Antwort der App als Text, daher gleicht die Schleife sie mit includes() ab.
So verhielt sich das Skript gegen die Mocks, mit capskip 1.6.0 unter Node.js 24.22.0. Node.js 20.11.1 und 25.2.1 beendeten jeden Fall gleich, mit denselben Exit-Codes. Das Testgerüst änderte nur die Adressen und, in den Timeout-Zeilen, das Abfragelimit.
| Mock-Einstellung | Was das Skript tat |
|---|---|
| Enterprise-Website; Mock nach der dritten Abfrage bereit, oder 20 Sekunden nach dem Senden | Jeweils eine Aufgabe und Status 200. Die Abfragen kamen im ersten Fall bei etwa 0; 0,3 und 0,8 Sekunden. Im zweiten kamen sie bei etwa 0; 0,3; 0,8; 1,8; 3,8; 7,8; 12,8; 17,8 und 22,8 Sekunden auf allen drei Runtimes, der Token erreichte das Skript also 2,8 Sekunden, nachdem er bereit war |
| Unsichtbare Website; Website, die keinen rqdata-Wert ausgibt | in.php erhielt im ersten Fall invisible=1 und im zweiten kein Feld data, und beide Formular-POSTs kamen durch |
| ERROR_CAPTCHA_UNSOLVABLE zweimal in einem Lauf, dreimal in einem anderen | Zwei Fehlschläge: Status 200 bei der dritten Aufgabe, mit drei verschiedenen rqdata-Werten. Drei Fehlschläge: der Error “hCaptcha not passed in 3 attempts” und Exit-Code 1 |
| Die Mock-Website lehnt den ersten Token ab | “attempt 1: the site answered HTTP 403”, dann eine zweite Aufgabe mit einem neuen rqdata-Wert und Status 200 |
| Zwischengespeicherte Challenge für einen zweiten Login wiederverwendet (der erste ging durch); Feld data weggelassen; Formular ohne den User-Agent der Antwort gesendet | Jeder dieser Versuche bekam vom Mock eine 403, und jeder Lauf endete im Error “hCaptcha not passed in 3 attempts”. Das sind die Regeln meines Mocks, nicht die einer echten Website |
| Leerer sitekey, ftp als pageurl, invisible auf das Wort maybe gesetzt, die Option domain; ein Proxy-String, der kein Proxy ist, ein Schlüssel, den CapSkip nicht kennt, Aufgabentyp abgelehnt | ValidationException in den ersten vier Fällen, ohne dass eine Aufgabe an in.php gesendet wurde. ApiException mit ERROR_PROXY_FORMAT, ERROR_KEY_DOES_NOT_EXIST und ERROR_TASK_NOT_SUPPORTED in den anderen, jeweils nach einer Aufgabe. Jedes Mal Exit-Code 1 |
| Abfragen, die mit ERROR_PROXY_CONNECT_REFUSED oder ERROR_RECAPTCHA_INVALID_SITEKEY antworten | Nur eine Aufgabe. Das Skript stoppte beim ersten Fehler |
| Proxy 203.0.113.10:8080 oder user:[email protected]:8080; Mock nie bereit (Limit auf 1,5 Sekunden gekürzt); kein Prozess an der CapSkip-Adresse | in.php erhielt den Proxy-String unverändert, mit proxytype HTTP, und der Lauf war erfolgreich; TimeoutException: timeout 1.5 exceeded; NetworkException: connect ECONNREFUSED, dann ECONNREFUSED in der nächsten Zeile, und keine Aufgabe |
| Mock nie bereit, mit dem Limit von 120 Sekunden; Mock-Prozess endet während einer Lösung (Limit auf 4 Sekunden gekürzt) | Die letzte Abfrage kam bei 118 Sekunden und die TimeoutException bei etwa 123. Nachdem der Mock gestorben war, fragte das SDK weiter ab und endete mit einer TimeoutException, nicht mit einem Verbindungsfehler |
Häufige Fehler
| Fehler | Ursache | Beheben |
|---|---|---|
| ApiException mit ERROR_WRONG_USER_KEY oder ERROR_KEY_DOES_NOT_EXIST | API Key Validation ist in CapSkip eingeschaltet, und API_KEY gehört nicht zu seinen Schlüsseln. | Setzen Sie API_KEY auf einen Schlüssel aus CapSkip. |
| ApiException mit ERROR_TASK_NOT_SUPPORTED | CapSkip lehnt den Aufgabentyp ab. Eine Version vor 4.0.0 ist eine Ursache | Aktualisieren Sie auf 4.0.0 oder neuer |
| ApiException mit ERROR_RECAPTCHA_INVALID_SITEKEY | hCaptcha hat den sitekey für diese Seite abgelehnt. Ein leerer sitekey kommt nie so weit, weil das SDK ihn vorher ablehnt | Prüfen Sie sitekey und pageurl anhand der Seite |
| ValidationException | Das SDK lehnte den Aufruf ab, bevor es etwas sendete, und seine Meldung nennt das Problem | Korrigieren Sie den Aufruf |
| ApiException mit ERROR_PROXY_FORMAT | Der Proxy-String hat ein Format, das CapSkip nicht akzeptiert | Verwenden Sie IP:PORT, LOGIN:PASSWORD@IP:PORT oder IP:PORT:LOGIN:PASSWORD |
| ApiException mit ERROR_PROXY_CONNECT_REFUSED | CapSkip konnte das Ziel über den Proxy nicht erreichen | Testen Sie den Proxy für sich, prüfen Sie Login und Typ und führen Sie das Skript erneut aus |
| ApiException mit ERROR_CAPTCHA_UNSOLVABLE | Die Aufgabe konnte nicht gelöst werden | Holen Sie einen neuen rqdata-Wert und senden Sie eine neue Aufgabe. Die Schleife macht das |
| TimeoutException: timeout 120 exceeded | Die Aufgabe lief beim Limit des Skripts noch, oder die ID war unbekannt oder ihr Ergebnis wurde bereits gelesen (beides kommt als leerer Body zurück) | Prüfen Sie den Monitor in CapSkip und führen Sie das Skript dann erneut aus |
| NetworkException: connect ECONNREFUSED | Unter der CAPSKIP-Adresse antwortet nichts: CapSkip ist beendet, oder Host oder Port stimmen nicht. Die Zeile danach zeigt die Ursache, ECONNREFUSED bei einem Port ohne lauschenden Prozess | Starten Sie CapSkip und vergleichen Sie die Adresse dann mit Ihren Verbindungseinstellungen |
| Die Website lehnt das Formular nach einem gelösten Token ab | Der Token ist älter, als die Website erlaubt, der User-Agent oder die Adresse weicht von der Lösung ab, die Website hat den Token als riskant bewertet, oder der rqdata-Wert war veraltet oder wurde wiederverwendet (mein Mock erzwingt das, die Dokumentation sagt nur, dass er schnell abläuft) | Senden Sie direkt nach der Lösung, senden Sie den userAgent der Antwort, holen Sie für jede Aufgabe einen neuen rqdata-Wert, und lesen Sie die Proxy-Hinweise unten |
Proxys und Server-Modus
CapSkip erzwingt für hCaptcha keinen Proxy. Laut Dokumentation reicht eine Adresse zum Testen und für gelegentliche Lösungen, aber hCaptcha bewertet das Netzwerk, aus dem ein Token kommt, ebenso wie den Browser, und ein stetiger Strom von Lösungen von einer IP ist genau das, was seine Ratenbegrenzungen erkennen sollen. Richten Sie bei größeren Mengen in der App unter Settings, Captcha types, hCaptcha, Configure Proxies einen Proxy-Pool ein. Damit eine Lösung aus einem bestimmten Netzwerk kommt, senden Sie mit der Aufgabe einen Proxy, was die Einstellung PROXY tut. Ein mit einer Aufgabe gesendeter Proxy hat immer Vorrang vor der Liste. CapSkip akzeptiert den Proxy als IP:PORT, LOGIN:PASSWORD@IP:PORT oder IP:PORT:LOGIN:PASSWORD. Ein Proxy-String allein geht mit proxytype HTTP hinaus. Für SOCKS5 übergeben Sie proxy als Objekt mit einem type, der HTTP, HTTPS, SOCKS5 oder SOCKS5H annimmt, und einer uri. Gegen den Mock kam das bei in.php als proxytype SOCKS5 an. Eine echte SOCKS5-Lösung habe ich nicht getestet.
Die Einstellung verlegt nur die Lösung. Für eine strenge Website sagt die Dokumentation außerdem, dass das Formular von derselben Adresse gesendet werden soll, aber das in Node.js eingebaute fetch hat keine Proxy-Option pro Anfrage, daher geht der Formular-POST hier von dem PC aus, auf dem das Skript läuft. Den Formular-POST über einen Proxy habe ich nicht getestet.
Der Server-Modus ändert nur, wo der Löser sitzt. Richten Sie die Einstellung CAPSKIP auf den Server aus, und der Rest des Skripts bleibt, wie er ist. Der Server-Modus verlangt, dass CapSkip als Administrator läuft, und eine statische öffentliche IP gibt den stabilsten Fernzugriff. Der Löser ist weiterhin Ihre eigene Hardware, ohne Gebühr pro Lösung. CapSkip nimmt dann Verbindungen von jeder Adresse an, fügen Sie daher eine Blockierregel der Windows Firewall für die Adressen hinzu, die es nicht erreichen sollen, schalten Sie API Key Validation in CapSkip ein und tragen Sie API_KEY ein. Die Lösung läuft nun auf dem Windows-VPS, daher sieht hCaptcha das Netzwerk dieses Rechners oder den Proxy, den Sie übergeben.
FAQ
Warum braucht hCaptcha Enterprise in Node.js jedes Mal einen frischen rqdata-Wert?
Laut CapSkip-Dokumentation stellt die Website den Wert für eine Challenge aus, und er läuft schnell ab, ein zwischengespeicherter Wert ist also ein alter. Ein veralteter Wert ist ein möglicher Grund für einen abgelehnten Token, und der, den dieser Leitfaden ausschließen kann. Wie eine echte Website mit einem alten Wert scheitert, ist nirgends dokumentiert, wo ich lesen konnte, daher zeigt die Ablehnung durch meinen Mock nur, wie die Schleife reagiert.
Was, wenn die Website einen von CapSkip zurückgegebenen Token trotzdem ablehnt?
Prüfen Sie die Einstellung High score mode, in der Zeile hCaptcha unter Captcha types in Settings. Laut CapSkip-Changelog hat 4.0.0 sie standardmäßig eingeschaltet, und sie löst in Google Chrome. Ist der Modus ausgeschaltet oder Chrome nicht installiert, wird im CapSkip Custom Browser gelöst, und ohne Chrome ist die Einstellung ausgegraut. Die API-Dokumentation ergänzt drei Gewohnheiten für strenge Websites: einen guten Proxy nutzen, das Formular von derselben Adresse aus senden und den User-Agent senden, den die Antwort nennt.
Kann ich CapSkip von einem Skript aufrufen, das auf einer gehosteten Plattform oder einem VPS läuft?
Ja, sobald CapSkip im Server-Modus läuft. Richten Sie die Einstellung CAPSKIP auf seine Adresse aus, und das Skript braucht keine weitere Änderung. Bedenken Sie, dass die Lösung dann auf dem Server läuft, geben Sie der Aufgabe also einen Proxy, wenn der Website das Netzwerk wichtig ist. CapSkip bleibt auf Hardware, die Ihnen gehört.
Was die Website Ihnen auch entgegenstellt: hCaptcha Enterprise in Node.js zu lösen bleibt eine einzige Schleife, mit einem frischen rqdata-Wert, einer neuen Aufgabe und einem sofort gesendeten Token. Wenn Sie sie über einen Captcha-Löser auf Ihrem eigenen Rechner ausführen, fällt bei einer Wiederholung keine Gebühr pro Lösung an. Weitere Node.js-Werkzeuge finden Sie auf der Node.js-Captcha-Solver-Seite, und jeder Parameter steht im hCaptcha-Abschnitt der API-Dokumentation.
