Pemecahan Masalah

Waktu Kedaluwarsa Token Cloudflare Turnstile dan Race Condition

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%.

Komentar dinonaktifkan untuk artikel ini.