Sorun Giderme

Cloudflare Turnstile Tokenının Sona Erme Zamanlaması ve Yarış Koşulları

Testlerde çalışan bir Turnstile jetonu üretimde başarısız oluyor. Nedeni: jetonun süresinin dolması. Turnstile jetonlarının kullanım ömrü sınırlıdır ve iş akışınız jetonun alınması ile gönderilmesi arasında çok uzun sürerse site bunu reddeder. İşte zamanlamayı doğru şekilde nasıl kullanacağınız.

Token Ömrü

Turnstile jetonlarının geçerliliği, oluşturulduktan yaklaşık 300 saniye (5 dakika) sonra sona erer. Bu, reCAPTCHA'nın ~120 saniyesinden daha cömerttir, ancak karmaşık iş akışlarında hala yarış koşulları ortaya çıkmaktadır.

CAPTCHA türü Jeton ömrü
reCAPTCHA v2/v3 ~120 saniye
Cloudflare Turnstile ~300 saniye
hCaptcha ~120 saniye

Zamanlayıcı, Cloudflare tokenı oluşturduğunda başlar; CaptchaAI tokenı size geri verdiğinde veya onu kodunuza aldığınızda değil.

Yarış Durumu

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

Saat 0:20'den itibaren işliyor. Belirteci göndermek için yaklaşık 5:20'ye kadar vaktiniz var. Bu cömertçe görünebilir, ancak gerçek bir iş akışında neler olduğunu düşünün:

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

Yaygın Yarış Durumu Senaryoları

1. Çok Adımlı Formlar

Son gönderimden önce birkaç sayfa gerektiren formlar:

Step 1: Fill personal info → Step 2: Fill address → 
Step 3: Solve CAPTCHA → Step 4: Review → Step 5: Submit

CAPTCHA 3. Adımdaysa ancak gönderim 5. Adımda gerçekleşirse, çözme ile gönderme arasındaki gecikme 5 dakikayı aşabilir.

2. Toplu İşleme Kuyrukları

Jetonları önceden çözmek ve daha sonra kullanmak:

# 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. Eski Jetonlarla Döngüleri Yeniden Deneyin

Başarısız bir gönderimden sonra jetonun yeniden kullanılması:

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

Son Kullanma Tarihinin Önlenmesi

Strateji 1: Tam Zamanında Çözün

Belirteci yalnızca göndermeye hazır olduğunuzda isteyin:

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

Strateji 2: Token Yaşını Takip Edin

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 min — safety margin from 5 min limit

    @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))

# Check before using
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)

Strateji 3: Yeniden Denemede Yeni Token (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');
}

Süresi Dolmuş Jetonların Tespiti

Site genellikle size açıkça "belirtecin süresinin dolduğunu" söylemez. Şu sinyalleri arayın:

Sinyal Endikasyon
Belirteci gönderdikten sonra HTTP 403 Belirteç geçersiz veya süresi dolmuş
Form sayfasına geri yönlendir Jeton doğrulaması başarısız oldu
Hata mesajı: "doğrulama başarısız oldu" Genel hata – son kullanma tarihi geçmiş olabilir
Yarışma sayfası yeniden görünüyor Token reddedildi, Cloudflare yeniden meydan okuyor

Teşhis için Günlüğe Kaydetme

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)")

Turnstilenin Otomatik Yenileme Davranışı

Tarayıcı tabanlı akışlarda Turnstile widget'ları, belirteçleri süreleri dolmadan otomatik olarak yeniler. data-expired-callback, bir tokenın süresi dolduğunda etkinleşir:

turnstile.render('#captcha', {
  sitekey: '0x4AAAA...',
  callback: (token) => {
    console.log('New token:', token);
  },
  'expired-callback': () => {
    console.log('Token expired — widget will auto-refresh');
  }
});

Yalnızca API otomasyonunda (tarayıcı yok), otomatik yenilemeden yararlanamazsınız. Token tazeliğini kendiniz yönetmelisiniz.

Sorun giderme

Sorun Sebep Düzeltme
Token testte çalışıyor ancak üretimde çalışmıyor Üretim iş akışı daha yavaştır Önceden değil, tam zamanında çözün
İlk gönderim başarılı, yeniden denemeler başarısız Tüketilen jetonların yeniden kullanılması Her denemede yeni bir jeton çözün
Uzun formlarda aralıklı hatalar Çok adımlı akış sırasında jetonun süresi doluyor CAPTCHA çözümünü son adıma taşıyın
Toplu işlerin başarısızlık oranı yüksektir Toplu olarak çözülen jetonların kullanımdan önce geçerliliği sona erer Belirteçleri toplu olarak değil, isteğe bağlı olarak çözün

SSS

Bir Turnstile jetonunun ömrünü uzatabilir miyim?

Hayır. Geçerlilik süresi Cloudflare tarafından belirlenir ve değiştirilemez. Tek seçeneğiniz yeni bir jetonu çözmek.

300 saniye sınırı ne kadar kesindir?

Yaklaşık bir değerdir. Cloudflare, yapılandırmaya bağlı olarak zamanlamayı ayarlayabilir. Güvenlik payı için pratik maksimum süreniz olarak 270 saniyeyi (4,5 dakika) kullanın.

Zaman kazanmak için belirteçleri önceden çözmeli miyim?

Yalnızca iş akışınız bunları birkaç dakika içinde kullanabilirse. Toplu işleme için belirteçleri önceden çözmek yerine isteğe bağlı olarak çözün.

İlgili Makaleler

Sonraki Adımlar

Turnstile jetonunun süresinin dolmasını önleyin —CaptchaAI API anahtarınızı alınve %100 başarı oranıyla tam zamanında çözüm uygulayın.

Bu makale için yorumlar devre dışı bırakılmıştır.