Cara Memecahkan CAPTCHA di Postman dan Melakukan Polling untuk Token

Anda bisa memecahkan captcha di Postman tanpa menulis satu baris pun kode aplikasi. API-nya kompatibel dengan 2captcha dan berjalan di komputer Anda sendiri, jadi cukup dua permintaan: POST tugasnya ke /in.php lalu simpan ID-nya, kemudian lakukan polling ke /res.php sampai jawabannya tiba. Skrip post-response yang singkat mengubah permintaan kedua itu menjadi sebuah loop, dan sebuah collection variable membawa ID di antara keduanya. Panduan ini memuat kolom-kolomnya secara persis, kedua skripnya, dan satu pengaturan yang mencegah loop berjalan selamanya.
Apa yang Anda butuhkan
- Aplikasi desktop Postman. Aplikasi ini berbicara langsung ke 127.0.0.1 tanpa melibatkan agen. Aplikasi web dibahas di bawah dan membutuhkan satu komponen tambahan
- CapSkip berjalan dan dapat dijangkau. Mode Local mendengarkan di 127.0.0.1 port 8080 untuk klien di mesin yang sama, dan Mode Server mendengarkan di jaringan atau IP publik Anda sehingga sebuah laptop, rekan tim, atau runner terkelola bisa menjangkaunya. Keduanya ada di pengaturan koneksi
- Sebuah sitekey dan URL halaman sebagai sasaran pemecahan
Tidak ada lagi. Tanpa SDK, tanpa dependency, tanpa akun. Validasi key mati secara bawaan, jadi string apa pun yang tidak kosong bisa dipakai sebagai nilai key, dan tidak mengirim apa pun sama sekali akan mengembalikan ERROR_WRONG_USER_KEY alih-alih hasil pemecahan.
Siapkan tiga collection variable terlebih dahulu
Tempatkan variabel ini pada collection, bukan di sebuah environment. Collection variable ikut terbawa saat diekspor, jadi semuanya tetap bekerja ketika orang lain mengimpornya.
| Variabel | Nilai awal | Mengapa |
|---|---|---|
| baseUrl | http://127.0.0.1:8080 | Satu tempat untuk diubah ketika pemecah pindah ke sebuah server |
| apiKey | capskip | String apa pun yang tidak kosong. Validasi mati secara bawaan |
| captchaId | kosong | Skrip submit menuliskannya, permintaan polling membacanya |
Permintaan 1: kirim tugasnya
Sebuah POST ke {{baseUrl}}/in.php dengan body formulir. Pilih x-www-form-urlencoded, bukan JSON mentah: API membaca kolom formulir.
| Kunci | Nilai |
|---|---|
| key | {{apiKey}} |
| method | userrecaptcha |
| googlekey | YOUR_SITEKEY |
| pageurl | https://example.com/page-with-recaptcha |
| json | 1 |
Kolom json=1 lebih penting di Postman daripada di terminal. Tanpa itu, balasannya adalah string polos OK yang diikuti sebuah pipe dan ID, yang lalu harus Anda pisahkan secara manual. Dengan itu Anda mendapat sebuah objek dan pretty printer bekerja.
Tambahkan ini ke tab Scripts, di bagian Post-response. Versi Postman yang lebih lama menyebut tab yang sama dengan nama Tests.
// Post-response script on the submit request.
const body = pm.response.json();
pm.test('task accepted', function () {
pm.expect(body.status).to.eql(1);
});
// Hand the ID to the polling request.
pm.collectionVariables.set('captchaId', body.request);Bentuk responsnya sama untuk setiap jenis CAPTCHA. Status bernilai 1 ketika tugasnya diterima, dan nilai yang menarik selalu ada di kolom request.
{"status": 1, "request": "2122988149"}Perhatikan nama parameternya. reCAPTCHA memakai googlekey dan Turnstile memakai sitekey, dan mengirim yang keliru adalah penyebab umum balasan ERROR_GOOGLEKEY. Halaman pemecah Turnstile memuat daftar kolom lengkap untuk halaman challenge, yang juga membutuhkan nilai cData dan chlPageData yang diambil dari halaman.
Request yang sama, untuk delapan tipe lainnya
Hanya request submit yang berubah. Lima nilai method mencakup setiap tipe yang didukung CapSkip, dan variannya berupa kolom tambahan pada form body yang sama, bukan endpoint terpisah. Duplikasi Request 1, terapkan kolom terakhir, dan biarkan sisa request-nya apa adanya.
| Tipe | Setel method ke | Lalu ubah body-nya |
|---|---|---|
| Gambar, file yang diunggah | method = post | Ubah body ke form-data dan lampirkan gambar sebagai file |
| Gambar, base64 | method = base64 | Hapus googlekey dan pageurl, kirim body berisi gambar terenkode |
| reCAPTCHA v2 checkbox | method = userrecaptcha | Tidak ada. Ini adalah request yang ditunjukkan di atas |
| reCAPTCHA v2 Invisible | method = userrecaptcha | Tambahkan invisible dengan nilai 1 |
| reCAPTCHA Enterprise | method = userrecaptcha | Tambahkan enterprise dengan nilai 1 |
| reCAPTCHA v3 | method = userrecaptcha | Tambahkan version yang disetel ke v3, dan sebuah action |
| Widget Turnstile | method = turnstile | Ganti nama googlekey menjadi sitekey |
| Halaman challenge Turnstile | method = turnstile | Ganti nama googlekey menjadi sitekey, lalu tambahkan data dan pagedata |
| GeeTest v3 | method = geetest | Kirim gt dan challenge sebagai ganti googlekey |
Dua di antaranya perlu perhatian khusus di Postman. Gambar yang diunggah adalah satu-satunya yang tidak bisa memakai x-www-form-urlencoded, karena file membutuhkan body multipart, jadi ubah request yang satu itu ke form-data. Dan GeeTest punya tenggat: nilai challenge-nya kedaluwarsa dalam sekitar satu menit, jadi ambil nilainya tepat sebelum Anda mengirim, bukan memakai ulang yang Anda simpan sebelumnya.
Request polling tidak pernah berubah. Justru itulah alasan membangun semua ini sebagai collection: satu Request 2 melayani setiap tipe dalam daftar, karena jawabannya selalu datang dalam bentuk yang sama.
Permintaan 2: lakukan polling sampai jawabannya tiba
Sebuah POST ke {{baseUrl}}/res.php, dengan gaya body formulir yang sama.
| Kunci | Nilai |
|---|---|
| key | {{apiKey}} |
| action | get |
| id | {{captchaId}} |
| json | 1 |
Selama job masih berjalan, permintaan ini mengembalikan CAPCHA_NOT_READY, dieja persis seperti itu, termasuk huruf yang hilang. Ini adalah status dan bukan error, dan satu-satunya respons yang benar adalah bertanya lagi.
// Post-response script on the polling request.
const body = pm.response.json();
const tries = Number(pm.collectionVariables.get('tries') || 0);
if (body.request === 'CAPCHA_NOT_READY' && tries < 20) {
// Run this same request again.
pm.collectionVariables.set('tries', tries + 1);
pm.execution.setNextRequest(pm.info.requestId);
} else {
pm.collectionVariables.set('captchaToken', body.request);
pm.collectionVariables.set('tries', 0);
pm.execution.setNextRequest(null);
}Tiga hal dalam skrip itu layak disorot, karena masing-masing bisa menghabiskan waktu satu sore Anda.
Loop hanya berjalan di Collection Runner. Dokumentasi Postman sendiri menyatakan dengan jelas bahwa setNextRequest tidak berpengaruh ketika Anda mengirim satu permintaan tunggal, jadi mengklik Send pada permintaan polling hanya mengirimnya sekali dan skripnya tampak mati. Jalankan collection-nya, Postman CLI, atau Newman.
Penghitungnya bukan opsional. Tanpa batas atas, tugas yang tidak pernah selesai akan terus berulang sampai Anda menghentikan run-nya secara manual. Dua puluh percobaan dengan jarak lima detik berarti lebih dari seratus detik menunggu, yang dengan nyaman melampaui 15 sampai 20 detik yang dibutuhkan sebuah job reCAPTCHA v2.
Rujuk permintaannya lewat ID. Meneruskan pm.info.requestId mengarahkan loop ke permintaan yang sedang berjalan, sehingga mengganti namanya nanti tidak diam-diam memutus rantainya.
Beri runner sebuah delay, atau Anda akan menggempur endpoint-nya
Skrip di atas berulang secepat yang bisa dilakukan runner, dan melakukan polling pada job yang baru berjalan dua detik adalah pekerjaan sia-sia. Collection Runner punya kolom Delay di konfigurasi run-nya, dalam milidetik, yang diterapkan sebelum setiap permintaan. Atur ke 5000.
Berapa lama menunggu sebelum polling pertama tergantung pada apa yang Anda kirim:
| Tipe | Belum siap sebelum |
|---|---|
| Gambar | 1 detik |
| reCAPTCHA v2 | 15 hingga 20 detik |
| reCAPTCHA v3 | 10 hingga 15 detik |
| GeeTest v3 | sekitar 5 detik |
Di Newman, pengaturan yang sama berupa flag command line, jadi collection yang bekerja di aplikasinya akan bekerja tanpa perubahan di CI.
# npm install -g newman newman run captcha.postman_collection.json --delay-request 5000
Membaca balasan dalam teks biasa sebagai gantinya
Hilangkan json=1 dan body-nya akan kembali sebagai teks, yang kadang memang Anda inginkan. Dua potongan bantu berikut sudah mencukupi.
// Plain text mode: OK|2122988149
const id = pm.response.text().split('|')[1];
// Turnstile also returns the user agent, as a header.
const ua = pm.response.headers.get('X-Turnstile-User-Agent');Header itu bukan sekadar hal unik. Cloudflare mengikat token Turnstile ke fingerprint browser yang menghasilkannya, jadi token harus dikirim dengan user agent yang sama atau situs akan menolaknya padahal tokennya sendiri sepenuhnya valid.
Satu aturan lagi yang khususnya menjerat pengguna Postman, karena aplikasinya membuat klik Send dua kali jadi begitu mudah: hasil hanya bisa dibaca satu kali. Pembacaan kedua atas ID yang sama akan kembali kosong, yang tampak persis seperti pemecahan yang gagal. Simpan token dalam sebuah variabel pada pembacaan pertama.
Soal agen, dan mengarahkan Postman ke sebuah server
Jika Anda memakai aplikasi web Postman alih-alih aplikasi desktopnya, permintaan berjalan melalui sebuah agen, dan pilihan agen menentukan apakah 127.0.0.1 bisa dijangkau sama sekali. Cloud Agent berjalan di infrastruktur Postman dan tidak bisa menjangkau apa pun di jaringan privat. Desktop Agent berjalan di komputer Anda dan bisa menjangkaunya.
| Cara Anda menjalankan Postman | Bisakah menjangkau pemecah lokal? |
|---|---|
| Aplikasi desktop | Ya, tanpa perlu agen |
| Aplikasi web dengan Desktop Agent | Ya, agen merutekannya lewat komputer Anda |
| Aplikasi web dengan Cloud Agent | Tidak, ia tidak bisa melihat jaringan privat |
Mode Server mengubah perhitungan itu. Jalankan CapSkip di sebuah mesin yang mendengarkan di jaringan Anda atau di IP publik, ubah variabel baseUrl agar mengarah ke sana, dan setiap permintaan dalam collection akan mengikuti. Tidak ada lagi yang berubah, karena satu-satunya yang berpindah adalah alamatnya.
# The collection variable is the only edit. baseUrl = http://YOUR_SERVER_IP:8080
IP publik statis direkomendasikan, dan langkah-langkahnya ada di pengaturan koneksi. Mode Server tetap perangkat keras milik Anda sendiri dan tetap tanpa kuota: yang berubah adalah tempat pemecah mendengarkan, bukan siapa pemiliknya.
Kesalahan umum dan artinya
| Apa yang Anda lihat | Penyebab | Perbaiki |
|---|---|---|
ERROR_WRONG_USER_KEY | Kolom key tiba dalam keadaan kosong karena {{apiKey}} tidak ter-resolve | Definisikan apiKey pada collection, bukan di environment yang harus Anda ingat untuk dipilih |
ERROR_WRONG_METHOD | Salah ketik pada method, atau pada nilai action | Keduanya adalah kolom formulir, bukan HTTP verb: submit memakai kolom method, polling memakai kolom action yang disetel ke get |
ERROR_GOOGLEKEY | Sebuah sitekey Turnstile dikirim ke userrecaptcha | Cocokkan method dengan nama kolomnya |
ERROR_PAGEURL | URL halaman tidak punya skema, atau terpotong | Sertakan https, dan pakai body formulir alih-alih query string |
| Body respons kosong | ID itu sudah pernah dibaca sekali | Simpan token pada pembacaan pertama; kirim ulang untuk mendapat yang baru |
| Tidak bisa mengirim permintaan, koneksi ditolak | Tidak ada yang mendengarkan di alamat tersebut | Jalankan pemecahnya, atau periksa apakah Desktop Agent sudah dipilih |
| Skripnya berjalan tetapi tidak ada yang berulang | Anda mengklik Send alih-alih menjalankan collection-nya | setNextRequest hanya bekerja dalam sebuah collection run |
Rumusan persis setiap kode yang bisa dikembalikan API ada di dokumentasi API.
Pertanyaan yang sering diajukan
Bisakah saya melakukan semuanya dalam satu permintaan?
Secara teknis bisa, dengan pm.sendRequest di sebuah pre-request script, dan itu jarang sepadan. Sandbox-nya dibuat untuk skrip pendek, jadi polling yang memblokir membuat permintaannya tampak menggantung tanpa umpan balik selama menunggu. Dua permintaan ditambah runner memperlihatkan setiap percobaan kepada Anda, dan itulah alasan berada di Postman alih-alih di dalam kode.
Apakah ini akan berjalan di CI lewat Newman?
Ya. setNextRequest bekerja di Newman dan di Postman CLI persis seperti di aplikasinya, jadi collection yang diekspor berjalan tanpa perubahan. Satu hal yang perlu dibereskan adalah keterjangkauan: runner terkelola punya alamat loopback-nya sendiri, jadi pemecahnya perlu berada dalam Mode Server di alamat yang bisa dirutekan oleh runner tersebut.
Apakah ada batas laju untuk berapa banyak yang bisa saya antrekan?
Tidak ada. Kirim sebanyak apa pun tugas yang Anda mau dan lakukan polling setiap ID secara terpisah. Pekerjaannya terjadi di perangkat keras Anda sendiri, bukan di antrean bersama milik orang lain, jadi batasnya adalah seberapa cepat mesin Anda menyelesaikannya, bukan sebuah kuota atau saldo.
Kapan saatnya beranjak dari Postman
Postman adalah alat yang tepat untuk membuktikan API-nya bekerja, menjelajahi jenis CAPTCHA baru, dan menyerahkan sesuatu kepada kolega yang bisa mereka impor dan jalankan. Postman adalah alat yang keliru untuk produksi, terutama karena polling-nya: runner menunggu habis delay tetapnya setiap kali, sementara SDK resmi mulai polling pada 250 milidetik lalu melonggar, sehingga pemecahan yang cepat kembali dengan cepat. SDK juga mengubah string error menjadi exception bertipe.
Untuk dua panggilan yang sama dalam sebuah shell script, lihat panduan cURL. Bagaimanapun juga, panggilannya menuju komputer Anda sendiri, dan itulah yang membuat pemecah captcha tanpa batas layak dijadikan sasaran sebuah collection: Anda bisa menjalankan collection itu dua puluh kali sambil membenahi kolom-kolomnya, dan biayanya tidak lebih dari CPU Anda sendiri.
