Token Turnstile yang berfungsi saat pengujian gagal di produksi. Penyebabnya: masa berlaku token habis. Token Turnstile memiliki lifetime terbatas, dan jika alur kerja Anda terlalu lama antara menerima token dan mengirimkannya, situs akan menolaknya. Berikut cara menangani timing dengan benar.
Lifetime Token
Masa berlaku token Turnstile sekitar 300 detik (5 menit) setelah dibuat. Ini lebih lama dibanding reCAPTCHA (~120 detik), namun race condition tetap bisa terjadi pada alur kerja yang kompleks.
| Jenis CAPTCHA | Lifetime Token |
|---|---|
| reCAPTCHA v2/v3 | ~120 detik |
| Cloudflare Turnstile | ~300 detik |
| hCaptcha | ~120 detik |
Timer mulai saat Cloudflare membuat token — bukan saat CaptchaAI mengembalikannya, dan bukan saat kode Anda menerimanya.
Race Condition
Time 0:00 — You submit a Turnstile task to CaptchaAI
Time 0:15 — CaptchaAI begins solving
Time 0:20 — Token is generated (timer starts here)
Time 0:25 — CaptchaAI returns token to you
Time 0:25+ — Your code processes the token
Time ??? — Your code submits the token to the site
Jam terus berdetak dari Time 0:20. Anda punya waktu hingga sekitar Time 5:20 untuk submit token. Terdengar cukup longgar, tapi perhatikan apa yang terjadi dalam alur kerja nyata:
Time 0:20 — Token generated
Time 0:25 — Received by your code
Time 0:30 — Fill form fields
Time 0:35 — Navigate to next page
Time 1:00 — Handle additional dialogs
Time 2:00 — Wait for page load
Time 4:00 — Network latency spike
Time 5:30 — Submit token → EXPIRED
Skenario Race Condition Umum
1. Form Multi-Langkah
Form yang memerlukan beberapa halaman sebelum submit akhir:
Step 1: Fill personal info → Step 2: Fill address →
Step 3: Solve CAPTCHA → Step 4: Review → Step 5: Submit
Jika CAPTCHA ada di Langkah 3 tapi submit dilakukan di Langkah 5, penundaan antara solving dan submit bisa melebihi 5 menit.
2. Antrian Pemrosesan Batch
Solve token terlebih dahulu dan menggunakannya belakangan:
# DON'T: Solve all tokens first, then use them
tokens = []
for url in urls:
tokens.append(solve_turnstile(url)) # Tokens age while waiting
for url, token in zip(urls, tokens):
submit_form(url, token) # Early tokens may be expired
3. Retry Loop dengan Token Lama
Menggunakan kembali token setelah submit gagal:
token = solve_turnstile(site_key, page_url)
for attempt in range(3):
result = submit_form(page_url, token)
if result.ok:
break
# BUG: Retrying with the same token — it may be expired OR already consumed
Mencegah Kedaluwarsa
Strategi 1: Solve Just-in-Time
Minta token hanya saat Anda siap submit:
import requests
import time
def solve_turnstile(site_key, page_url):
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": "YOUR_API_KEY",
"method": "turnstile",
"sitekey": site_key,
"pageurl": page_url,
"json": 1
})
task_id = resp.json()["request"]
for _ in range(60):
time.sleep(3)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": "YOUR_API_KEY",
"action": "get",
"id": task_id,
"json": 1
})
data = result.json()
if data["status"] == 1:
return data["request"]
raise TimeoutError("Solve timed out")
# Complete all form steps FIRST
fill_personal_info()
fill_address()
navigate_to_review()
# THEN solve and submit immediately
token = solve_turnstile(site_key, page_url)
submit_form(token) # Submit within seconds of receiving the token
Strategi 2: Lacak Usia Token
import time
class TimedToken:
def __init__(self, token, created_at=None):
self.token = token
self.created_at = created_at or time.time()
self.max_age = 270 # 4.5 menit — safety margin dari batas 5 menit
@property
def is_valid(self):
return (time.time() - self.created_at) < self.max_age
@property
def remaining_seconds(self):
return max(0, self.max_age - (time.time() - self.created_at))
# Usage
timed_token = TimedToken(solve_turnstile(site_key, page_url))
# Cek sebelum menggunakan
if timed_token.is_valid:
submit_form(timed_token.token)
else:
# Solve token baru
timed_token = TimedToken(solve_turnstile(site_key, page_url))
submit_form(timed_token.token)
Strategi 3: Token Baru saat Retry (JavaScript)
async function submitWithFreshToken(siteKey, pageUrl, formData) {
const maxRetries = 3;
for (let attempt = 0; attempt < maxRetries; attempt++) {
// Always solve a fresh token for each attempt
const token = await solveTurnstile(siteKey, pageUrl);
const response = await fetch(pageUrl, {
method: 'POST',
body: JSON.stringify({ ...formData, 'cf-turnstile-response': token }),
headers: { 'Content-Type': 'application/json' }
});
if (response.ok) return await response.json();
console.log(`Attempt ${attempt + 1} failed, solving fresh token...`);
}
throw new Error('All attempts failed');
}
if timed_token.is_valid: submit_form(timed_token.token) else: # Solve a fresh token timed_token = TimedToken(solve_turnstile(site_key, page_url)) submit_form(timed_token.token)
### Strategi 3: Token Baru saat Coba Lagi (JavaScript)
```javascript
async function submitWithFreshToken(siteKey, pageUrl, formData) {
const maxRetries = 3;
for (let attempt = 0; attempt < maxRetries; attempt++) {
// Always solve a fresh token for each attempt
const token = await solveTurnstile(siteKey, pageUrl);
const response = await fetch(pageUrl, {
method: 'POST',
body: JSON.stringify({ ...formData, 'cf-turnstile-response': token }),
headers: { 'Content-Type': 'application/json' }
});
if (response.ok) return await response.json();
console.log(`Attempt ${attempt + 1} failed, solving fresh token...`);
}
throw new Error('All attempts failed');
}
Mendeteksi Token Kedaluwarsa
Situs biasanya tidak memberi tahu "token kedaluwarsa" secara eksplisit. Perhatikan sinyal berikut:
| Sinyal | Indikasi |
|---|---|
| HTTP 403 setelah submit token | Token tidak valid atau kedaluwarsa |
| Redirect kembali ke halaman form | Validasi token gagal |
| Pesan error: "verifikasi gagal" | Kegagalan umum — mungkin sudah kedaluwarsa |
| Halaman challenge muncul kembali | Token ditolak, Cloudflare kembali menantang |
Pencatatan untuk Diagnosis
import time
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("turnstile")
token_received_at = time.time()
token = solve_turnstile(site_key, page_url)
logger.info(f"Token received, length: {len(token)}")
# ... workflow steps ...
submit_time = time.time()
age = submit_time - token_received_at
logger.info(f"Submitting token, age: {age:.1f}s")
if age > 270:
logger.warning(f"Token may be expired (age: {age:.1f}s > 270s safety limit)")
Auto-Refresh Turnstile
Dalam alur berbasis browser, widget Turnstile me-refresh token secara otomatis sebelum kedaluwarsa. data-expired-callback dipanggil saat token kedaluwarsa:
turnstile.render('#captcha', {
sitekey: '0x4AAAA...',
callback: (token) => {
console.log('New token:', token);
},
'expired-callback': () => {
console.log('Token expired — widget will auto-refresh');
}
});
Dalam otomasi khusus API (tanpa browser), Anda tidak mendapatkan manfaat auto-refresh. Anda harus mengelola kesegaran token sendiri.
Pemecahan Masalah
| Masalah | Penyebab | Solusi |
|---|---|---|
| Token berfungsi saat pengujian tapi tidak di produksi | Alur kerja produksi lebih lambat | Solve just-in-time, bukan di muka |
| Submit pertama berhasil, retry gagal | Menggunakan kembali token yang sudah dikonsumsi | Solve token baru untuk setiap upaya |
| Kegagalan intermiten pada form panjang | Token kedaluwarsa selama alur multi-langkah | Pindahkan solve CAPTCHA ke langkah terakhir |
| Pekerjaan batch memiliki tingkat kegagalan tinggi | Token yang di-solve massal kedaluwarsa sebelum digunakan | Solve token sesuai permintaan, bukan sekaligus |
Pertanyaan Umum
Bisakah saya memperpanjang lifetime token Turnstile?
Tidak. Masa berlakunya ditentukan oleh Cloudflare dan tidak dapat diubah. Satu-satunya pilihan adalah solve token baru.
Seberapa tepat batas 300 detik?
Ini perkiraan. Cloudflare dapat menyesuaikan waktu berdasarkan konfigurasi. Gunakan 270 detik (4,5 menit) sebagai batas maksimum praktis dengan margin keamanan.
Haruskah saya solve token terlebih dahulu untuk menghemat waktu?
Hanya jika alur kerja Anda bisa menggunakannya dalam beberapa menit. Untuk pemrosesan batch, solve token sesuai permintaan, bukan di muka.
Artikel Terkait
- Cloudflare Challenge vs Turnstile: Cara Mendeteksi
- Cloudflare Turnstile 403 Setelah Submit Token — Perbaikan
- Token Turnstile Tidak Valid Setelah Solving
Langkah Selanjutnya
Cegah kedaluwarsa token Turnstile — dapatkan kunci API CaptchaAI dan terapkan solve just-in-time dengan tingkat keberhasilan 100%.