C# ile hCaptcha Nasıl Çözülür: HCaptchaAsync (.NET 8+)

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

C#’ta hCaptcha çözmek için CapSkip NuGet paketinden HCaptchaAsync çağrısını widget’ın sitekey’i ve sayfa adresiyle yapın. Dönen SolveResult token’ı, respKey’i ve token’ı kazanan User-Agent’ı taşır; formunuzu token ile birlikte bu User-Agent altında gönderirsiniz. Aynı metot checkbox, invisible ve Enterprise widget’larını kapsar. Çağrı CapSkip hCaptcha çözücüsü ile konuşur; o, kendi Windows bilgisayarınızda çalışır ve sabit lisans sayesinde ikinci bir deneme hiçbir şeye mal olmaz.

Neye ihtiyacınız var

  • CapSkip 4.0.0 veya üzerini çalıştıran bir Windows bilgisayarı; hCaptcha desteğini ekleyen sürüm budur. Kurulum adımları için bkz. kurulum kılavuzu.
  • En az .NET 8 SDK ve CapSkip NuGet paketi 1.6.0 veya üzeri; HCaptchaAsync bulunan ilk sürüm. Paket netstandard2.0 hedefler ve System.Text.Json 8.0.5 sürümüne bağlıdır. Bende tek bir SDK kurulu, 10.0.100, ve her şeyi yalnızca net10.0 ve net8.0 üzerinde CapSkip 1.6.0 ile çalıştırdım.
  • Bir PowerShell istemi ve üzerinde otomasyon yapmanıza izin verilen, bir hCaptcha widget’ı gösteren bir sayfa; sitekey’iyle birlikte.
  • CapSkip için bir adres. Local modu yalnızca 127.0.0.1 üzerinde yanıt verir, o bilgisayardaki programlar içindir. Server modu ağınızı veya genel IP’nizi de dinler, böylece başka bir makinedeki bir program aynı API’yi çağırabilir. Modu bağlantı ayarları bölümünden seçersiniz.

Test kurulumu: NuGet’ten gerçek CapSkip 1.6.0 paketi ve kendi yazdığım iki mock sunucu; gerçek bir hCaptcha sitesi yok. Mock’lardan biri CapSkip uygulamasının yerini tutar ve API belgeleri içindeki hCaptcha bölümünü izler. İkincisi kayıt sayfasının yerini tutar ve proxy olarak da davranabilir. Kuralları (bir oturum çerezi, bir Referer ya da Origin, token’ın geldiği User-Agent) benim seçimlerimdir, hCaptcha’nın değil. Gerçek bir sitenin token’ı nasıl denetlediği ise hCaptcha geliştirici belgelerinde anlatılır. Paket kaynağını v1.6.0 etiketinde okudum ve gerçek CapSkip uygulamasına hiçbir şey göndermedim, bu yüzden elimde gerçek bir çözüm süresi yok.

1. Adım: projeyi oluşturun ve CapSkip’i kurun

Bir konsol projesi oluşturun ve paketi kurun. Yeni bir proje implicit usings ve nullable reference types özelliklerini etkinleştirir, bu kodun ikisine de ihtiyacı var. Sürüm vermeden dotnet add package en yeni sürümü alır; ben çalıştırdığımda bu 1.6.0 idi.

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

Program.cs içindeki her şeyi, şablonun Console.WriteLine satırı dahil, silin; sonra aşağıdaki üç C# bloğunu sırayla yapıştırın, 2. Adım’dan başlayarak. Yalnızca ilk blokta using satırları var ve son blok yerine oturmadan hiçbir şey çalışmaz.

2. Adım: HCaptchaAsync çağrısı

Sitekey sayfada bulunur. Çoğu sayfa onu widget kapsayıcısında data-sitekey olarak yazdırır; bir script ile oluşturulan widget onu hcaptcha.render() çağrısının sitekey seçeneği olarak verir. HCaptchaAsync sitekey’i, sayfa adresini, bir seçenekler sözlüğünü ve bir CancellationToken alır. Tipli aşırı yüklemesi seçeneklerden önce invisible adlı bir bool alır: true invisible=1 gönderir, false hiçbir şey göndermez. Bir rqdata ayarlayan Enterprise site, değeri data anahtarı altında alır; her görev için yenisi gerekir. Proxy, bir type (HTTP, HTTPS, SOCKS5 veya SOCKS5H) ve bir login:password@host:port dizesi içeren bir Proxy nesnesidir. Portu açıkça yazın, çünkü Uri.Authority varsayılan portu atar. Mock çalıştırmasında invisible, data ve proxy in.php’ye ulaştı.

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);
    }
}

Sonucun bilmeniz gereken dört özelliği var. Token ve Code aynı dizeyi taşır. RespKey, hCaptcha’nın widget’a verdiği ikinci değerdir; bir tarayıcıda hcaptcha.getRespKey() bunu döndürür. Çoğu site onu hiç okumaz ve hiç yoksa null değil, boş bir dizedir. UserAgent, token’ı kazanan tarayıcının User-Agent dizesidir. Yanıt hiçbirini belirtmezse null kalır; o zaman 3. Adım hiç User-Agent göndermez ve mock sitem gönderimi reddetti.

SDK argümanlarınızı herhangi bir istekten önce denetler. Boş bir sitekey, mutlak http veya https olmayan bir sayfa adresi, 0, 1, true veya false dışında bir invisible değeri ve CapSkip’in hCaptcha API’sinin almadığı her parametre, bunların arasında 2Captcha’nın domain parametresi, bir ValidationException fırlatır ve mock bunların hiçbiri için görev almadı. Aksi halde SDK görevi gönderir ve hemen yoklar, sonra 0,25 saniye sonra yine yoklar, ardından aralık 5 saniyeye kadar ikiye katlanarak devam eder. Mock’a karşı yoklamalar, görevden sonraki 0, 0,25, 0,75, 1,75, 3,75, 7,75 ve 12,75. saniyelerin 0,15 saniye içinde gerçekleşti.

Bekleme, RecaptchaTimeout sonrasında TimeoutException ile biter; constructor’a recaptchaTimeout ya da tek bir çağrıya timeout seçeneği vermediğiniz sürece 300 saniyedir. hCaptcha bu daha uzun zaman aşımını alır, çünkü widget gerçek bir tarayıcıda geçilir ve belgeler bir çözümün genellikle 10 ile 30 saniye sürdüğünü söyler. Son tarih yoklamalar arasında denetlenir: 22 saniyelik zaman aşımı ve hiç yanıt vermeyen bir mock ile istisna çağrıdan 22,9 saniye sonra geldi.

SDK’nın fırlattığı her istisna CapSkipError sınıfını genişletir. ValidationException yerel bir reddir. NetworkException, isteğin başarısız olduğu ya da CapSkip’in HTTP 200 ile yanıt vermediği anlamına gelir. ApiException, CapSkip’in bir hatayla yanıt verdiği anlamına gelir ve iletisi yanıt gövdesinin tamamıdır (mock’a karşı, yoklamadan sonra JSON, görevden sonra düz metin), bu yüzden kod onun içinde durur. İki tuzak var. TimeoutException System içinde de bulunur ve implicit usings System ad alanını içe aktarır, bu yüzden using CapSkip yanında yalın bir TimeoutException, belirsiz bir başvuru olan CS0104 ile başarısız olur. İlk blok SDK’nın sınıfına SolverTimeout takma adını verir. Ayrıca görev gönderilirken tetiklenen bir CancellationToken, iptali saran bir NetworkException olarak çıkar; yoklama sırasında tetiklenen ise bir TaskCanceledException olarak çıkar.

3. Adım: formu kendi handler’ından gönderin

Paket CapSkip için kendi HttpClient’ını tutar, bu yüzden aşağıdakilerden hiçbiri onu paylaşmaz. Form gönderimi farklıdır, çünkü bir cookie jar handler’a aittir ve iki kayıt çerez paylaşmamalıdır. Site.SignUp kendi CookieContainer’ına sahip bir handler oluşturur, etrafına bir istemci sarar ve sonunda ikisini de dispose eder. Microsoft’un HttpClient yönergeleri ayrı cookie container’larını, birden fazla örnek kullanmanın bir gerekçesi olarak gösterir.

Sayfa yüklemesi önce gelir, böylece sayfanın çerezleri gönderimle birlikte geri gider. İki istek de sonuçtaki User-Agent’ı taşır. HttpClient siz ayarlamadıkça hiçbirini göndermez: o satır kaldırıldığında, User-Agent’ı token’a karşı denetleyen mock site boş bir tane gördü ve her gönderimi reddetti. Gönderim ayrıca bir Referer ve bir Origin taşır, çünkü HttpClient ikisini de göndermez. Mock sitem bunlardan birini şart koşar, bu benim seçtiğim bir kuraldır ve gerçek sitelerin kaçının bunu yaptığını ölçmedim. Token h-captcha-response ve g-recaptcha-response alanlarına girer. Bir kez çalışır ve belgelere göre yaklaşık iki dakika geçerlidir, bu yüzden hemen gönderin.

Proxy isteğe bağlıdır, ancak belgeler tek bir IP’den gelen düzenli çözüm akışının hCaptcha’nın hız sınırlarına takıldığı konusunda uyarır. Verdiğiniz Uri, Solve.Run aracılığıyla CapSkip’e ve bu handler’a gider, çünkü belgeler katı sitelerde formun çözümle aynı adresten gelmesini ister. WebProxy adresteki kullanıcı adı ve parolayı yok sayar, bu yüzden handler onu bir NetworkCredential’a taşır. Basic kimlik bilgisi isteyen bir mock proxy, parolada yüzde işareti olsa bile onu kabul etti. Site ayağını SOCKS üzerinden çalıştırmadım.

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));
    }
}

4. Adım: C#’ta hCaptcha için tam döngüyü çalıştırın

Son blok Main metodudur. PageUrl ve SiteKey sabitlerini düzenleyin (yapıştırıldığı haliyle widget’ı olmayan example.com’u ister), sonra proje klasöründe dotnet run çalıştırın. Tek bir CancellationTokenSource altında en fazla üç deneme yapar ve her denemenin içinde SDK’nın kendi 300 saniyelik beklemesi vardır. CapSkip 4.1.0 kaynağını okuyuşuma göre bir görev, bir Max. Threads yuvası için 250 saniyeye kadar beklendikten sonra, CapSkip onu çözülemez ilan etmeden önce 300 saniyeye kadar çalışabilir; bu yüzden yük altında recaptchaTimeout değerini yükseltin.

Belgelere göre ERROR_CAPTCHA_UNSOLVABLE, hemen yeni bir görevin yardımcı olabileceği tek koddur. Hız sınırını aşan bir anahtarın aldığı ERROR_NO_SLOT_AVAILABLE, 5 saniyelik bir beklemeden sonra yeniden denenir. Diğer her kod çalıştırmayı bitirir, ValidationException da öyle, çünkü aynı argümanlar yine reddedilirdi. 400 veya daha yüksek yanıt veren bir site yeni bir görev ve yeni bir token alır. 200 her zaman başarı demek değildir, çünkü birçok site hatayı sayfanın içine koyar; bu yüzden durum testini yalnızca başarıda görünen bir şeyle değiştirin. Form gönderiminin 30 saniyelik HttpClient.Timeout süresi dolduğunda son catch bunu bildirir.

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;
    }
}

Gerçek bir site hakkında hiçbir şey kanıtlamayan mock’lara karşı, her satır net10.0 ve net8.0 üzerinde aynı sonucu verdi.

Mock ayarıProgram ne yaptı
Token 7. yoklamada hazır, SDK varsayılanlarıBir görev, yoklamalar görevden sonraki 0, 0,25, 0,75, 1,75, 3,75, 7,75 ve 12,75. saniyelerin 0,15 saniye içinde, sonra 200
İki ret (ERROR_CAPTCHA_UNSOLVABLE ya da beklemeli ERROR_NO_SLOT_AVAILABLE), sonra başarı; ya da her seferinde retÜçüncü görevde 200; ya da üç deneme satırı, çıkış kodu 1 ve siteye hiç istek yok
Site ilk form gönderimini 403 ile reddederYeni bir görev ve token, sonra 200
Boş sitekeyBir ValidationException satırı ve çıkış kodu 1; mock’ta görev yok
ERROR_ZERO_BALANCE, ERROR_PROXY_CONNECT_REFUSED veya ERROR_RECAPTCHA_INVALID_SITEKEYHer biri çalıştırmayı bir görevden sonra durdurdu
Invisible çağrı, Enterprise çağrısı, giriş bilgisi olan ya da olmayan proxyin.php invisible=1’i, data değerini ya da proxytype HTTP artı adresi gördü ve site istekleri proxy mock’u üzerinden geldi
Constructor’da bir apiKey, anahtar doğrulaması açıkAnahtar görev gönderimine ve her yoklamaya ulaştı. Varsayılan anahtar ERROR_KEY_DOES_NOT_EXIST aldı
recaptchaTimeout değeri 22 ve hiç yanıt vermeyen bir mockTimeoutException, çağrıdan 22,9 saniye sonra
2 saniyelik bütçe, bir yoklama beklemesi ya da takılan bir in.php sırasındaHer iki seferde de 2,0 saniye sonra bütçe iletisi
CapSkip’te ya da sitede dinleyen yok; hiç yanıt vermeyen bir site sayfasıNetworkException; istek başarısız oldu; 30 saniye sonra 30 saniyelik ileti
Aynı anda üç kayıtÜç görev, üç oturum, gönderimlerde üç User-Agent, üç 200 yanıtı

İki kod parçası geri kalanı kapsar. İlki çağrıyı invisible ya da Enterprise widget için değiştirir. İkincisi aynı anda birkaç hesap kaydeder: Main içindeki dış try bloğunun süslü parantezleri arasındaki satırları onunla değiştirin ve catch satırlarını koruyun. Her kayıt kendi handler’ını oluşturur ve mock her göreve kendi User-Agent’ını verir, bu yüzden bir karışıklık gönderimlerin başarısız olmasına yol açardı. Kod parçası rqData geçirmez; bu yüzden bir Enterprise site için lambda içinde yeni bir değer okuyun.

// 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;

Yaygın hatalar

GördüğünüzNedenDüzeltme
ValidationExceptionGöndermeden önce reddedildi: boş bir sitekey, mutlak http veya https olmayan bir sayfa adresi, hatalı bir invisible değeri ya da domain gibi hCaptcha API’sinin almadığı bir parametreArgümanı düzeltin. Yeniden denemek yardımcı olmaz
ERROR_RECAPTCHA_INVALID_SITEKEYSitekey o sayfa için reddedildidata-sitekey değerini yeniden kopyalayın ve sayfa adresini kontrol edin
ERROR_CAPTCHA_UNSOLVABLECapSkip widget’ı geçemediDöngü yeni bir görev gönderir, en fazla üç kez
ERROR_PROXY_FORMAT veya ERROR_PROXY_CONNECT_REFUSEDCapSkip proxy değerini okuyamadı ya da hedefe onun üzerinden ulaşamadı (ikinci durumu yalnızca simüle ettim)Şema, host ve port içeren bir Uri verin ve proxy’yi tek başına test edin
ERROR_WRONG_METHOD4.0.0 öncesi bir CapSkip hCaptcha metodunu tanımayabilir (test edilmedi)CapSkip’i 4.0.0 veya üzerine güncelleyin
ERROR_NO_SLOT_AVAILABLE, ERROR_ZERO_BALANCE veya ERROR_IP_NOT_ALLOWEDYalnızca API Key Validation açıkken. 4.1.0 kaynağını okuyuşuma göre: anahtar hız sınırını aştı, kredisi bitti ya da tek cihazlık bir anahtar başka yerde kullanılıyorDöngü ilkinde duraklar ve yeniden dener. Diğerleri için anahtarın ayarlarını CapSkip’te değiştirin
ERROR_WRONG_USER_KEY veya ERROR_KEY_DOES_NOT_EXISTAPI Key Validation açık ve constructor çağrınızdaki apiKey eksik ya da yanlışCapSkipClient satırında geçerli bir apiKey verin
TimeoutExceptionrecaptchaTimeout içinde token gelmedi. Boş bir yanıt hazır değil sayılır, bu yüzden SDK yoklamaya devam ederGörevi CapSkip Monitor sekmesinde kontrol edin, sonra recaptchaTimeout değerini yükseltin
Çağrı başlarken NetworkExceptionO host ve portta yanıt veren program yok. İç istisna bir HttpRequestExceptionCapSkip’i çalıştırın, sonra host ve portunu bağlantı ayarlarından constructor çağrınıza kopyalayın
Error CS0104: belirsiz başvuruTimeoutException hem System içinde hem CapSkip içinde var. System.ComponentModel.DataAnnotations içe aktarıldığında ValidationException da aynı şekilde çakışırSDK sınıfına ilk blokta olduğu gibi takma ad verin ya da tam adını yazın
Geçerli görünen bir token reddediliyorBelgeler şunları sayar: yeniden kullanılmış bir token, yaklaşık iki dakikadan eski bir token ve sonuçtakinden farklı bir User-Agent. Mock’um ayrıca eksik bir User-Agent, Referer, Origin ya da oturum çerezini de reddetti. 407, proxy’nin bir giriş istediği anlamına gelirHer token’ı Site.SignUp içinden bir kez, hemen gönderin

CapSkip’i bir sunucuda kullanma

Server modunda CapSkip ağ adresinizi ya da bir genel IP’yi dinler; bu yüzden C#’ta aynı hCaptcha kodu başka bir bilgisayardan, bir Windows VPS’ten ya da barındırılan bir platformdan çalışır. Server modu CapSkip’in yönetici olarak çalışmasını gerektirir ve kurulum kılavuzu statik bir genel IP önerir. CapSkipClient satırındaki host’u sunucunun adresiyle değiştirin; başka hiçbir şey değişmez.

Server modu başladığında CapSkip portunu her adrese açar; bu yüzden onu beklediğiniz makinelerle sınırlamak için diğerleri için bir Windows Firewall engelleme kuralı ekleyin ve CapSkipClient satırında bir apiKey ile API Key Validation’ı açın. Çözüm artık sunucuda çalışır, bu yüzden hCaptcha o makinenin ağını görür.

FAQ

C#’ta invisible ya da Enterprise hCaptcha nasıl çözülür?

Aynı HCaptchaAsync çağrısıyla. data-size değeri invisible olan bir widget için invisible bool değerine true verin. Bir rqdata ayarlayan Enterprise site için değeri data anahtarı altında verin ve her görev için yenisini okuyun, çünkü belgeler sitenin onu tek bir challenge için verdiğini söyler. 4. Adım’daki ilk kod parçası ikisini de gösterir.

SDK’yı IHttpClientFactory ile kaydedebilir miyim?

Kaydedilecek bir şey yok. Paket CapSkip’e yaptığı çağrıları kendi static HttpClient’ıyla yapar. Site.SignUp’ı da factory’nin dışında tutun: Microsoft’un yönergeleri, havuzlanmış handler’ların CookieContainer’larını paylaştığı konusunda uyarır.

Site neden CapSkip’in verdiği bir token’ı reddediyor?

Katı bir site, widget geçilmiş olsa bile hCaptcha’nın riskli puanladığı bir token’ı reddedebilir; Enterprise siteler olağan durumdur. Belgeler hCaptcha ayarlarındaki High score mode’u önerir. CapSkip bilgisayarında Google Chrome gerektirir ve 4.1.0 kaynağını okuyuşuma göre varsayılan olarak açıktır. Denemek için elimde katı bir site yoktu.

C#’ta hCaptcha çözmek, tek bir HCaptchaAsync çağrısına, yalnızca denemeye değer kodları yeniden deneyen bir döngüye ve doğru çerezlere ve User-Agent’a sahip bir handler’dan yapılan form gönderimine iner. CapSkip yerel bir captcha atlatma aracıdır ve sabit lisansla çalışır, bu yüzden bir deneme daha yalnızca süreye mal olur. C# CAPTCHA çözücü sayfası diğer CAPTCHA türlerini .NET için kapsar; hCaptcha demosu ise bir widget’ın geçtiğini gösterir.