So lösen Sie hCaptcha in C# mit HCaptchaAsync (.NET 8+)

hcaptcha in c# - How to Solve hCaptcha in C# With HCaptchaAsync (.NET 8+)

Um hCaptcha in C# zu lösen, rufen Sie HCaptchaAsync aus dem NuGet-Paket CapSkip mit dem sitekey des Widgets und der Seitenadresse auf. Das zurückgegebene SolveResult enthält den Token, den respKey und den User-Agent, mit dem der Token ausgestellt wurde, und Sie senden Ihr Formular mit dem Token unter diesem User-Agent. Dieselbe Methode deckt Checkbox-Widgets, unsichtbare Widgets und Enterprise-Widgets ab. Den Aufruf nimmt der CapSkip-hCaptcha-Löser auf Ihrem eigenen Windows-PC entgegen, und dank der Pauschallizenz kostet ein zweiter Versuch nichts.

Was Sie brauchen

  • Ein Windows-PC mit CapSkip 4.0.0 oder neuer, der Version, die hCaptcha hinzugefügt hat. Die Installationsschritte stehen in der Einrichtungsanleitung.
  • Das .NET-8-SDK oder neuer und das NuGet-Paket CapSkip 1.6.0 oder neuer, die erste Version mit HCaptchaAsync. Das Paket zielt auf netstandard2.0 und hängt von System.Text.Json 8.0.5 ab. Ich habe ein SDK installiert, 10.0.100, und alles mit CapSkip 1.6.0 nur unter net10.0 und net8.0 ausgeführt.
  • Eine PowerShell-Eingabeaufforderung und eine Seite, die Sie automatisieren dürfen und die ein hCaptcha-Widget zeigt, samt ihrem sitekey.
  • Eine Adresse für CapSkip. Der Local-Modus antwortet nur auf 127.0.0.1, für Programme auf diesem PC. Der Server-Modus lauscht zusätzlich auf Ihrer Netzwerkadresse oder öffentlichen IP, sodass ein Programm auf einem anderen Rechner dieselbe API aufrufen kann. Die Verbindungseinstellungen speichern diese Wahl.

Testaufbau: das echte CapSkip-Paket 1.6.0 von NuGet und zwei eigene Mock-Server, ohne echte hCaptcha-Website. Ein Mock steht für die CapSkip-App und folgt dem hCaptcha-Abschnitt der API-Dokumentation. Der andere spielt die Registrierungsseite und kann als Proxy dienen. Seine Regeln (ein Sitzungs-Cookie, ein Referer oder ein Origin, der User-Agent, mit dem der Token kam) habe ich gewählt, sie stammen nicht von hCaptcha. Die Entwicklerdokumente von hCaptcha beschreiben, wie eine echte Website einen Token prüft. Ich habe den Paketquelltext beim Tag v1.6.0 gelesen und der echten CapSkip-App nichts gesendet, daher habe ich keine echte Lösezeit.

Schritt 1: das Projekt erstellen und CapSkip installieren

Erstellen Sie ein Konsolenprojekt und installieren Sie das Paket. Ein neues Projekt aktiviert implizite usings und Nullable-Referenztypen, und dieser Code braucht beides. Ohne Version nimmt dotnet add package das neueste Release, bei meinem Lauf 1.6.0.

dotnet new console -o hcaptcha-demo
cd hcaptcha-demo
dotnet add package CapSkip

Löschen Sie in Program.cs alles, auch die Zeile Console.WriteLine der Vorlage, und fügen Sie dann die drei C#-Blöcke unten der Reihe nach ein, beginnend mit Schritt 2. Nur der erste Block hat using-Zeilen, und nichts läuft, bevor der letzte Block eingefügt ist.

Schritt 2: HCaptchaAsync aufrufen

Der sitekey steht auf der Seite. Die meisten Seiten geben ihn als data-sitekey am Container des Widgets aus, und ein per Skript gebautes Widget übergibt ihn als Option sitekey von hcaptcha.render(). HCaptchaAsync nimmt den sitekey, die Seitenadresse, ein Options-Dictionary und ein CancellationToken. Seine typisierte Überladung nimmt vor den Optionen einen bool namens invisible: true sendet invisible=1, false sendet nichts. Eine Enterprise-Website, die rqdata setzt, bekommt den Wert unter dem Schlüssel data, für jede Aufgabe frisch. Ein Proxy ist ein Proxy-Objekt mit einem type (HTTP, HTTPS, SOCKS5 oder SOCKS5H) und einem String login:password@host:port. Schreiben Sie den Port aus, weil Uri.Authority einen Standardport weglässt. Im Mock-Lauf kamen invisible, data und der Proxy bei in.php an.

using System.Net;
using System.Text.RegularExpressions;
using CapSkip;
using SolverTimeout = CapSkip.TimeoutException;  // System.TimeoutException is in scope too (CS0104)

static class Solve
{
    // Local mode. In Server mode, use your server's address instead. If API Key
    // Validation is on in CapSkip, also pass apiKey: "YOUR_KEY" here.
    static readonly CapSkipClient Client = new(host: "127.0.0.1", port: 8080);

    public static Task<SolveResult> Run(string siteKey, string pageUrl, bool invisible,
                                        string? rqData, Uri? proxy, CancellationToken ct)
    {
        var options = new Dictionary<string, object?>();
        if (rqData is not null) options["data"] = rqData;  // Enterprise rqdata, fresh per task
        if (proxy is not null)
        {
            // Uri.Authority drops a default port such as 80, so build host:port by hand.
            var login = proxy.UserInfo.Length > 0 ? Uri.UnescapeDataString(proxy.UserInfo) + "@" : "";
            options["proxy"] = new Proxy(proxy.Scheme.ToUpperInvariant(), $"{login}{proxy.Host}:{proxy.Port}");
        }
        // invisible: false sends nothing, true sends invisible=1.
        return Client.HCaptchaAsync(siteKey, pageUrl, invisible, options, ct);
    }
}

Das Ergebnis hat vier Eigenschaften, die Sie kennen sollten. Token und Code enthalten denselben String. RespKey ist der zweite Wert, den hCaptcha dem Widget übergibt, derjenige, den hcaptcha.getRespKey() in einem Browser zurückgibt. Die meisten Websites lesen ihn nie, und er ist ein leerer String, nicht null, wenn es keinen gibt. UserAgent ist der User-Agent-String des Browsers, der den Token ausgestellt hat. Er bleibt null, wenn die Antwort keinen nennt, und dann sendet Schritt 3 keinen User-Agent, und meine Mock-Website lehnte den Post ab.

Das SDK prüft Ihre Argumente vor jeder Anfrage. Ein leerer sitekey, eine Seitenadresse, die kein absolutes http oder https ist, ein invisible-Wert außer 0, 1, true oder false und jeder Parameter, den die hCaptcha-API von CapSkip nicht annimmt, darunter domain von 2Captcha, lösen eine ValidationException aus, und der Mock erhielt für keinen davon eine Aufgabe. Andernfalls sendet das SDK die Aufgabe und fragt sofort ab, dann nach 0,25 Sekunden wieder und danach mit sich verdoppelndem Abstand bis zu 5 Sekunden. Gegen den Mock trafen die Abfragen innerhalb von 0,15 Sekunden bei 0; 0,25; 0,75; 1,75; 3,75; 7,75 und 12,75 Sekunden nach dem Senden ein.

Das Warten endet mit einer TimeoutException nach RecaptchaTimeout, 300 Sekunden, sofern Sie dem Konstruktor kein recaptchaTimeout oder einem Aufruf keine Option timeout übergeben. hCaptcha bekommt dieses längere Timeout, weil das Widget in einem echten Browser bestanden wird, und laut Dokumentation dauert eine Lösung meist 10 bis 30 Sekunden. Die Frist wird zwischen den Abfragen geprüft: Bei einem Timeout von 22 Sekunden und einem Mock, der nie antwortete, kam die Exception 22,9 Sekunden nach dem Aufruf.

Jede Exception des SDK erweitert CapSkipError. ValidationException ist eine lokale Ablehnung. NetworkException bedeutet, dass die Anfrage scheiterte oder CapSkip nicht mit HTTP 200 antwortete. ApiException bedeutet, dass CapSkip mit einem Fehler antwortete, und ihre Meldung ist der gesamte Antwort-Body (JSON nach einer Abfrage und bloßer Text nach dem Senden, gegen den Mock), der Code steckt also darin. Zwei Fallen folgen daraus. TimeoutException gibt es auch in System, und implizite usings importieren System, daher scheitert eine bloße TimeoutException neben using CapSkip mit CS0104, einer mehrdeutigen Referenz. Der erste Block gibt der Klasse des SDK den Alias SolverTimeout. Und ein CancellationToken, das beim Senden auslöst, kommt als NetworkException heraus, die den Abbruch umschließt, während eines, das beim Abfragen auslöst, als TaskCanceledException herauskommt.

Schritt 3: das Formular mit einem eigenen Handler senden

Das Paket hält für CapSkip einen eigenen HttpClient, daher teilt nichts unten ihn. Der Formular-POST ist anders, denn ein Cookie-Jar gehört zum Handler, und zwei Registrierungen dürfen keine Cookies teilen. Site.SignUp baut einen Handler mit eigenem CookieContainer, legt einen Client darum und gibt am Ende beide frei. Die HttpClient-Richtlinien von Microsoft nennen getrennte Cookie-Container als Grund für mehr als eine Instanz.

Zuerst kommt das Laden der Seite, damit die Cookies der Seite mit dem Post zurückgehen. Beide Anfragen tragen den User-Agent aus dem Ergebnis. HttpClient sendet keinen, wenn Sie keinen setzen: Ohne diese Zeile sah die Mock-Website, die ihn mit dem Token abgleicht, einen leeren und lehnte jeden Post ab. Der Post trägt außerdem einen Referer und einen Origin, denn HttpClient sendet keinen von beiden. Meine Mock-Website verlangt einen von beiden, eine Regel, die ich gewählt habe, und ich habe nicht gemessen, wie viele echte Websites das tun. Der Token geht in h-captcha-response und g-recaptcha-response. Er funktioniert einmal und hält laut Dokumentation etwa zwei Minuten, senden Sie ihn also sofort.

Ein Proxy ist optional, auch wenn die Dokumentation warnt, dass ein stetiger Strom von Lösungen von einer IP genau das ist, was die Ratenbegrenzungen von hCaptcha erkennen. Das Uri-Objekt, das Sie übergeben, geht über Solve.Run an CapSkip und an diesen Handler, weil die Dokumentation für strenge Websites verlangt, dass das Formular von derselben Adresse kommt wie die Lösung. WebProxy ignoriert einen Login in der Adresse, daher übernimmt der Handler ihn in eine NetworkCredential. Ein Mock-Proxy, der Basic-Zugangsdaten verlangte, akzeptierte sie, auch mit einem Prozentzeichen im Passwort. Den Weg zur Website über SOCKS habe ich nicht ausgeführt.

static class Site
{
    // One HttpClient per sign-up, because the cookie jar belongs to the handler and two
    // sign-ups must not share cookies. Dispose it when the sign-up is over.
    public static async Task<(HttpStatusCode Status, string Body)> SignUp(
        string pageUrl, SolveResult solved, string email, Uri? proxy, CancellationToken ct)
    {
        var handler = new HttpClientHandler { CookieContainer = new CookieContainer() };
        if (proxy is not null)
        {
            var address = new UriBuilder(proxy.Scheme, proxy.Host, proxy.Port).Uri;
            var login = proxy.UserInfo.Split(':', 2).Select(Uri.UnescapeDataString).ToArray();
            handler.Proxy = new WebProxy(address)
            {
                Credentials = login.Length == 2 ? new NetworkCredential(login[0], login[1]) : null,
            };
        }
        using var http = new HttpClient(handler) { Timeout = TimeSpan.FromSeconds(30) };
        // The User-Agent the token was earned with, on the page load and on the post.
        if (solved.UserAgent is not null)
            http.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", solved.UserAgent);

        using (await http.GetAsync(pageUrl, ct)) { }  // the page's own cookies land in the jar

        var origin = new Uri(pageUrl).GetLeftPart(UriPartial.Authority);
        using var post = new HttpRequestMessage(HttpMethod.Post, pageUrl)
        {
            Content = new FormUrlEncodedContent(new Dictionary<string, string>
            {
                ["email"] = email,  // your form's own fields go here
                ["h-captcha-response"] = solved.Token!,  // always set on an hCaptcha result
                ["g-recaptcha-response"] = solved.Token!,  // the widget fills both
            }),
        };
        post.Headers.TryAddWithoutValidation("Referer", pageUrl);  // HttpClient sends none
        post.Headers.TryAddWithoutValidation("Origin", origin);
        using var response = await http.SendAsync(post, ct);
        return (response.StatusCode, await response.Content.ReadAsStringAsync(ct));
    }
}

Schritt 4: die ganze Schleife für hCaptcha in C# ausführen

Der letzte Block ist die Methode Main. Bearbeiten Sie die Konstanten PageUrl und SiteKey (wie eingefügt, fragt er example.com an, das kein Widget hat), und führen Sie dann dotnet run im Projektordner aus. Er macht bis zu drei Versuche unter einer CancellationTokenSource, und in jedem Versuch steckt das eigene Warten des SDK von 300 Sekunden. Nach meiner Lesart des Quelltexts von CapSkip 4.1.0 kann eine Aufgabe bis zu 300 Sekunden laufen, bevor CapSkip sie für unlösbar erklärt, nachdem sie bis zu 250 Sekunden auf einen freien Platz unter Max. Threads gewartet hat. Erhöhen Sie unter Last daher recaptchaTimeout.

ERROR_CAPTCHA_UNSOLVABLE ist laut Dokumentation der eine Code, bei dem eine sofortige neue Aufgabe helfen kann. ERROR_NO_SLOT_AVAILABLE, den ein Schlüssel über seinem Ratenlimit bekommt, wird nach einer Pause von 5 Sekunden wiederholt. Jeder andere Code beendet den Lauf, ebenso eine ValidationException, da dieselben Argumente wieder abgelehnt würden. Eine Website, die mit 400 oder höher antwortet, bekommt eine neue Aufgabe und einen neuen Token. Ein 200 bedeutet nicht immer Erfolg, denn viele Websites legen den Fehler in die Seite, tauschen Sie also die Statusprüfung gegen etwas aus, das nur ein Erfolg zeigt. Läuft das HttpClient.Timeout von 30 Sekunden des Formular-POST ab, meldet es der letzte catch.

static class Program
{
    const string PageUrl = "https://example.com/signup";  // the page that shows the widget
    const string SiteKey = "YOUR_SITEKEY";  // the data-sitekey of its h-captcha div
    static readonly Uri? ProxyUri = null;  // for example new Uri("http://user:[email protected]:8080")

    // The reply body is the exception message, JSON on a poll and bare text on a submit.
    static string ErrorCode(ApiException ex)
    {
        var found = Regex.Match(ex.Message, "ERROR_[A-Z_]+");
        return found.Success ? found.Value : ex.Message;
    }

    static async Task<int> Main()
    {
        // One budget for every attempt. Cancelling it stops a wait or a request at once.
        using var budget = new CancellationTokenSource(TimeSpan.FromMinutes(6));
        try
        {
            for (var attempt = 1; attempt <= 3; attempt++)
            {
                SolveResult solved;
                try
                {
                    solved = await Solve.Run(SiteKey, PageUrl, invisible: false, rqData: null, ProxyUri, budget.Token);
                }
                catch (ApiException ex) when (ErrorCode(ex) is "ERROR_CAPTCHA_UNSOLVABLE" or "ERROR_NO_SLOT_AVAILABLE")
                {
                    Console.WriteLine($"attempt {attempt}: {ErrorCode(ex)}, new task");
                    // The second code means the key is over its rate limit, so pause first.
                    if (ErrorCode(ex) == "ERROR_NO_SLOT_AVAILABLE") await Task.Delay(TimeSpan.FromSeconds(5), budget.Token);
                    continue;
                }

                var (status, body) = await Site.SignUp(PageUrl, solved, "[email protected]", ProxyUri, budget.Token);
                if ((int)status < 400)
                {
                    Console.WriteLine($"{(int)status} {body[..Math.Min(40, body.Length)]}");
                    return 0;
                }
                Console.WriteLine($"attempt {attempt}: the site answered {(int)status}, new token");
            }
            Console.WriteLine("no accepted form after 3 attempts");
        }
        // A cancelled submit surfaces as a NetworkException, a cancelled poll as a
        // TaskCanceledException, so test the budget itself.
        catch (Exception) when (budget.IsCancellationRequested) { Console.WriteLine("the 6 minute budget ran out"); }
        catch (ApiException ex) { Console.WriteLine($"CapSkip answered {ErrorCode(ex)}"); }
        catch (SolverTimeout ex) { Console.WriteLine($"no token in time: {ex.Message}"); }
        catch (CapSkipError ex) { Console.WriteLine($"{ex.GetType().Name}: {ex.Message}"); }
        catch (HttpRequestException ex) { Console.WriteLine($"request failed: {ex.Message}"); }
        catch (TaskCanceledException) { Console.WriteLine("the site did not answer in 30 seconds"); }  // HttpClient.Timeout
        return 1;
    }
}

Gegen die Mocks, die nichts über eine echte Website beweisen, kam jede Zeile unter net10.0 und net8.0 gleich heraus.

Mock-EinstellungWas das Programm tat
Token bei der 7. Abfrage bereit, SDK-StandardwerteEine Aufgabe, Abfragen innerhalb von 0,15 Sekunden bei 0; 0,25; 0,75; 1,75; 3,75; 7,75 und 12,75 Sekunden nach dem Senden, dann 200
Zwei Ablehnungen (ERROR_CAPTCHA_UNSOLVABLE oder ERROR_NO_SLOT_AVAILABLE mit einer Pause), dann Erfolg; oder jedes Mal Ablehnungen200 bei der dritten Aufgabe; oder drei Versuchszeilen, Exit-Code 1 und keine Anfrage an die Website
Website lehnt den ersten Formular-POST mit einer 403 abEine neue Aufgabe und ein neuer Token, dann 200
Leerer sitekeyEine Zeile ValidationException und Exit-Code 1, ohne Aufgabe beim Mock
ERROR_ZERO_BALANCE, ERROR_PROXY_CONNECT_REFUSED oder ERROR_RECAPTCHA_INVALID_SITEKEYJeder beendete den Lauf nach einer Aufgabe
Unsichtbarer Aufruf, Enterprise-Aufruf, Proxy mit oder ohne Loginin.php sah invisible=1, den Wert data oder proxytype HTTP plus die Adresse, und die Anfragen an die Website kamen über den Proxy-Mock an
Ein apiKey im Konstruktor, Schlüsselprüfung eingeschaltetDer Schlüssel erreichte das Senden und jede Abfrage. Der Standardschlüssel bekam ERROR_KEY_DOES_NOT_EXIST
recaptchaTimeout von 22 und ein Mock, der nie antwortetTimeoutException, 22,9 Sekunden nach dem Aufruf
Zeitbudget von 2 Sekunden, während einer Abfragepause oder einem hängenden in.phpDie Meldung zum Zeitbudget beide Male nach 2,0 Sekunden
Nichts lauscht bei CapSkip oder bei der Website; eine Seite der Website, die nie antwortetNetworkException; request failed; die Meldung zu 30 Sekunden nach 30 Sekunden
Drei Registrierungen gleichzeitigDrei Aufgaben, drei Sitzungen, drei User-Agents bei den Posts, drei Antworten 200

Zwei Snippets decken den Rest ab. Das erste tauscht den Aufruf gegen ein unsichtbares oder ein Enterprise-Widget aus. Das zweite meldet mehrere Konten gleichzeitig an: Ersetzen Sie die Zeilen zwischen den geschweiften Klammern des äußeren try in Main durch es und behalten Sie die catch-Zeilen. Jede Registrierung baut ihren eigenen Handler, und der Mock gibt jeder Aufgabe ihren eigenen User-Agent, ein Durcheinander hätte also die Posts scheitern lassen. Das Snippet übergibt kein rqData, lesen Sie daher für eine Enterprise-Website in der Lambda einen frischen Wert.

// Snippet, not part of Program.cs. In Main, replace the Solve.Run line with one of these.
// An invisible widget (data-size="invisible"):
solved = await Solve.Run(SiteKey, PageUrl, invisible: true, rqData: null, ProxyUri, budget.Token);
// An Enterprise widget. Read a fresh rqdata value from the page before every attempt,
// because it is single use. The literal below stands in for that code.
solved = await Solve.Run(SiteKey, PageUrl, invisible: false, rqData: "RQDATA_FROM_THE_PAGE", ProxyUri, budget.Token);
// Snippet, not part of Program.cs. In Main, replace the lines between the braces of the outer try
// with these, and keep the catch lines. Three accounts sign up at once on one SDK client.
var emails = new[] { "[email protected]", "[email protected]", "[email protected]" };
var codes = await Task.WhenAll(emails.Select(async email =>
{
    var solved = await Solve.Run(SiteKey, PageUrl, false, null, ProxyUri, budget.Token);
    var (status, _) = await Site.SignUp(PageUrl, solved, email, ProxyUri, budget.Token);
    return (int)status;
}));
Console.WriteLine(string.Join(" ", codes));
return codes.All(c => c < 400) ? 0 : 1;

Häufige Fehler

Was Sie sehenUrsacheBeheben
ValidationExceptionVor dem Senden abgelehnt: ein leerer sitekey, eine Seitenadresse, die kein absolutes http oder https ist, ein ungültiger invisible-Wert oder ein Parameter wie domain, den die hCaptcha-API nicht annimmtKorrigieren Sie das Argument. Eine Wiederholung hilft nicht
ERROR_RECAPTCHA_INVALID_SITEKEYDer sitekey wurde für diese Seite abgelehntKopieren Sie data-sitekey neu und prüfen Sie die Seitenadresse
ERROR_CAPTCHA_UNSOLVABLECapSkip hat das Widget nicht bestandenDie Schleife sendet eine neue Aufgabe, bis zu dreimal
ERROR_PROXY_FORMAT oder ERROR_PROXY_CONNECT_REFUSEDCapSkip konnte den Proxy-Wert nicht lesen oder das Ziel darüber nicht erreichen (den zweiten Fall habe ich nur simuliert)Übergeben Sie einen Uri mit Schema, Host und Port und testen Sie den Proxy für sich
ERROR_WRONG_METHODEin CapSkip älter als 4.0.0 kennt die Methode für hCaptcha vielleicht nicht (nicht getestet)Aktualisieren Sie CapSkip auf 4.0.0 oder neuer
ERROR_NO_SLOT_AVAILABLE, ERROR_ZERO_BALANCE oder ERROR_IP_NOT_ALLOWEDNur bei eingeschalteter API Key Validation. Nach meiner Lesart des Quelltexts von 4.1.0: Der Schlüssel hat sein Ratenlimit überschritten, hat keine Credits mehr, oder ein Schlüssel für ein einziges Gerät wird anderswo benutztDie Schleife pausiert und wiederholt beim ersten. Ändern Sie bei den anderen die Einstellungen des Schlüssels in CapSkip
ERROR_WRONG_USER_KEY oder ERROR_KEY_DOES_NOT_EXISTAPI Key Validation ist eingeschaltet, und der apiKey in Ihrem Konstruktoraufruf fehlt oder ist falschÜbergeben Sie in der Zeile CapSkipClient einen gültigen apiKey
TimeoutExceptionInnerhalb von recaptchaTimeout kam kein Token an. Eine leere Antwort gilt als noch nicht bereit, daher fragt das SDK weiter abSuchen Sie die Aufgabe im CapSkip Monitor und erhöhen Sie dann recaptchaTimeout
NetworkException, wenn der Aufruf beginntKein Programm antwortet an diesem Host und Port. Die innere Exception ist eine HttpRequestExceptionStarten Sie CapSkip und kopieren Sie dann Host und Port aus den Verbindungseinstellungen in Ihren Konstruktoraufruf
Error CS0104: ambiguous referenceTimeoutException gibt es in System und in CapSkip. ValidationException kollidiert genauso, sobald Sie System.ComponentModel.DataAnnotations importierenGeben Sie der Klasse des SDK einen Alias, wie es der erste Block tut, oder schreiben Sie ihren vollständigen Namen
Ein gültig aussehender Token wird abgelehntDie Dokumentation nennt einen wiederverwendeten Token, einen, der älter als etwa zwei Minuten ist, und einen anderen User-Agent als den des Ergebnisses. Mein Mock lehnte auch einen fehlenden User-Agent, Referer, Origin oder ein fehlendes Sitzungs-Cookie ab. Ein 407 bedeutet, dass der Proxy einen Login willSenden Sie jeden Token nur einmal, sofort, aus Site.SignUp

CapSkip auf einem Server verwenden

Im Server-Modus lauscht CapSkip auf Ihrer Netzwerkadresse oder einer öffentlichen IP, sodass derselbe Code für hCaptcha in C# von einem anderen PC, einem Windows-VPS oder einer gehosteten Plattform aus funktioniert. Der Server-Modus verlangt, dass CapSkip als Administrator läuft, und die Einrichtungsanleitung empfiehlt eine statische öffentliche IP. Ändern Sie den Host in der Zeile CapSkipClient auf die Adresse des Servers, und sonst ändert sich nichts.

CapSkip öffnet seinen Port für jede Adresse, wenn der Server-Modus startet. Damit er nur den erwarteten Rechnern offensteht, fügen Sie eine Blockierregel der Windows Firewall für die anderen hinzu und schalten Sie API Key Validation mit einem apiKey in der Zeile CapSkipClient ein. Die Lösung läuft jetzt auf dem Server, daher sieht hCaptcha das Netzwerk dieses Rechners.

FAQ

Wie löse ich ein unsichtbares oder Enterprise-hCaptcha in C#?

Mit demselben Aufruf HCaptchaAsync. Übergeben Sie für ein Widget, dessen data-size invisible ist, true als bool invisible. Für eine Enterprise-Website, die rqdata setzt, übergeben Sie den Wert unter dem Schlüssel data und lesen für jede Aufgabe einen frischen, denn laut Dokumentation stellt die Website ihn für eine Challenge aus. Das erste Snippet in Schritt 4 zeigt beides.

Kann ich das SDK mit IHttpClientFactory registrieren?

Es gibt nichts zu registrieren. Das Paket macht seine Aufrufe an CapSkip mit einem eigenen statischen HttpClient. Halten Sie auch Site.SignUp aus der Factory heraus: Die Richtlinien von Microsoft warnen, dass gepoolte Handler ihren CookieContainer teilen.

Warum lehnt die Website einen Token ab, den CapSkip mir gegeben hat?

Eine strenge Website kann einen Token ablehnen, den hCaptcha als riskant bewertet hat, auch wenn das Widget bestanden wurde, und Enterprise-Websites sind der übliche Fall. Die Dokumentation rät zu High score mode in den hCaptcha-Einstellungen. Er braucht Google Chrome auf dem CapSkip-PC und ist nach meiner Lesart des Quelltexts von 4.1.0 standardmäßig eingeschaltet. Ich hatte keine strenge Website zum Testen.

hCaptcha in C# zu lösen läuft auf einen Aufruf HCaptchaAsync hinaus, eine Schleife, die nur die Codes wiederholt, bei denen es sich lohnt, und einen Formular-POST von einem Handler mit den richtigen Cookies und dem richtigen User-Agent. Bei CapSkip läuft die Captcha-Umgehung lokal und mit einer Pauschallizenz, daher kostet ein weiterer Versuch nur die Zeit, die er braucht. Die C#-Captcha-Solver-Seite behandelt die anderen Captcha-Typen in .NET, und die hCaptcha-Demo zeigt, wie ein Widget bestanden wird.