Cara Memecahkan CaptchaFox di C# Tanpa Token yang Ditolak

Untuk memecahkan CaptchaFox di C#, panggil CaptchaFoxAsync dengan sitekey dan URL halaman, masukkan token yang dikembalikan ke field form cf-captcha-response, lalu kirim permintaan itu dengan user agent yang dikembalikan CapSkip bersama token tersebut. Bagian terakhir inilah tempat sebagian besar integrasi gagal. Token CaptchaFox terikat pada browser yang menghasilkannya, dan user agent yang tidak cocok adalah alasan paling umum token yang benar ditolak, padahal pemecahannya sendiri berhasil. CapSkip menambahkan CaptchaFox pada versi 1.4.0. Panduan ini membahas cara menemukan key, pemanggilannya, pengirimannya, dan beberapa pengaturan yang menentukan apakah token diterima.
Apa yang Anda butuhkan
- CapSkip 1.4.0 atau lebih baru yang berjalan di komputer Windows. Dukungan CaptchaFox hadir pada rilis tersebut, bersama Friendly Captcha dan Capy Puzzle.
- Paket CapSkip .NET versi 1.3.0 atau lebih baru, yaitu rilis yang menambahkan CaptchaFoxAsync. Paket ini menargetkan .NET Standard 2.0 dan bergantung pada System.Text.Json 8, sehingga didukung di .NET Framework 4.6.2 ke atas dan di .NET 6 ke atas. Contoh kodenya memakai top-level statements dan implicit usings dari proyek console .NET 6, jadi jalankan di .NET 6 atau lebih baru.
- Dua nilai dari halaman target: sitekey dan URL halaman tempat widget berjalan. Langkah 1 menunjukkan letak key tersebut, dan satu detail lagi dari halaman itu menentukan sebuah pengaturan opsional.
- Sebuah alamat untuk pemecah CAPTCHA. Mode Local menjawab di 127.0.0.1 hanya untuk perangkat itu; mode Server mendengarkan di alamat jaringan atau IP publik Anda sehingga mesin lain dapat memanggilnya melalui API. Keduanya ada di pengaturan koneksi, dan salah satu bagian di bawah membahas kapan Anda perlu beralih.
# dotnet add package CapSkip dotnet add package CapSkip
Langkah 1: temukan sitekey dan sumber widget
Semua yang Anda butuhkan untuk memecahkan CaptchaFox di C# diambil dari halaman target. Sitekey bersifat publik, sama untuk setiap pengunjung, dan secara konvensi diawali sk_. Situs menaruhnya di salah satu dari tiga tempat, dan Anda hanya perlu menemukan salah satunya.
- Pada elemen container, ketika widget merender dirinya sendiri: sebuah div dengan class captchafox dan atribut data-sitekey. Mode tersembunyi, yang tidak menampilkan apa pun sampai form dikirim, memakai div yang sama dengan data-mode bernilai hidden, jadi key-nya juga ada di sana.
- Di dalam opsi pemanggilan captchafox.render, ketika halaman membangun widget dari skripnya sendiri. Pemanggilan render juga bisa mengaktifkan mode tersembunyi, dengan key berada tepat di sampingnya.
- Di tab Network, ketika tidak satu pun dari keduanya muncul di HTML yang disajikan. Temukan permintaan ke api.captchafox.com; key-nya adalah segmen path setelah /captcha/.
Selagi kode sumber halaman terbuka, lihat tag script yang memuat widget. Widget ini dimuat ke halaman dari dua tempat, dan tempat yang dimuat sebuah situs menentukan bentuk token yang diharapkan situs itu kembali.
| Halaman memuat widget dari | Token yang dikembalikan | Apa yang perlu diberikan |
|---|---|---|
| https://cdn.captchafox.com/, widget standar yang dipakai sebagian besar situs | Token biasa | Tidak ada tambahan; ini default-nya |
| Paket di bawah https://s.uicdn.com/mampkg/, yang disematkan beberapa platform | Token yang diawali MAM_ | Path paket lengkap dari tag script, sebagai opsi api_server |
Kesalahan di sini terjadi diam-diam. Jika Anda mengirim sumber yang salah, pemecahan tetap berhasil dan mengembalikan token, hanya saja dalam format yang tidak akan diterima situs, sehingga kegagalannya baru muncul belakangan sebagai form yang ditolak, bukan sebagai error yang bisa Anda tangkap.
Langkah 2: pemanggilan CaptchaFoxAsync
Metode ini menerima sitekey, URL halaman, dan dictionary opsi yang bersifat opsional. Untuk widget standar, Anda hanya butuh dua yang pertama.
// dotnet add package CapSkip
using CapSkip;
var solver = new CapSkipClient(host: "127.0.0.1", port: 8080);
// The sitekey from the widget, and the page the widget runs on.
var result = await solver.CaptchaFoxAsync(
"YOUR_SITEKEY",
"https://example.com/signup");
Console.WriteLine(result.Token); // goes in cf-captcha-response
Console.WriteLine(result.UserAgent); // send this as the User-AgentBaca properti Token. Properti Code berisi string yang sama, tetapi Token dinamai sesuai field tujuannya. UserAgent adalah identitas browser yang menerbitkan token, yaitu browser milik CapSkip sendiri, bukan apa pun yang Anda kirim. SDK membiarkannya null ketika sebuah pemecahan tidak melaporkan user agent, alih-alih mengarang nilai.
URL halaman lebih penting di sini dibanding pada kebanyakan tipe lain. CaptchaFox mendaftarkan setiap key terhadap daftar domain yang diizinkan dan memeriksa host sebelum menerbitkan apa pun, sehingga key yang dikirim dengan halaman yang salah ditolak secara permanen, bukan sesekali. CapSkip langsung melaporkan kasus itu alih-alih mencobanya ulang, karena percobaan ulang tidak akan membantu. Kirim halaman tempat widget benar-benar berjalan, bukan hasil pencarian, redirect, atau tautan yang dipendekkan.
Situs yang memuat paket MAM
Jika Langkah 1 menemukan skrip di bawah s.uicdn.com, salin path paketnya persis seperti yang ditulis halaman dan berikan sebagai api_server. Token kemudian kembali dengan awalan MAM_ yang diharapkan situs.
// Only for pages whose script tag loads the MAM build.
var result = await solver.CaptchaFoxAsync(
"YOUR_SITEKEY",
"https://example.com/signup",
new Dictionary<string, object?>
{
["api_server"] =
"https://s.uicdn.com/mampkg/@mamdev/core.frontend.libs.captchafox/",
});Dictionary opsi menerima api_server, proxy dan useragent, beserta proxytype dan timeout per panggilan dalam detik. Opsi useragent ada demi kompatibilitas dengan layanan lain dan tidak diterapkan, karena CapSkip memecahkan di browser sungguhan dengan identitas browser itu sendiri yang konsisten. Key yang tidak dikenal, atau sitekey maupun URL halaman yang kosong, memicu ValidationException sebelum permintaan dibuat.
Langkah 3: kirim dengan user agent yang menerbitkan token
Inilah langkah yang membedakan token yang diterima dari token yang ditolak. CaptchaFox menilai browser yang menjalankan widget, dan token yang diterbitkannya milik browser tersebut. HttpClient sama sekali tidak mengirim header User-Agent kecuali Anda menambahkannya, dan string desktop yang ditulis langsung di kode sama salahnya, jadi salin user agent yang dikembalikan CapSkip ke permintaan yang membawa token.
// http is your HttpClient; result comes from Step 2.
var request = new HttpRequestMessage(HttpMethod.Post, "https://example.com/signup")
{
Content = new FormUrlEncodedContent(new Dictionary<string, string>
{
["email"] = "[email protected]",
["cf-captcha-response"] = result.Token!,
}),
};
// The token is bound to the browser that produced it.
if (result.UserAgent is { } ua)
request.Headers.TryAddWithoutValidation("User-Agent", ua);
var response = await http.SendAsync(request);TryAddWithoutValidation dipakai dengan sengaja. UserAgent.ParseAdd yang lebih ketat memeriksa string terhadap tata bahasa header dan melempar FormatException ketika keduanya tidak cocok, sedangkan nilai ini harus dikirim byte demi byte, apa pun isinya. Setel per permintaan, bukan di header default klien, agar satu HttpClient bisa membawa token dari beberapa pemecahan.
Dua aturan lagi berasal dari cara CaptchaFox memeriksa token di sisi situs. Dokumentasi CaptchaFox sendiri menyatakan bahwa setiap token hanya dapat diverifikasi sekali, dan hanya dalam waktu singkat, jadi pecahkan saat Anda hendak mengirim, kirim token sekali saja, dan pecahkan lagi jika form ditinggalkan lalu dilanjutkan kembali. Selain itu, perlakukan token sebagai string opaque: token diperiksa terhadap sesi yang menghasilkannya, jadi memotong atau meng-encode ulang token akan merusaknya. Sebagian integrasi mengirimnya di body JSON, bukan lewat form post, jadi kirim form sekali secara manual dengan DevTools terbuka, lalu tiru persis apa yang dikirim halaman itu.
Langkah 4: proxy, tipe challenge, dan timeout
CaptchaFox menilai jaringan tempat widget berjalan, bukan hanya browsernya. Satu alamat sudah cukup untuk pengujian dan pemecahan sesekali, tetapi pemecahan berulang dari alamat itu mendorongnya ke arah challenge interaktif lalu ke arah penolakan. Begitu Anda memecahkan dalam volume berapa pun, konfigurasikan pool proxy di CapSkip, atau kirim proxy per permintaan. Jika Anda melakukannya, kirim form melalui alamat keluar yang sama juga, agar token dan form tiba dari satu jaringan. Verifikasi CaptchaFox memungkinkan situs meneruskan alamat IP pengunjung bersama token, dan itu satu alasan lagi untuk menjaga keduanya di satu rute.
// using System.Net; for WebProxy and NetworkCredential.
// Same exit address for the solve and the submit.
var result = await solver.CaptchaFoxAsync("YOUR_SITEKEY", pageUrl,
new Dictionary<string, object?>
{
["proxy"] = new Proxy("HTTP", "login:[email protected]:8080"),
});
var http = new HttpClient(new HttpClientHandler
{
Proxy = new WebProxy("http://1.2.3.4:8080")
{
Credentials = new NetworkCredential("login", "password"),
},
});Anda tidak memilih challenge mana yang muncul. Sebagian besar pemecahan tidak menampilkan apa pun, karena bukti dari browser sudah lolos dengan sendirinya, dan CapSkip juga menyelesaikan slider ketika CaptchaFox memintanya. Dua challenge cadangan yang jarang muncul tidak dipecahkan.
| Tipe challenge | Seberapa sering | Terpecahkan |
|---|---|---|
| Invisible, tanpa ada yang ditampilkan | Biasanya | Ya |
| Teka-teki geser | Terkadang | Ya |
| Pilih gambar | Jarang | Tidak, dilaporkan tidak bisa dipecahkan |
| Audio | Jarang | Tidak, dilaporkan tidak bisa dipecahkan |
Laporan tidak bisa dipecahkan datang sebagai ApiException, dengan cepat, alih-alih menunggu sampai timeout. Percobaan ulang biasanya memunculkan challenge yang berbeda, jadi anggap itu alasan untuk mengirim ulang, bukan tanda key yang rusak. Contoh lengkap di bawah hanya mencoba ulang kasus itu, sebanyak dua kali, karena ApiException juga mencakup error yang tidak bisa diperbaiki dengan percobaan ulang, seperti API key yang salah.
CaptchaFoxAsync melakukan polling dengan recaptchaTimeout, 300 detik secara default, karena ini adalah sesi browser sungguhan dan berjalan lebih lama ketika slider ditampilkan. CapSkip juga menjalankan timer-nya sendiri: sebuah tugas bisa menunggu hingga 250 detik (Wait Timeout) untuk salah satu dari 10 thread CaptchaFox (Max. Threads), dan satu percobaan mendapat 150 detik (Row Timeout). Karena itu, percobaan yang melambat karena proxy gagal lebih dulu di dalam CapSkip, dan timeout SDK yang lebih panjang tidak memberinya waktu tambahan. Dengan Retries pada nilai default 0 dan ada thread yang kosong, kegagalan itu sampai ke Anda sebagai ApiException jauh sebelum 300 detik milik SDK habis; jika tugas lama mengantre, SDK bisa mencapai batasnya lebih dulu dan justru melempar CapSkip.TimeoutException.
Timeout SDK hanya perlu diperpanjang saat Anda menaikkan Retries (0-3) di pengaturan CaptchaFox pada CapSkip, karena setiap percobaan ulang tambahan bisa menambah waktu hingga satu Row Timeout lagi pada satu pemanggilan. Dalam hal itu, berikan timeout yang lebih panjang di dictionary opsi, atau naikkan recaptchaTimeout di konstruktor.
Menjalankan pemecah di tempat lain
Contoh kode memakai 127.0.0.1 karena itu benar selama kode Anda dan CapSkip berada di mesin yang sama. Begitu aplikasi .NET berjalan di tempat lain, seperti container, build agent, VPS atau app service, loopback menunjuk ke mesin yang salah dan pemecahan pertama melempar NetworkException. Alihkan CapSkip ke mode Server dan ia akan mendengarkan di alamat jaringan atau IP publik Anda, sehingga semua lingkungan itu dapat menjangkaunya melalui API. Gunakan IP publik statis jika rutenya melewati internet, aktifkan validasi API key, dan batasi port hanya untuk alamat yang Anda harapkan dengan aturan Windows Firewall. Mesinnya tetap mesin Windows milik Anda sendiri, dan pemecahannya tetap tanpa kuota.
Klien tidak membaca variabel lingkungan dengan sendirinya. Baca CAPSKIP_HOST dan CAPSKIP_API_KEY di kode Anda sendiri dan berikan ke konstruktor, seperti pada contoh lengkap, agar build yang sama bisa berjalan di komputer Anda maupun di server.
Contoh lengkap yang berfungsi
// dotnet add package CapSkip
using System.Text.RegularExpressions;
using CapSkip;
// Copied by hand from the script tag, for pages that load the MAM build.
const string MamPackage = "https://s.uicdn.com/mampkg/@mamdev/core.frontend.libs.captchafox/";
var pageUrl = "https://example.com/signup";
var http = new HttpClient();
var solver = new CapSkipClient(
apiKey: Environment.GetEnvironmentVariable("CAPSKIP_API_KEY") ?? "capskip",
host: Environment.GetEnvironmentVariable("CAPSKIP_HOST") ?? "127.0.0.1",
port: 8080);
// Read the sitekey off the captchafox container, in either attribute order.
var html = await http.GetStringAsync(pageUrl);
var widget = Regex.Match(html,
"<[^>]*class=\"(?:[^\"]*\\s)?captchafox(?:\\s[^\"]*)?\"[^>]*>").Value;
var sitekey = Regex.Match(widget, "data-sitekey=\"([^\"]+)\"").Groups[1].Value;
// MAM pages may carry the key in the script src instead.
if (sitekey.Length == 0)
sitekey = Regex.Match(html,
"captchafox[^\"]*/api\\.js\\?key=([^\"&]+)").Groups[1].Value;
if (sitekey.Length == 0)
throw new InvalidOperationException("No sitekey in the HTML; find it in DevTools.");
// The same CDN serves other packages, so match the captchafox one.
var options = new Dictionary<string, object?>();
if (html.Contains("mampkg/@mamdev/core.frontend.libs.captchafox"))
options["api_server"] = MamPackage;
try
{
// Image-select and audio come back unsolvable; a retry redraws.
// Other API errors, such as a wrong key, are not worth repeating.
SolveResult? result = null;
for (var attempt = 1; result is null; attempt++)
{
try
{
result = await solver.CaptchaFoxAsync(sitekey, pageUrl, options);
}
catch (ApiException ex) when (attempt < 3 && ex.Message.Contains("UNSOLVABLE"))
{
Console.WriteLine($"attempt {attempt}: {ex.Message}");
}
}
var request = new HttpRequestMessage(HttpMethod.Post, pageUrl)
{
Content = new FormUrlEncodedContent(new Dictionary<string, string>
{
["email"] = "[email protected]",
["cf-captcha-response"] = result.Token!,
}),
};
if (result.UserAgent is { } ua)
request.Headers.TryAddWithoutValidation("User-Agent", ua);
// Post wherever the form's action attribute points.
var response = await http.SendAsync(request);
Console.WriteLine($"{(int)response.StatusCode}, UA sent: {result.UserAgent is not null}");
}
catch (CapSkip.ValidationException ex)
{
// An option the method does not take.
Console.WriteLine($"not sent: {ex.Message}");
}
catch (CapSkip.TimeoutException)
{
Console.WriteLine("gave up waiting; recaptchaTimeout is 300 seconds");
}
catch (CapSkipError ex)
{
// The third unsolvable result, a refused key, or CapSkip unreachable.
Console.WriteLine($"gave up: {ex.Message}");
}Regex membatasi nama class dengan spasi, sehingga elemen seperti captchafox-wrapper tidak ikut cocok secara tidak sengaja, dan regex mengharapkan atribut dengan tanda kutip ganda, seperti cara snippet resmi CaptchaFox menuliskannya. Jika pemecahan langsung gagal setiap kali dijalankan, periksa URL halaman sebelum hal lain: key yang dipakai di luar domain terdaftarnya gagal dengan cara yang sama setiap kali. Ketika regex tidak menemukan apa pun, halaman merender widget dari skrip, dan key-nya ada di pemanggilan render atau di tab Network seperti dijelaskan di Langkah 1. Endpoint mentah di balik metode ini didokumentasikan di referensi API, dan setiap metode lain yang disediakan paket ini tercantum di halaman pemecah CAPTCHA C#.
Kesalahan umum dan artinya
| Apa yang Anda lihat | Penyebab | Perbaiki |
|---|---|---|
| Situs menolak token yang dikembalikan CapSkip sebagai berhasil dipecahkan | Permintaan dikirim dengan User-Agent yang berbeda dari yang dipakai saat token diterbitkan | Kirim result.UserAgent pada permintaan pengiriman, byte demi byte |
| Ditolak padahal user agent sudah cocok | Situs memuat paket MAM tetapi pemecahan memakai widget default, atau sebaliknya | Baca tag script dan setel api_server agar sesuai dengannya |
| Token berawalan MAM_ yang ditolak situs | api_server disetel untuk halaman yang memuat widget standar | Hapus opsi itu dan pakai default |
| ApiException langsung muncul, setiap kali, untuk satu key | URL halaman berada di luar domain tempat key didaftarkan | Kirim halaman tempat widget berjalan, bukan redirect atau hasil pencarian |
| ApiException sesekali yang menyatakan CAPTCHA tidak bisa dipecahkan | CaptchaFox menampilkan challenge pilih gambar atau audio | Kirim ulang; percobaan berikutnya biasanya memunculkan challenge yang berbeda |
| Challenge makin sering, lalu penolakan, seiring berjalannya proses | Setiap pemecahan berasal dari satu alamat dan CaptchaFox menilai jaringannya | Sebarkan pemecahan ke pool proxy, dan kirim melalui alamat keluar yang sama |
| Token yang berhasil sekali gagal pada pengiriman kedua | Setiap token hanya bisa diverifikasi sekali dan cepat kedaluwarsa | Pecahkan ulang untuk setiap pengiriman, dan langsung kirim |
| ValidationException sebelum apa pun terkirim | Sitekey atau URL halaman kosong, atau opsi berisi key yang tidak diterima metode ini | Pastikan regex menemukan elemennya, dan buang opsi yang disebut dalam pesan |
| NetworkException pada pemecahan pertama | CapSkip tidak berjalan, atau host dan port-nya salah | Jalankan CapSkip, lalu periksa apakah ia harus berada di mode Local atau mode Server |
| Build gagal karena TimeoutException yang ambigu | CapSkip dan System sama-sama mendefinisikan nama pendek itu | Tulis CapSkip.TimeoutException secara lengkap, atau tangkap CapSkipError |
FAQ
Mengapa CaptchaFox membutuhkan user agent padahal kebanyakan tipe CAPTCHA tidak?
Karena CaptchaFox menilai browser, bukan meminta seseorang membaca apa pun. Token adalah putusan layanan itu atas satu browser tertentu, jadi token hanya masuk akal jika kembali dari browser tersebut. Halaman challenge Cloudflare Turnstile bekerja dengan cara yang sama, dan sisi C#-nya dibahas di panduan halaman challenge Turnstile. CapSkip mengembalikan user agent tepat untuk kedua tipe itu, dan itu petunjuk yang andal tentang di mana user agent berpengaruh.
Bisakah aplikasi .NET di platform hosting menjangkau pemecah CAPTCHA?
Bisa. Alihkan CapSkip ke mode Server di pengaturan koneksi agar ia mendengarkan di alamat jaringan, bukan di loopback, baca alamat itu dari CAPSKIP_HOST di kode Anda, lalu berikan ke klien. Container host, VPS, CI agent dan layanan aplikasi terkelola semuanya terhubung dengan cara yang sama, melalui API HTTP yang sama. Gunakan IP publik statis dengan aturan firewall jika rutenya melewati internet. Pemecah CAPTCHA tetap berada di perangkat milik Anda, jadi tidak ada yang berubah soal lisensi atau jumlah pemecahan.
Apa bedanya dengan memecahkan Friendly Captcha di C#?
Keduanya hadir di CapSkip 1.4.0 dan keduanya memakai timeout 300 detik, dan kurang lebih hanya itu kesamaannya. Pada Friendly Captcha, keputusannya adalah versi protokol mana yang dijalankan situs, dan token tidak terikat pada user agent. Pada CaptchaFox, keputusannya adalah sumber widget mana yang dimuat situs dan user agent mana yang membawa token. Sisi Friendly Captcha dibahas di panduan Friendly Captcha di C#.
Bisakah saya memecahkan beberapa token CaptchaFox sekaligus?
Bisa. Klien ini async, jadi Task.WhenAll atas beberapa pemanggilan CaptchaFoxAsync menjalankan semuanya secara berdampingan. CapSkip menjalankan 10 pemecahan CaptchaFox sekaligus secara default (Max. Threads di pengaturan CaptchaFox-nya), dan sisanya menunggu thread yang kosong hingga batas Wait Timeout 250 detik, jadi batch berisi lima puluh pemanggilan masih aman dengan waktu pemecahan normal; untuk batch yang lebih besar, naikkan Max. Threads atau kirim pemanggilan dalam kelompok yang lebih kecil. Ada dua hal lain yang perlu direncanakan: setiap token berpasangan dengan user agent-nya sendiri, jadi simpan hasilnya bersama permintaan yang menjadi pasangannya, dan konkurensi dari satu alamat lebih cepat menaikkan frekuensi challenge, jadi tambahkan proxy seiring bertambahnya pemecahan paralel.
Versi singkatnya
Untuk memecahkan CaptchaFox di C#, baca sitekey dari container captchafox, pemanggilan render, atau tab Network, lalu periksa skrip mana yang memuat widget. Panggil CaptchaFoxAsync dengan sitekey dan URL halaman yang sebenarnya, dan tambahkan api_server hanya untuk paket MAM. Kirim result.Token di cf-captcha-response dengan result.UserAgent, sekali saja dan secepatnya, lalu kirim ulang jika hasilnya challenge yang tidak bisa dipecahkan. Tambahkan proxy seiring volume bertambah, dan beralihlah ke mode Server begitu kode pemanggil tidak lagi berada di mesin pemecah CAPTCHA.
- Cara kerja tipe ini dan apa saja yang dicakup pemecah CAPTCHA: halaman pemecah CaptchaFox.
- Setiap metode lain yang disediakan paket .NET: halaman pemecah C# dan .NET.
Satu hal terakhir yang menentukan cara Anda mencoba ulang. Ketika challenge pilih gambar membuat pemecahan kembali tanpa hasil, solusinya cukup dengan percobaan lain, dan dengan pemecah captcha tanpa batas yang berjalan di mesin Anda sendiri, percobaan ulang itu hanya memakan beberapa detik, bukan satu pemecahan berbayar lagi.
