Kenapa satu form Turnstile menampilkan checkbox, form lain cuma spinner sekejap, dan form ketiga tidak menampilkan tanda widget sama sekali? Bukan bug — itu tiga mode widget yang berbeda, dan ketiganya tetap menghasilkan token cf-turnstile-response yang sama untuk di-solve.
Singkatnya:
- Managed — Cloudflare menentukan level challenge per pengunjung, widget kadang terlihat kadang tidak.
- Non-interactive — cuma proof-of-work di background, UI tidak pernah tampil.
- Invisible — tidak ada container yang terlihat sama sekali di viewport.
Apakah Mode Widget Ini Memengaruhi Cara CaptchaAI Solve?
Tidak. CaptchaAI memakai method turnstile untuk ketiga mode dengan parameter yang sama: sitekey dan page URL. Yang berbeda cuma tampilan ke pengguna dan cara Anda mendeteksinya dari HTML.
Ringkasan Perbedaan Ketiga Mode
| Fitur | Managed | Non-interactive | Invisible |
|---|---|---|---|
| Widget terlihat? | Terkadang | Tidak pernah (hanya spinner) | Tidak pernah |
| Butuh elemen container? | Ya | Ya | Ya (tersembunyi) |
| Butuh interaksi pengguna? | Terkadang (checkbox) | Tidak | Tidak |
| Ada proof-of-work challenge? | Ya (bisa naik eskalasi) | Ya (selalu) | Ya (selalu) |
| Ada fallback ke checkbox interaktif? | Ya | Tidak (langsung gagal) | Tidak (langsung gagal) |
| Output token | cf-turnstile-response |
cf-turnstile-response |
cf-turnstile-response |
| Method CaptchaAI | turnstile |
turnstile |
turnstile |
| Cocok dipakai untuk | Login, registrasi | Form low-friction | Verifikasi background |
Mode Managed: Cloudflare yang Menentukan Level Challenge
Managed adalah mode default. Cloudflare memutuskan level challenge per pengunjung berdasarkan sinyal reputasi: sebagian besar lolos tanpa UI, traffic mencurigakan melihat checkbox, traffic sangat mencurigakan bisa menghadapi challenge lebih rumit.
Implementasi
<!-- 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>
Yang Dilihat Otomasi
Mode managed beradaptasi berdasarkan sinyal reputasi pemohon:
- Kepercayaan tinggi — lolos invisible, tidak ada UI terlihat
- Kepercayaan sedang — widget checkbox, klik untuk verifikasi
- Kepercayaan rendah — challenge interaktif, atau blok langsung
Untuk otomasi, managed paling sering ditemui sekaligus paling sulit ditebak.
Heuristik untuk deteksi dari HTML: elemen cf-turnstile ada, tapi tidak ada atribut mode eksplisit.
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
Mode Non-Interactive: Proof-of-Work Tanpa Checkbox
Mode ini tidak pernah menampilkan checkbox. Proof-of-work berjalan di background, dan yang muncul di layar cuma spinner loading. Kalau challenge gagal diselesaikan secara non-interactive, prosesnya langsung gagal — tidak ada eskalasi ke checkbox seperti pada mode managed. Markup-nya:
<!-- Non-interactive mode -->
<div class="cf-turnstile"
data-sitekey="0x4AAAAAAAC3DHQhMMQ_Rxrg"
data-appearance="interaction-only">
</div>
Atau lewat JavaScript API:
turnstile.render('#turnstile-container', {
sitekey: '0x4AAAAAAAC3DHQhMMQ_Rxrg',
appearance: 'interaction-only',
callback: function(token) {
document.getElementById('cf-turnstile-response').value = token;
},
});
Alurnya di balik layar:
Page loads → Widget initializes
↓
Background proof-of-work runs
↓
Success → Token generated (no visible UI)
OR
Failure → Widget reports error (no fallback to checkbox)
Kapan Situs Pakai Mode Ini
| Skenario | Kenapa non-interactive |
|---|---|
| Form komentar, widget feedback | Friction harus mendekati nol |
| Pendaftaran newsletter | Aksi bernilai rendah |
| API endpoint sisi browser | Proteksi tanpa mengganggu UX |
Mode Invisible: Container yang Sepenuhnya Tersembunyi
Mode invisible benar-benar tidak kelihatan — tidak ada elemen container yang muncul di viewport. Widget jalan otomatis saat page load (atau dipicu lewat kode), lalu menghasilkan token tanpa indikasi visual apa pun.
Implementasi
<!-- Invisible mode — container is hidden -->
<div id="turnstile-invisible"
class="cf-turnstile"
data-sitekey="0x4AAAAAAAC3DHQhMMQ_Rxrg"
data-size="invisible">
</div>
Atau sepenuhnya lewat JavaScript:
// 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');
},
});
Turnstile invisible lebih sulit dideteksi karena containernya tidak punya dimensi yang terlihat — perlu mengecek beberapa indikator sekaligus:
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"}
Cara Ambil Sitekey, Apa Pun Mode yang Dipakai Situs
Apa pun modenya, Anda tetap butuh sitekey untuk solve. Fungsi berikut mencoba tiga pola — atribut HTML, config JavaScript, render call — sekaligus:
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
Solve Turnstile via API CaptchaAI — Contoh Python dan Node.js
Ketiga mode di-solve dengan alur yang identik, tidak peduli mode-nya:
- Submit sitekey dan page URL ke
in.php - Simpan task ID dari respons
- Polling
res.phptiap 5 detik sampai token siap
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)));
Konteks lokal: tim price-monitoring atau agency scraping freelance yang deploy dari ap-southeast-1/asia-southeast2 dan pakai banyak thread paralel — ingat CaptchaAI menagih per thread konkuren, bukan per solve, jadi BASIC ($15/bulan, 5 thread) sudah cukup untuk memantau puluhan target.
Troubleshooting: Kenapa Token Ditolak atau Widget Tidak Ketemu
- Token valid tapi form menolaknya — sitekey salah, beda dari widget yang terlihat. Periksa sitekey yang dirender lewat JavaScript.
- Widget tidak ditemukan di HTML — mode invisible dimuat setelah render awal. Tunggu page load penuh, periksa respons XHR.
- Ada beberapa widget Turnstile di satu halaman — sitekey beda untuk form beda. Cocokkan sitekey dengan form yang spesifik.
data-size="compact"bikin deteksi salah baca — compact itu varian ukuran, bukan mode. Tetap pakai managed secara default.- Atribut
data-actionada — itu tag analitik, bukan mode. Sertakan saat solve kalau diperlukan validasi. - Token kedaluwarsa sebelum disubmit — token Turnstile berlaku 300 detik. Solve sesaat sebelum submit, jangan cache.
Pertanyaan yang Sering Diajukan
Pertanyaan yang paling sering muncul seputar mode widget Turnstile:
Berapa lama waktu penyelesaian Turnstile lewat CaptchaAI?
Biasanya di bawah 10 detik dengan tingkat keberhasilan tinggi, sama untuk ketiga mode karena tantangan di level API identik.
Bagaimana cara mengetahui mode Turnstile yang dipakai sebuah situs?
Cek atribut data-appearance atau data-size di HTML: data-size="invisible" berarti invisible, data-appearance="interaction-only" berarti non-interactive, tidak ada keduanya berarti managed (default).
Apakah non-interactive berarti CAPTCHA-nya lebih mudah diselesaikan?
Tidak. Proof-of-work tetap jalan di semua mode — non-interactive cuma menyembunyikan UI-nya. Dari sisi solving, ketiganya setara.
Bisakah satu situs mengganti mode Turnstile tanpa mengubah sitekey?
Bisa. Beberapa situs pakai managed default lalu beralih ke non-interactive untuk halaman tertentu, sitekey tetap sama. Deteksi ulang mode tiap navigasi.
Mode mana yang paling sering muncul di form checkout atau login?
Managed untuk login dan registrasi. Non-interactive untuk form bernilai rendah seperti newsletter atau komentar. Invisible untuk verifikasi latar belakang yang tidak boleh mengganggu alur checkout.
Ringkasan Singkat
Tiga mode widget Cloudflare Turnstile — managed, non-interactive, invisible — mengatur pengalaman pengguna, tapi menghasilkan token cf-turnstile-response yang sama. Untuk otomasi, semua mode di-solve identik lewat Turnstile solver CaptchaAI, biasanya di bawah 10 detik dengan tingkat keberhasilan tinggi.
Yang perlu diingat:
- Mode cuma memengaruhi tampilan, bukan parameter API atau token.
- Deteksi mode dari
data-appearance/data-size, bukan dari perilaku solve. - Managed paling umum tapi paling variatif; invisible paling sulit dideteksi.