Captcha token kedaluwarsa: penyebab dan cara memperbaikinya
Token captcha adalah bukti singkat bahwa sebuah tantangan telah dilewati. Token PopularCaptcha dari Scarnox kedaluwarsa sekitar dua menit setelah diterbitkan. Jika Anda mengirim token setelah jendela itu, situs akan menolak form, sering kali dengan pesan bahwa captcha sudah kedaluwarsa atau tidak valid. Perbaikannya hampir selalu soal waktu: solve captcha sedekat mungkin dengan pengiriman, pakai setiap token hanya sekali, dan retry hanya jika Anda yakin percobaan pertama belum diterima.
Mengapa token kedaluwarsa
Token bukanlah kredensial permanen. Situs ingin tahu bahwa seseorang (atau solver yang bertindak untuk seseorang) menyelesaikan tantangan baru-baru ini, jadi ia memberi token masa berlaku yang singkat. Jamnya mulai berjalan saat token diterbitkan, bukan saat Anda pertama kali memanggil API. Apa pun yang terjadi di antara solve dan pengiriman akan memakan dua menit tersebut.
Penyebab umum
- Solve terlalu dini. Menyolve sekumpulan token di awal lalu menyimpannya untuk nanti adalah penyebab yang paling sering. Saat token dipakai, ia sudah basi.
- Kode lambat di antara solve dan pengiriman. Penulisan database yang panjang, antrean, atau
time.sleepyang diletakkan sebelum pengiriman form bisa mendorong token melewati masa berlakunya. - Memakai ulang token. Token yang sudah diterima, atau yang sudah dipakai oleh percobaan gagal, tidak akan bekerja lagi. Perlakukan setiap token sebagai sekali pakai.
- Memuat ulang halaman. Jika halaman di-refresh setelah solve, form mungkin menerbitkan tantangan baru dan membatalkan token yang Anda pegang.
Perbaikannya: solve tepat sebelum mengirim
Pola yang paling andal adalah menjadikan solve dan pengiriman satu langkah. Minta token, masukkan ke form, kirim form, dan jangan lakukan apa pun yang lambat di antaranya:
import requests
API_KEY = "scarnox_YOURAPIKEY"
CREATE_URL = "https://api.scarnox.com/api/tasks/create"
def fresh_token(sitekey: str, page_url: str) -> str:
r = requests.post(
CREATE_URL,
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"captcha_type": "PopularCaptchaTaskProxyless",
"site_key": sitekey,
"site_url": page_url,
},
timeout=185, # panggilan menunggu sampai token siap
)
data = r.json()
if data.get("errorId") != 0:
raise RuntimeError(f"{data.get('errorCode')}: {data.get('errorDescription')}")
return data["solution"]["token"]
def submit_form(page_url: str, sitekey: str, form: dict) -> requests.Response:
token = fresh_token(sitekey, page_url) # solve tepat sebelum mengirim
return requests.post(
page_url,
data={**form, "h-captcha-response": token, "g-recaptcha-response": token},
timeout=30,
)
Perhatikan bahwa submit_form tidak menyimpan token di cache atau antrean. Ia meminta satu token, mengirimnya, lalu lanjut. Solve yang gagal tidak dikenai biaya, jadi request yang gagal tidak membebani sisi solve.
Retry dengan aman
Beberapa situs menolak token yang kedaluwarsa dengan respons yang jelas. Situs lain mengembalikan halaman normal dengan pesan error di dalamnya, sehingga kode status saja tidak cukup untuk memberi tahu. Lihat respons yang sebenarnya dikembalikan situs untuk token kedaluwarsa, lalu bangun pengecekan Anda berdasarkan itu. Loop retry bisa terlihat seperti ini:
def submit_with_retry(page_url: str, sitekey: str, form: dict, attempts: int = 2):
for _ in range(attempts):
resp = submit_form(page_url, sitekey, form)
if resp.status_code < 400 and "captcha" not in resp.text.lower():
return resp # diterima, sejauh yang terlihat dari respons situs ini
raise RuntimeError("captcha token rejected after retries")
Berhati-hatilah dengan retry pada form yang membuat sesuatu. Jika percobaan pertama sebenarnya diterima tetapi kode Anda salah membaca responsnya, retry bisa membuat akun, pesanan, atau pesan yang duplikat. Retry hanya jika Anda yakin pengiriman pertama tidak diterima, dan buat pengecekannya spesifik untuk situs yang sedang Anda kerjakan.
Jaga waktunya tetap jujur
- Jangan melakukan solve dalam loop token yang berniat dipakai nanti. Solve per pengiriman.
- Jaga pekerjaan di antara solve dan pengiriman seminimal mungkin.
- Gunakan timeout sekitar 185 detik untuk request solve, karena panggilan memblokir sampai token siap. Timer terpisah untuk pengiriman form Anda seharusnya jauh lebih singkat daripada masa hidup token.
- Jika Anda membutuhkan pipeline yang lebih cepat, lihat kecepatan solving captcha, yang membahas solve paralel tanpa menyimpan token.
Kesalahan yang umum
- Menyimpan token di dictionary atau Redis untuk nanti. Cache ini terlihat tidak berbahaya sampai sebuah token dipakai setelah jendela waktunya habis dan setiap pengiriman gagal.
- Melakukan solve sekali per sesi. Sesi yang berumur panjang tetap memerlukan token baru untuk setiap pengiriman form, karena setiap pengiriman mungkin menjalankan pemeriksaan tantangannya sendiri.
- Tidur di antara solve dan pengiriman. Rate limiter atau jeda yang disengaja setelah solve menghabiskan masa hidup token. Letakkan pengaturan ritme sebelum solve.
- Memperlakukan semua kegagalan sama. Timeout di sisi Anda, token yang ditolak, dan error situs memerlukan penanganan yang berbeda. Catat secara terpisah.
Catat cukup untuk mendiagnosis
Saat pengiriman gagal, catat waktu token diterbitkan, waktu form dikirim, status HTTP, dan beberapa ratus karakter pertama dari respons. Dengan empat nilai itu Anda bisa langsung melihat apakah token sudah basi atau situs menolaknya karena alasan lain. Jangan mencatat token lengkap di log bersama, karena token yang valid adalah kredensial untuk satu tantangan itu.
Yang perlu dicek jika masih gagal
- Cetak waktu antara token dikembalikan dan pengiriman form.
- Pastikan
site_urlcocok dengan halaman yang menampilkan captcha. - Pastikan sitekey dibaca dari halaman yang sekarang, bukan salinan lama.
- Pastikan nama field form. Token PopularCaptcha dimasukkan ke
h-captcha-response, dan sering kali juga keg-recaptcha-response.
Untuk daftar lengkap respons error dan cara menangani masing-masing, lihat penanganan error solver captcha.