Cara Memecahkan hCaptcha di C# dengan HCaptchaAsync (.NET 8+)

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

Untuk memecahkan hCaptcha di C#, panggil HCaptchaAsync dari paket NuGet CapSkip dengan sitekey widget dan alamat halaman. SolveResult yang dikembalikan memuat token, respKey, dan User-Agent yang dipakai saat token diperoleh, dan Anda mengirim formulir dengan token itu di bawah User-Agent tersebut. Metode yang sama mencakup widget checkbox, invisible, dan Enterprise. Panggilan itu dikirim ke pemecah hCaptcha CapSkip yang berjalan di PC Windows Anda sendiri, dan lisensi tetap berarti percobaan kedua tidak dikenai biaya.

Apa yang Anda butuhkan

  • PC Windows yang menjalankan CapSkip 4.0.0 atau lebih baru, rilis yang menambahkan hCaptcha. Langkah instalasi ada di panduan penyiapan.
  • SDK .NET 8 atau lebih baru, dan paket NuGet CapSkip 1.6.0 atau lebih baru, rilis pertama dengan HCaptchaAsync. Paket ini menargetkan netstandard2.0 dan bergantung pada System.Text.Json 8.0.5. Saya hanya memasang satu SDK, 10.0.100, dan menjalankan semuanya dengan CapSkip 1.6.0 pada net10.0 dan net8.0.
  • Prompt PowerShell, dan halaman yang boleh Anda otomatisasi yang menampilkan widget hCaptcha, beserta sitekey-nya.
  • Sebuah alamat untuk CapSkip. Mode Local hanya menjawab di 127.0.0.1, untuk program di PC itu. Mode Server juga mendengarkan di jaringan atau IP publik Anda, sehingga program di mesin lain dapat memanggil API yang sama. Anda mengatur modenya di pengaturan koneksi dan pilihan itu tersimpan di sana.

Pengaturan pengujian: paket CapSkip 1.6.0 yang asli dari NuGet dan dua server mock buatan saya sendiri, tanpa situs hCaptcha sungguhan. Satu mock berperan sebagai aplikasi CapSkip dan mengikuti bagian hCaptcha pada Dokumentasi API. Mock lainnya berperan sebagai halaman pendaftaran dan bisa bertindak sebagai proxy. Aturannya (cookie sesi, Referer atau Origin, User-Agent yang dibawa token) adalah pilihan saya, bukan aturan hCaptcha. Cara situs sungguhan memeriksa token dijelaskan dalam dokumentasi developer hCaptcha. Saya membaca source paket pada tag v1.6.0 dan tidak mengirim apa pun ke aplikasi CapSkip yang asli, jadi saya tidak punya waktu pemecahan sungguhan.

Langkah 1: buat proyek dan instal CapSkip

Buat proyek console dan instal paketnya. Proyek baru mengaktifkan implicit usings dan nullable reference types, dan kode ini memerlukan keduanya. Tanpa versi, dotnet add package mengambil rilis terbaru, yaitu 1.6.0 saat saya menjalankannya.

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

Hapus semua isi Program.cs, termasuk baris Console.WriteLine dari template, lalu tempel ketiga blok C# di bawah ini secara berurutan, mulai dari Langkah 2. Hanya blok pertama yang memiliki baris using, dan tidak ada yang berjalan sebelum blok terakhir terpasang.

Langkah 2: panggil HCaptchaAsync

Sitekey ada di halaman. Sebagian besar halaman mencetaknya sebagai data-sitekey pada container widget, dan widget yang dibangun skrip meneruskannya sebagai opsi sitekey dari hcaptcha.render(). HCaptchaAsync menerima sitekey, alamat halaman, dictionary opsi, dan sebuah CancellationToken. Overload bertipenya menerima bool bernama invisible sebelum opsi: true mengirim invisible=1 dan false tidak mengirim apa pun. Situs Enterprise yang mengatur rqdata mendapatkan nilainya di bawah key data, baru untuk setiap task. Proxy adalah objek Proxy dengan type (HTTP, HTTPS, SOCKS5, atau SOCKS5H) dan string login:password@host:port. Tuliskan port secara eksplisit, karena Uri.Authority membuang port default. Pada eksekusi mock, invisible, data, dan proxy sampai di in.php.

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

Hasilnya memiliki empat properti yang perlu diketahui. Token dan Code berisi string yang sama. RespKey adalah nilai kedua yang diberikan hCaptcha kepada widget, yang dikembalikan hcaptcha.getRespKey() di browser. Sebagian besar situs tidak pernah membacanya, dan nilainya string kosong, bukan null, jika tidak ada. UserAgent adalah string User-Agent dari browser yang memperoleh token. Nilainya tetap null jika balasan tidak menyebut apa pun, dan dalam kondisi itu Langkah 3 tidak mengirim User-Agent dan situs mock saya menolak POST-nya.

SDK memeriksa argumen Anda sebelum permintaan apa pun. Sitekey kosong, alamat halaman yang bukan http atau https absolut, nilai invisible selain 0, 1, true, atau false, dan parameter apa pun yang tidak diterima API hCaptcha CapSkip, termasuk domain milik 2Captcha, memunculkan ValidationException, dan mock tidak menerima task untuk satu pun dari semuanya. Selain itu, SDK mengirim task dan melakukan polling seketika, lagi setelah 0.25 detik, lalu dengan jeda yang berlipat ganda hingga 5 detik. Terhadap mock, polling terjadi dalam selisih 0.15 detik dari 0, 0.25, 0.75, 1.75, 3.75, 7.75, dan 12.75 detik setelah submit.

Penantian berakhir dengan TimeoutException setelah RecaptchaTimeout, 300 detik kecuali Anda memberikan recaptchaTimeout ke constructor atau opsi timeout ke satu panggilan. hCaptcha mendapat timeout yang lebih panjang itu karena widget dilewati di browser sungguhan, dan dokumentasi menyebut satu pemecahan biasanya memakan 10 sampai 30 detik. Batas waktu diperiksa di antara polling: dengan timeout 22 detik dan mock yang tidak pernah menjawab, exception muncul 22.9 detik setelah panggilan.

Setiap exception yang dilempar SDK mewarisi CapSkipError. ValidationException adalah penolakan lokal. NetworkException berarti permintaan gagal atau CapSkip tidak menjawab dengan HTTP 200. ApiException berarti CapSkip membalas dengan error, dan pesannya adalah seluruh body balasan (JSON setelah polling dan teks polos setelah submit, terhadap mock), jadi kodenya berada di dalamnya. Dua jebakan menyusul. TimeoutException juga ada di System, dan implicit usings mengimpor System, jadi TimeoutException saja di samping using CapSkip gagal dengan CS0104, referensi yang ambigu. Blok pertama memberi alias SolverTimeout pada class milik SDK. Dan CancellationToken yang aktif selama submit muncul sebagai NetworkException yang membungkus pembatalan, sedangkan yang aktif selama polling muncul sebagai TaskCanceledException.

Langkah 3: kirim formulir dari handler tersendiri

Paket menyimpan HttpClient-nya sendiri untuk CapSkip, jadi tidak ada yang di bawah ini berbagi dengannya. POST formulir berbeda, karena cookie jar dimiliki handler dan dua pendaftaran tidak boleh berbagi cookie. Site.SignUp membuat handler dengan CookieContainer sendiri, membungkus klien di sekelilingnya, dan membuang keduanya di akhir. Menurut pedoman HttpClient dari Microsoft, cookie container yang terpisah adalah alasan untuk memakai lebih dari satu instance.

Pemuatan halaman datang lebih dulu, sehingga cookie halaman ikut kembali bersama POST. Kedua permintaan membawa User-Agent dari hasil. HttpClient tidak mengirim apa pun kecuali Anda mengaturnya: dengan baris itu dihapus, situs mock, yang mencocokkannya dengan token, melihat User-Agent kosong dan menolak setiap POST. POST juga membawa Referer dan Origin, karena HttpClient tidak mengirim keduanya. Situs mock saya mewajibkan salah satunya, aturan yang saya pilih, dan saya tidak mengukur berapa banyak situs sungguhan yang melakukannya. Token dimasukkan ke h-captcha-response dan g-recaptcha-response. Token hanya berfungsi sekali dan, menurut dokumentasi, bertahan sekitar dua menit, jadi kirim segera.

Proxy bersifat opsional, meskipun dokumentasi memperingatkan bahwa aliran pemecahan yang stabil dari satu IP adalah hal yang ditangkap oleh rate limit hCaptcha. Uri yang Anda berikan dikirim ke CapSkip melalui Solve.Run dan ke handler ini, karena dokumentasi meminta situs ketat menerima formulir dari alamat yang sama dengan pemecahan. WebProxy mengabaikan login di dalam alamat, jadi handler mengangkatnya ke NetworkCredential. Mock proxy yang meminta kredensial Basic menerimanya, bahkan dengan tanda persen di kata sandi. Saya tidak menjalankan bagian situs melalui SOCKS.

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

Langkah 4: jalankan seluruh loop hCaptcha di C#

Blok terakhir adalah metode Main. Ubah konstanta PageUrl dan SiteKey (seperti yang ditempel, kode meminta example.com, yang tidak punya widget), lalu jalankan dotnet run di folder proyek. Kode membuat hingga tiga percobaan di bawah satu CancellationTokenSource, dan setiap percobaan memiliki penantian 300 detik milik SDK di dalamnya. Menurut pembacaan saya atas source CapSkip 4.1.0, satu task bisa berjalan hingga 300 detik sebelum CapSkip menyebutnya tidak dapat dipecahkan, setelah menunggu hingga 250 detik untuk slot Max. Threads, jadi di bawah beban, naikkan recaptchaTimeout.

ERROR_CAPTCHA_UNSOLVABLE adalah satu-satunya kode di mana task baru yang langsung dikirim bisa membantu, menurut dokumentasi. ERROR_NO_SLOT_AVAILABLE, yang diterima key yang melewati rate limit-nya, dicoba ulang setelah jeda 5 detik. Setiap kode lain mengakhiri eksekusi, begitu juga ValidationException, karena argumen yang sama akan ditolak lagi. Situs yang menjawab 400 atau lebih tinggi mendapat task baru dan token baru. Status 200 tidak selalu berarti berhasil, karena banyak situs menaruh error di dalam halaman, jadi ganti uji status dengan sesuatu yang hanya muncul pada keberhasilan. Ketika HttpClient.Timeout 30 detik untuk POST formulir habis, catch terakhir melaporkannya.

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

Terhadap mock, yang tidak membuktikan apa pun tentang situs sungguhan, setiap baris menghasilkan hal yang sama pada net10.0 dan net8.0.

Pengaturan mockYang dilakukan program
Token siap pada polling ke-7, default SDKSatu task, polling dalam selisih 0.15 detik dari 0, 0.25, 0.75, 1.75, 3.75, 7.75, dan 12.75 detik setelah submit, lalu 200
Dua penolakan (ERROR_CAPTCHA_UNSOLVABLE, atau ERROR_NO_SLOT_AVAILABLE dengan jeda), lalu berhasil; atau penolakan setiap kali200 pada task ketiga; atau tiga baris percobaan, exit code 1, dan tidak ada permintaan ke situs
Situs menolak POST formulir pertama dengan 403Task dan token baru, lalu 200
Sitekey kosongSatu baris ValidationException dan exit code 1, tanpa task di mock
ERROR_ZERO_BALANCE, ERROR_PROXY_CONNECT_REFUSED, atau ERROR_RECAPTCHA_INVALID_SITEKEYMasing-masing menghentikan eksekusi setelah satu task
Panggilan invisible, panggilan Enterprise, proxy dengan atau tanpa loginin.php melihat invisible=1, nilai data, atau proxytype HTTP beserta alamatnya, dan permintaan ke situs tiba melalui mock proxy
Sebuah apiKey di constructor, validasi key aktifKey sampai ke submit dan setiap polling. Key default mendapat ERROR_KEY_DOES_NOT_EXIST
recaptchaTimeout 22 dan mock yang tidak pernah menjawabTimeoutException, 22.9 detik setelah panggilan
Anggaran waktu 2 detik, saat menunggu polling atau in.php yang menggantungPesan anggaran waktu setelah 2.0 detik pada kedua kasus
Tidak ada yang mendengarkan di CapSkip atau di situs; halaman situs yang tidak pernah menjawabNetworkException; permintaan gagal; pesan 30 detik setelah 30 detik
Tiga pendaftaran sekaligusTiga task, tiga sesi, tiga User-Agent pada POST, tiga jawaban 200

Dua snippet mencakup sisanya. Yang pertama mengganti panggilan untuk widget invisible atau Enterprise. Yang kedua mendaftarkan beberapa akun sekaligus: ganti baris di antara kurung kurawal try terluar di Main dengan snippet itu, dan pertahankan baris catch. Setiap pendaftaran membuat handler sendiri, dan mock memberi setiap task User-Agent sendiri, jadi kekeliruan akan menggagalkan POST. Snippet tidak memberikan rqData, jadi untuk situs Enterprise baca nilai baru di dalam lambda.

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

Kesalahan umum

Apa yang Anda lihatPenyebabPerbaiki
ValidationExceptionDitolak sebelum dikirim: sitekey kosong, alamat halaman yang bukan http atau https absolut, nilai invisible yang buruk, atau parameter seperti domain yang tidak diterima API hCaptchaPerbaiki argumennya. Mencoba ulang tidak akan membantu
ERROR_RECAPTCHA_INVALID_SITEKEYSitekey ditolak untuk halaman ituSalin ulang data-sitekey dan periksa alamat halaman
ERROR_CAPTCHA_UNSOLVABLECapSkip tidak berhasil melewati widgetLoop mengirim task baru, hingga tiga kali
ERROR_PROXY_FORMAT atau ERROR_PROXY_CONNECT_REFUSEDCapSkip tidak dapat membaca nilai proxy, atau menjangkau target melaluinya (kasus kedua hanya saya simulasikan)Berikan Uri dengan skema, host, dan port, lalu uji proxy secara terpisah
ERROR_WRONG_METHODCapSkip yang lebih lama dari 4.0.0 mungkin tidak mengenal metode hCaptcha (tidak diuji)Perbarui CapSkip ke 4.0.0 atau lebih baru
ERROR_NO_SLOT_AVAILABLE, ERROR_ZERO_BALANCE, atau ERROR_IP_NOT_ALLOWEDHanya dengan API Key Validation aktif. Menurut pembacaan saya atas source 4.1.0: key melewati rate limit-nya, kehabisan kredit, atau key satu perangkat dipakai di tempat lainLoop menjeda dan mencoba ulang yang pertama. Ubah pengaturan key di CapSkip untuk yang lain
ERROR_WRONG_USER_KEY atau ERROR_KEY_DOES_NOT_EXISTAPI Key Validation aktif, dan apiKey di panggilan constructor Anda hilang atau salahBerikan apiKey yang valid di baris CapSkipClient
TimeoutExceptionTidak ada token yang tiba dalam recaptchaTimeout. Balasan kosong dianggap belum siap, jadi SDK terus melakukan pollingPeriksa Monitor CapSkip untuk task itu, lalu naikkan recaptchaTimeout
NetworkException saat panggilan dimulaiTidak ada program yang menjawab di host dan port itu. Inner exception-nya adalah HttpRequestExceptionJalankan CapSkip, lalu salin host dan port-nya dari pengaturan koneksi ke panggilan constructor Anda
Error CS0104: referensi ambiguTimeoutException ada di System dan di CapSkip. ValidationException bentrok dengan cara yang sama setelah Anda mengimpor System.ComponentModel.DataAnnotationsBeri alias pada class milik SDK, seperti yang dilakukan blok pertama, atau tulis nama lengkapnya
Token yang tampak valid ditolakDokumentasi menyebut token yang dipakai ulang, yang lebih tua dari sekitar dua menit, dan User-Agent selain yang ada di hasil. Mock saya juga menolak User-Agent, Referer, Origin, atau cookie sesi yang hilang. Status 407 berarti proxy meminta loginKirim setiap token sekali saja, segera, dari Site.SignUp

Menggunakan CapSkip di server

Dalam mode Server, CapSkip mendengarkan di alamat jaringan Anda atau IP publik, jadi kode hCaptcha di C# yang sama berfungsi dari PC lain, Windows VPS, atau platform hosting. Mode Server mengharuskan CapSkip berjalan sebagai administrator, dan panduan penyiapan menyarankan IP publik statis. Ubah host di baris CapSkipClient ke alamat server dan tidak ada hal lain yang berubah.

CapSkip membuka portnya untuk semua alamat ketika mode Server dimulai, jadi agar hanya mesin yang Anda harapkan yang bisa mengakses, tambahkan aturan blokir Windows Firewall untuk yang lain, dan aktifkan API Key Validation dengan apiKey di baris CapSkipClient. Pemecahan kini berjalan di server, jadi hCaptcha melihat jaringan mesin itu.

FAQ

Bagaimana cara memecahkan hCaptcha invisible atau Enterprise di C#?

Dengan panggilan HCaptchaAsync yang sama. Untuk widget yang data-size-nya invisible, berikan true untuk bool invisible. Untuk situs Enterprise yang mengatur rqdata, berikan nilainya di bawah key data dan baca yang baru untuk setiap task, karena dokumentasi menyebut situs menerbitkannya untuk satu challenge. Snippet pertama di Langkah 4 menunjukkan keduanya.

Bisakah saya mendaftarkan SDK dengan IHttpClientFactory?

Tidak ada yang perlu didaftarkan. Paket melakukan panggilannya ke CapSkip dengan satu HttpClient statis miliknya sendiri. Jauhkan Site.SignUp dari factory juga: pedoman Microsoft memperingatkan bahwa handler yang di-pool berbagi CookieContainer mereka.

Mengapa situs menolak token yang diberikan CapSkip kepada saya?

Situs yang ketat bisa menolak token yang dinilai hCaptcha berisiko, bahkan ketika widget berhasil dilewati, dan situs Enterprise adalah kasus yang paling umum. Dokumentasi menyarankan High score mode, di pengaturan hCaptcha. Mode ini memerlukan Google Chrome di PC CapSkip, dan menurut pembacaan saya atas source 4.1.0, mode ini aktif secara default. Saya tidak punya situs ketat untuk mengujinya.

Memecahkan hCaptcha di C# berpusat pada satu panggilan HCaptchaAsync, loop yang hanya mencoba ulang kode yang layak dicoba ulang, dan POST formulir dari handler dengan cookie dan User-Agent yang benar. CapSkip adalah bypass captcha lokal dengan lisensi tetap, jadi percobaan lagi hanya memakan waktu yang dibutuhkannya. Halaman pemecah CAPTCHA C# membahas tipe CAPTCHA lain di .NET, dan Demo hCaptcha menampilkan widget yang berhasil dilewati.