Cara Memecahkan Cloudflare Turnstile di Node.js dan TypeScript

Cloudflare Turnstile muncul dalam dua bentuk dan keduanya memerlukan kode yang berbeda. Widget di dalam formulir adalah panggilan dua argumen. Tantangan interstisial satu halaman penuh memerlukan dua nilai tambahan yang diambil dari halaman, dan tokennya hanya akan diterima jika Anda mengirimkan kembali user agent yang digunakan pemecah. Persyaratan terakhir itulah yang menghasilkan token yang terlihat sempurna tetapi selalu gagal.
Cara membedakannya
| Widget | Halaman challenge | |
|---|---|---|
| Tampilan | Checkbox di dalam formulir yang dapat digunakan | Interstisial satu halaman penuh, halaman terblokir |
| Membutuhkan cData dan chlPageData | Tidak | Ya |
| Membutuhkan user agent yang dikembalikan | Tidak | Ya |
Kami demo Turnstile langsung menjalankan varian widget, yang menjadi referensi berguna saat Anda mencoba menentukan varian mana yang sedang Anda hadapi.
Penyiapan
npm install capskip
const { CapSkip } = require('capskip');
const solver = new CapSkip({
host: '127.0.0.1',
port: 8080,
recaptchaTimeout: 300, // seconds, also covers Turnstile
});CapSkip memecahkan secara lokal, jadi aplikasi desktop harus berjalan sebelum panggilan apa pun berhasil.
Mode widget
const result = await solver.turnstile( '0x4AAAAAAA...', // the data-sitekey attribute 'https://example.com/login', ); console.log(result.code); // cf-turnstile-response token
Letakkan result.code ke dalam cf-turnstile-response dan kirim. Tidak ada lagi yang diperlukan.
Halaman challenge membutuhkan dua nilai tambahan
Interstitial membawa state per permintaan yang mengikat token tersebut. Dua bagian darinya harus ikut dikirim bersama pemecahan:
- cData, diteruskan sebagai
data - chlPageData, diteruskan sebagai
pagedata
Keduanya berada di halaman tantangan itu sendiri, bukan di atribut formulir, sehingga halamannya harus diambil sebelum dapat dipecahkan. Pada interstisial Cloudflare standar, keduanya berada pada objek opsi tantangan milik halaman itu sendiri, di samping sitekey. Keduanya sekali pakai dan terikat pada pemuatan halaman tersebut, jadi ambil dan pecahkan sekaligus alih-alih menyimpannya di cache.
const result = await solver.turnstile(sitekey, pageUrl, {
data: cData, // the cData value
pagedata: chlPageData, // the chlPageData value
action: 'managed', // optional, when the page declares one
});
console.log(result.code);
console.log(result.userAgent); // required for the next stepUser agent bukan opsional
Turnstile mengikat token ke fingerprint browser yang menghasilkannya, dan user agent adalah bagian dari fingerprint itu. CapSkip mengembalikan nilai yang dipakainya di result.userAgent. Kirim token dengan user agent bawaan fetch Node dan Cloudflare akan menolak token yang sebenarnya sepenuhnya valid.
userAgent hanya terisi untuk Turnstile. Nilainya undefined untuk setiap tipe CAPTCHA lain, itulah tepatnya mengapa hal ini menjebak orang yang memakai ulang helper reCAPTCHA yang sudah bekerja.
const response = await fetch(pageUrl, {
method: 'POST',
headers: {
// Send back the exact user agent the solve was performed with.
'User-Agent': result.userAgent,
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
'cf-turnstile-response': result.code,
}),
});Jika sebuah token ditolak dan cData-nya masih baru, ini hampir selalu alasannya.
TypeScript
import { CapSkip, SolveResult } from 'capskip';
const solver = new CapSkip({ host: '127.0.0.1', port: 8080 });
const result: SolveResult = await solver.turnstile(sitekey, pageUrl);
// userAgent is optional on the type, because only Turnstile populates it.
if (result.userAgent) {
// safe to forward
}Definisi disertakan bersama paket, sehingga tidak ada @types install. Anotasi tipe opsional pada userAgent adalah dorongan yang berguna: kompiler tidak akan membiarkan Anda lupa bahwa jenis CAPTCHA lain membiarkannya kosong.
Proxy dan konkurensi
// Solve through the same egress you will submit from.
await solver.turnstile(sitekey, pageUrl, {
data: cData,
pagedata: chlPageData,
proxy: { type: 'HTTPS', uri: 'user:[email protected]:3128' },
});
// Several at once.
const results = await Promise.all(targets.map((t) =>
solver.turnstile(t.sitekey, t.url)));Proxy berfungsi untuk Turnstile, reCAPTCHA, dan GeeTest, tetapi tidak untuk CAPTCHA gambar, yang tidak pernah menyentuh situs target. Untuk halaman tantangan, setiap pemecahan memerlukan cData miliknya sendiri yang baru diambil, jadi ambillah di dalam fungsi yang dipetakan alih-alih dalam satu batch di awal.
Pertanyaan yang sering diajukan
Apakah widget pernah membutuhkan cData?
Tidak, dan mengirim nilai kosong akan membuat pemecahan gagal alih-alih membantu. Hanya tantangan interstitial satu halaman penuh yang menggunakannya.
Token terlihat baik-baik saja tetapi situs menolaknya.
Hampir selalu user agent. Kirim menggunakan result.userAgent alih-alih apa pun yang dikirim client HTTP Anda secara bawaan. Penyebab paling mungkin kedua adalah cData yang basi, yang terikat pada satu kali muat halaman.
Bisakah saya menggunakan ini dengan Puppeteer?
Ya, dan keduanya cocok dipadukan: baca cData dari halaman yang sudah dimuat dengan page.evaluate, pecahkan dengan SDK ini, lalu setel user agent yang sama pada halaman sebelum melanjutkan. Lihat pemecah CAPTCHA Node.js halaman membahas sisi otomatisasi.
Ringkasan
Widget memerlukan sitekey dan URL. Halaman challenge membutuhkan data dan pagedata dibaca segar dari halaman, dan token harus dikirimkan bersama result.userAgent. Selebihnya adalah penanganan Promise biasa.
Bahasa lain ada di Pemecah Cloudflare Turnstile halaman, detail parameter di dokumentasi API, dan cakupan Node yang lebih luas ada di halaman pemecah CAPTCHA Node.js halaman. CapSkip adalah pemecah captcha tanpa batas yang berjalan di perangkat keras Anda sendiri.
