Explainers

Cloudflare Turnstile Widget Modları: Yönetilen, Etkileşimsiz, Görünmez

Aynı Turnstile widget'ı bir ziyaretçide onay kutusu gösterir, diğerinde hiç görünmeden geçer — bunun sebebi sitenin seçtiği widget modudur. Cloudflare Turnstile üç modda çalışır:

  • Yönetilen — kararı Cloudflare verir; kimi ziyaretçi görünmeden geçer, kimi onay kutusu görür.
  • Etkileşimsiz — yalnızca arka planda iş kanıtı çalışır, ekranda döndürücü dışında hiçbir şey görünmez.
  • Görünmez — sayfada hiçbir kapsayıcı öğe belirmez, doğrulama sessizce arka planda tamamlanır.

Otomasyon açısından iyi haber şu: üçü de aynı cf-turnstile-response token'ını üretir ve CaptchaAI'de aynı turnstile yöntemiyle çözülür. Fark, modu sayfada nasıl tespit ettiğinizde ve token'ın ne zaman hazır olduğunda ortaya çıkar.

Yönetilen mod: kararı Cloudflare verir

Yönetilen mod, zorluk seviyesini ziyaretçi bazında Cloudflare'e bırakır. Çoğu ziyaretçi hiçbir şey görmeden geçer; şüpheli görünen trafik bir onay kutusuyla karşılaşır; yüksek riskli trafik daha ağır bir doğrulamaya veya bloğa takılır. Bir giriş ya da kayıt formunda en sık karşılaştığınız mod budur. HTML'e şöyle eklenir:

<!-- Managed mode (default) -->
<div class="cf-turnstile"
     data-sitekey="0x4AAAAAAAC3DHQhMMQ_Rxrg"
     data-theme="light">
</div>
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>

Otomasyon tarafında widget, isteğin itibar sinyaline göre farklı oluşur — en yaygın ama en değişken mod budur:

İtibar sinyali Widget nasıl oluşur
Yüksek güven Görünmez geçiş (arayüz yok)
Orta güven Onay kutusu (doğrulamak için tıklayın)
Düşük güven Etkileşimli doğrulama veya blok

Yönetilen mod, HTML'de açık bir mod özniteliği bulunmamasından anlaşılır:

def is_managed_mode(html):
    """Check if Turnstile is using managed mode (default)."""
    # Managed mode is the default — no explicit mode attribute
    has_turnstile = "cf-turnstile" in html
    has_explicit_mode = 'data-appearance="interaction-only"' in html or \
                        'data-appearance="always"' in html or \
                        'appearance: "interaction-only"' in html
    return has_turnstile and not has_explicit_mode

Etkileşimsiz mod: yalnızca döndürücü

Etkileşimsiz mod hiçbir zaman onay kutusu veya etkileşimli bir öğe göstermez. Arka planda bir iş kanıtı (proof-of-work) sorgusu çalıştırır ve ekranda yalnızca yüklenen bir döndürücü görünür. Doğrulama etkileşimsiz biçimde tamamlanamazsa, yönetilen moda yükselmek yerine doğrudan başarısız olur:

<!-- Non-interactive mode -->
<div class="cf-turnstile"
     data-sitekey="0x4AAAAAAAC3DHQhMMQ_Rxrg"
     data-appearance="interaction-only">
</div>

Aynı yapılandırmayı JavaScript API'siyle de kurabilirsiniz:

turnstile.render('#turnstile-container', {
    sitekey: '0x4AAAAAAAC3DHQhMMQ_Rxrg',
    appearance: 'interaction-only',
    callback: function(token) {
        document.getElementById('cf-turnstile-response').value = token;
    },
});

Çalışma akışı

Page loads → Widget initializes
    ↓
Background proof-of-work runs
    ↓
Success → Token generated (no visible UI)
    OR
Failure → Widget reports error (no fallback to checkbox)

Bu modu genellikle sürtünmenin en aza indirilmesi gereken sayfalarda görürsünüz:

  • Yorum formları ve geri bildirim widget'ları
  • Bülten kayıtları
  • Düşük değerli, hızlı tamamlanması beklenen eylemler
  • Tarayıcı tarafında korunan API uç noktaları

Görünmez mod: ekranda hiç iz yok

Görünmez mod gerçekten görünmezdir; görünüm alanında hiçbir kapsayıcı öğe belirmez. Widget, sayfa yüklendiğinde (veya programatik bir tetikleyicide) çalışır ve hiçbir görsel işaret bırakmadan bir token üretir:

<!-- Invisible mode — container is hidden -->
<div id="turnstile-invisible"
     class="cf-turnstile"
     data-sitekey="0x4AAAAAAAC3DHQhMMQ_Rxrg"
     data-size="invisible">
</div>

Ya da tamamen JavaScript ile:

// Programmatic invisible Turnstile
turnstile.render('#hidden-container', {
    sitekey: '0x4AAAAAAAC3DHQhMMQ_Rxrg',
    size: 'invisible',
    callback: function(token) {
        // Token ready — submit form automatically
        submitForm(token);
    },
    'error-callback': function() {
        // Challenge failed
        console.error('Invisible Turnstile failed');
    },
});

Görünmez modu fark etmek zordur, çünkü kapsayıcının görünür bir boyutu yoktur — widget'ı gözle değil, HTML ve script içeriğini tarayarak bulursunuz. Aşağıdaki yardımcı, birkaç sinyali birleştirip bir güven seviyesi döndürür:

import re

def detect_invisible_turnstile(html):
    """Detect invisible Turnstile on a page."""
    indicators = {
        "script_loaded": "challenges.cloudflare.com/turnstile" in html,
        "size_invisible": 'data-size="invisible"' in html or
                          "size: 'invisible'" in html or
                          'size: "invisible"' in html,
        "api_render_call": "turnstile.render" in html,
        "response_field": "cf-turnstile-response" in html,
    }

    if indicators["script_loaded"] and indicators["size_invisible"]:
        return {"mode": "invisible", "confidence": "high"}
    elif indicators["script_loaded"] and indicators["api_render_call"]:
        return {"mode": "invisible_or_programmatic", "confidence": "medium"}
    elif indicators["response_field"]:
        return {"mode": "turnstile_present", "confidence": "low"}

    return {"mode": "none", "confidence": "high"}

Her modda sitekey çıkarma

Modu ne olursa olsun, çözüm için tek gerçek gereksinim sitekey'dir. Aşağıdaki yardımcı, üç modun herhangi birinden sitekey'i çeker:

import re

def extract_turnstile_sitekey(html):
    """Extract Turnstile sitekey from page HTML (works for all modes)."""

    # Pattern 1: data-sitekey attribute in HTML
    match = re.search(r'data-sitekey=["\']([0-9x][A-Za-z0-9_-]+)["\']', html)
    if match:
        return match.group(1)

    # Pattern 2: JavaScript render call
    match = re.search(r"sitekey:\s*['\"]([0-9x][A-Za-z0-9_-]+)['\"]", html)
    if match:
        return match.group(1)

    # Pattern 3: Turnstile config object
    match = re.search(r"siteKey['\"]?\s*[:=]\s*['\"]([0-9x][A-Za-z0-9_-]+)['\"]", html)
    if match:
        return match.group(1)

    return None

Üç modu da CaptchaAI ile çözme

İşin pratik tarafı burada: mod ne olursa olsun API çağrısı değişmez. sitekey ile pageurl'i turnstile yöntemine verirsiniz, gerisi aynıdır.

Somut bir örnek: bir Türk e-ticaret sitesinin ödeme akışını QA test ortamınızda doğruluyorsunuz. Giriş formu yönetilen modda, bülten kaydı ise etkileşimsiz modda çalışıyor olabilir; kodunuz ikisinde de tek satır değişmeden çalışır. Thread tabanlı planlar sayesinde maliyet de öngörülebilir kalır — USD üzerinden aylık sabit ücret (BASIC $15/ay, 5 thread'den başlar) TL kurundaki dalgalanmadan etkilenmez.

Python

import requests
import time

API_KEY = "YOUR_API_KEY"

def solve_turnstile(sitekey, page_url):
    """Solve any Turnstile mode — managed, non-interactive, or invisible."""
    submit = requests.post("https://ocr.captchaai.com/in.php", data={
        "key": API_KEY,
        "method": "turnstile",
        "sitekey": sitekey,
        "pageurl": page_url,
        "json": 1,
    })

    task_id = submit.json()["request"]

    for _ in range(60):
        time.sleep(5)
        result = requests.get("https://ocr.captchaai.com/res.php", params={
            "key": API_KEY,
            "action": "get",
            "id": task_id,
            "json": 1,
        }).json()

        if result.get("status") == 1:
            return result["request"]

    raise TimeoutError("Turnstile solve timed out")


# Use with any mode
token = solve_turnstile("0x4AAAAAAAC3DHQhMMQ_Rxrg", "https://staging.example.com/qa-login")
print(f"Token: {token[:50]}...")

Node.js

const axios = require("axios");

const API_KEY = "YOUR_API_KEY";

async function solveTurnstile(sitekey, pageUrl) {
  const submit = await axios.post("https://ocr.captchaai.com/in.php", null, {
    params: {
      key: API_KEY,
      method: "turnstile",
      sitekey,
      pageurl: pageUrl,
      json: 1,
    },
  });

  const taskId = submit.data.request;

  for (let i = 0; i < 60; i++) {
    await new Promise((r) => setTimeout(r, 5000));

    const result = await axios.get("https://ocr.captchaai.com/res.php", {
      params: { key: API_KEY, action: "get", id: taskId, json: 1 },
    });

    if (result.data.status === 1) {
      return result.data.request;
    }
  }

  throw new Error("Turnstile solve timed out");
}

// Same function works for all Turnstile modes
solveTurnstile("0x4AAAAAAAC3DHQhMMQ_Rxrg", "https://staging.example.com/qa-login")
  .then((token) => console.log("Token:", token.substring(0, 50)));

Modları tek bakışta karşılaştırma

Üç modu yan yana koyduğunuzda tablo netleşir: kullanıcıya yönelik davranış değişse de token çıktısı ve çözüm çağrısı sabittir.

Özellik Yönetilen Etkileşimsiz Görünmez
Widget görünür mü? Bazen Asla (yalnızca döndürücü) Asla
Kapsayıcı öğe gerekir mi? Evet Evet Evet (gizli)
Kullanıcı etkileşimi gerekir mi? Bazen (onay kutusu) Hayır Hayır
İş kanıtı (proof-of-work)? Evet (yükselebilir) Evet (her zaman) Evet (her zaman)
Onay kutusuna geri düşer mi? Evet Hayır (bunun yerine başarısız olur) Hayır (bunun yerine başarısız olur)
Token çıktısı cf-turnstile-response cf-turnstile-response cf-turnstile-response
CaptchaAI yöntemi turnstile turnstile turnstile
Nerede önerilir Giriş, kayıt Düşük sürtünmeli formlar Arka plan doğrulaması

Sık karşılaşılan sorunlar

Entegrasyonda en çok bu altı belirti karşınıza çıkar; her birinin nedeni ve çözümü aşağıda:

Belirti Neden Çözüm
Token geçerli ama form reddediyor sitekey yanlış (görünür widget'takinden farklı) JavaScript ile oluşturulan sitekey'i kontrol edin
Widget HTML'de bulunamıyor Görünmez mod ilk render'dan sonra yüklendi Sayfanın tam yüklenmesini bekleyin, XHR yanıtlarını inceleyin
Sayfada birden fazla Turnstile widget'ı Farklı formlar farklı sitekey kullanıyor sitekey'i ilgili formla eşleştirin
data-size="compact" tespiti şaşırtıyor Compact bir mod değil, boyut çeşididir Compact varsayılan olarak yönetilen modu kullanır
data-action özniteliği var Mod değil, analitik için eylem etiketi Doğrulama gerektiriyorsa eylemi çözüme dahil edin
Token gönderilmeden süresi doluyor Turnstile token'ları 300 saniyede geçersiz olur Göndermeden hemen önce çözün

Sık sorulan sorular

Turnstile çözümü CaptchaAI ile ne kadar sürer?

Cloudflare Turnstile tipik olarak 10 saniyenin altında, yüksek başarı oranıyla çözülür. Mod (yönetilen, etkileşimsiz veya görünmez) bu süreyi değiştirmez; API tarafındaki zorluk üçünde de aynıdır.

Yönetilen modda widget neden bazen görünüp bazen görünmüyor?

Çünkü yönetilen mod kararı ziyaretçinin sinyallerine göre verir. Yüksek güvenli isteklerde widget görünmeden geçer, şüpheli isteklerde onay kutusu çıkar. Aynı sitekey'de bile davranış değişebildiği için modu her gezinmede yeniden tespit edin.

Görünmez Turnstile'ı bir sayfada nasıl fark ederim?

data-size="invisible" özniteliğini ya da JavaScript render çağrısındaki size: 'invisible' değerini arayın. Kapsayıcının görünür boyutu olmadığından widget'ı gözle değil, HTML ve script içeriğini tarayarak bulursunuz.

Turnstile token'ı ne kadar süre geçerli kalır?

Turnstile token'ları üretildikten sonra 300 saniye içinde geçersiz olur. Bu yüzden token'ı çözer çözmez, formu göndermeden hemen önce kullanın.

BASIC plan Turnstile otomasyonu için yeterli mi?

Küçük hacimli işler için evet: BASIC planı ($15/ay, 5 thread) aynı anda 5 Turnstile çözümü çalıştırır ve thread başına sınırsız çözüm içerir. Eşzamanlı iş yükünüz büyüdükçe üst planlara geçebilirsiniz.

Özetle

Cloudflare Turnstile'ın üç widget modu — yönetilen, etkileşimsiz ve görünmez — kullanıcı deneyimini belirler ama hepsi aynı cf-turnstile-response token'ını üretir. Otomasyon açısından üçü de CaptchaAI'nin Turnstile çözücüsüyle aynı method=turnstile çağrısı üzerinden, tipik olarak 10 saniyenin altında ve yüksek başarı oranıyla çözülür. Geliştiriciyi ilgilendiren asıl fark tespittir: yönetilen mod görünür HTML bırakırken, görünmez mod sitekey'i bulmak için daha derin sayfa analizi gerektirir.

İlgili Makaleler

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