Turnstile tidak pernah menampilkan puzzle atau kotak centang. Yang terjadi di balik layar: CaptchaAI membaca sinyal browser itu lewat API dan mengembalikan token cf-turnstile-response yang tinggal disuntik ke form target Anda — biasanya dalam kurang dari 10 detik.
Panduan ini untuk tim otomasi dan QA yang form-nya harus tetap bisa disubmit lewat script, bukan dibuka satu-satu secara manual. Anda akan mengikuti alur yang sama dengan integrasi CaptchaAI lain: kirim task, simpan ID-nya, polling, lalu pakai token. Kalau belum pernah pakai API CaptchaAI sama sekali, mulai dari panduan quickstart dulu supaya empat langkah ini terasa familiar.
Yang Anda perlukan sebelum mulai
Siapkan empat hal ini sebelum masuk ke Langkah 1 — tanpa salah satunya, task akan ditolak backend CaptchaAI:
| Item | Nilai |
|---|---|
| API key CaptchaAI | Dari dashboard di captchaai.com |
| Sitekey Turnstile | Diekstrak dari halaman target (diawali 0x) |
| URL halaman | URL lengkap tempat Turnstile muncul |
| Bahasa | Python 3.7+ atau Node.js 14+ |
Langkah 1: Cari sitekey Turnstile di halaman target
Sitekey biasanya nongol di HTML halaman, di dalam tag div atau script:
<div class="cf-turnstile" data-sitekey="0x4AAAAAAAC3DHQFLr1GavNl"></div>
Atau di-render lewat JavaScript:
turnstile.render('#widget', {
sitekey: '0x4AAAAAAAC3DHQFLr1GavNl',
callback: function(token) { /* ... */ }
});
Tiga cara mengambilnya kalau tidak langsung terlihat:
- DevTools browser — buka tab Elements, cari
data-sitekeyataucf-turnstile. - Lihat source —
Ctrl+U, cari string yang diawali0x. - Tab Network — filter request ke
challenges.cloudflare.com; sitekey ada di parameternya.
Sitekey Turnstile selalu diawali
0xdan panjangnya sekitar 22 karakter — beda pola dari sitekey reCAPTCHA yang mulai dengan6L.
Langkah 2: Kirim task ke API CaptchaAI
Task-nya sederhana: POST ke https://ocr.captchaai.com/in.php dengan method=turnstile, sitekey, dan pageurl.
import requests
API_KEY = "YOUR_CAPTCHAAI_KEY"
SITEKEY = "0x4AAAAAAAC3DHQFLr1GavNl"
PAGEURL = "https://staging.example.com/qa-login"
r = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": "turnstile",
"sitekey": SITEKEY,
"pageurl": PAGEURL,
"json": 1,
})
data = r.json()
if data["status"] != 1:
raise RuntimeError(f"submit failed: {data}")
task_id = data["request"]
print("task id:", task_id)
Kalau stack Anda Node.js, logikanya identik:
const axios = require("axios");
const { data } = await axios.post("https://ocr.captchaai.com/in.php", null, {
params: {
key: process.env.CAPTCHAAI_KEY,
method: "turnstile",
sitekey: "0x4AAAAAAAC3DHQFLr1GavNl",
pageurl: "https://staging.example.com/qa-login",
json: 1,
},
});
if (data.status !== 1) throw new Error(`submit failed: ${JSON.stringify(data)}`);
const taskId = data.request;
Kalau berhasil, respons-nya {"status": 1, "request": "<task_id>"}. Simpan task_id ini — dipakai di Langkah 3 untuk polling.
Langkah 3: Polling sampai token siap
Turnstile umumnya kelar dalam waktu kurang dari 10 detik. Beri jeda 10 detik dulu sebelum polling pertama, lalu ulangi tiap 5 detik sampai maksimum 40 kali percobaan:
import time
time.sleep(10)
for _ in range(40):
r = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY,
"action": "get",
"id": task_id,
"json": 1,
})
res = r.json()
if res["status"] == 1:
token = res["request"]
break
if res["request"] != "CAPCHA_NOT_READY":
raise RuntimeError(f"solver error: {res}")
time.sleep(5)
else:
raise TimeoutError("turnstile solving timed out")
print("token (60 karakter pertama):", token[:60])
Token yang dikembalikan adalah string Base64, biasanya diawali 0. dan panjangnya 400–600 karakter.
Langkah 4: Suntik token ke form dan submit
Setelah token di tangan, masukkan ke field tersembunyi cf-turnstile-response pada form Turnstile, baru submit formnya.
Kalau pakai Selenium:
driver.execute_script(
"document.querySelector('[name=cf-turnstile-response]').value = arguments[0];",
token,
)
driver.find_element("css selector", "form").submit()
Kalau pakai Playwright:
page.evaluate(
"(t) => document.querySelector('[name=cf-turnstile-response]').value = t",
token,
)
page.click("button[type=submit]")
Kalau cuma request HTTP biasa: tambahkan cf-turnstile-response=<token> ke body application/x-www-form-urlencoded sebelum dikirim.
Token Turnstile hanya berlaku sekitar 120–300 detik. Pakai secepatnya setelah diterima — kalau kelamaan, backend target akan menolaknya dengan
timeout-or-duplicatedan Anda harus solve ulang dari Langkah 2.
Contoh Python siap pakai
Gabungan keempat langkah di atas dalam satu fungsi, tinggal import dan panggil:
import os, time, requests
API = "https://ocr.captchaai.com"
KEY = os.environ["CAPTCHAAI_KEY"]
def solve_turnstile(sitekey: str, pageurl: str) -> str:
r = requests.post(f"{API}/in.php", data={
"key": KEY, "method": "turnstile",
"sitekey": sitekey, "pageurl": pageurl, "json": 1,
}, timeout=30)
j = r.json()
if j["status"] != 1:
raise RuntimeError(f"submit: {j}")
tid = j["request"]
time.sleep(10)
for _ in range(40):
r = requests.get(f"{API}/res.php", params={
"key": KEY, "action": "get", "id": tid, "json": 1,
}, timeout=30)
j = r.json()
if j["status"] == 1:
return j["request"]
if j["request"] != "CAPCHA_NOT_READY":
raise RuntimeError(f"poll: {j}")
time.sleep(5)
raise TimeoutError("timeout")
if __name__ == "__main__":
print(solve_turnstile("0x4AAAAAAAC3DHQFLr1GavNl", "https://staging.example.com/qa-login"))
Kalau Turnstile gagal di-solve
Lima penyebab paling sering ditemui tim yang baru mengintegrasikan Turnstile — tidak berurutan, cek yang paling relevan dengan gejala Anda dulu:
- Sitekey berubah tiap kunjungan. Sebagian situs Cloudflare menerbitkan sitekey baru setiap halaman dimuat ulang. Jangan hardcode — scrape ulang sitekey sebelum tiap task dikirim.
pageurlharus persis sama. Backend Turnstile mencocokkan URL secara ketat terhadap sitekey. Kirim path final apa adanya, tanpa query string tambahan yang tidak perlu.- Klien HTTP polos gampang ditolak Cloudflare. Kalau permintaan langsung (bukan lewat browser) sering kena block sebelum sempat submit token, pola koneksinya kemungkinan beda dari browser asli. Pindah ke
curl_cffi, Playwright, atau browser sungguhan biasanya menyelesaikannya. - Token kedaluwarsa sebelum sempat dipakai. Solve-nya sukses tapi form Anda baru submit dua menit kemudian? Solve ulang saja, jangan paksakan token lama.
- Jaringan lambat menambah risiko tantangan tambahan. Ini lebih terasa di koneksi mobile atau lewat IP datacenter murah. Pakai egress jaringan yang diotorisasi, dan kalau server Anda jalan dari region Asia Tenggara (mis. Singapura atau Jakarta), pastikan latensi ke
ocr.captchaai.comstabil sebelum menyalahkan solver-nya.
Kode error yang sering muncul
Kalau task ditolak atau solve gagal, cek dulu tabel ini sebelum membuka tiket support:
| Kode | Arti | Tindakan |
|---|---|---|
ERROR_WRONG_USER_KEY |
Format API key salah | Pastikan CAPTCHAAI_KEY disalin utuh, tanpa spasi tersisa |
ERROR_KEY_DOES_NOT_EXIST |
API key tidak dikenali | Salin ulang key langsung dari dashboard |
ERROR_ZERO_BALANCE |
Saldo habis | Top up saldo, lalu kirim ulang task |
ERROR_PAGEURL |
Parameter pageurl hilang atau tidak lengkap |
Kirim URL penuh yang berawalan https:// |
ERROR_CAPTCHA_UNSOLVABLE |
Gagal setelah beberapa kali percobaan | Cek kecocokan sitekey dan pageurl, lalu coba kirim task baru |
Tabel error yang lebih lengkap ada di panduan solve reCAPTCHA v2 — kode-kodenya banyak yang sama lintas tipe CAPTCHA.
Pertanyaan seputar solve Turnstile via API
Apakah solve Turnstile lewat API CaptchaAI perlu proxy?
Tidak wajib. Submit task cukup butuh sitekey dan pageurl yang valid — beda dengan Cloudflare Challenge yang kadang perlu parameter proxy tambahan. Kalau situs target punya proteksi reputasi IP yang ketat, kualitas jaringan tetap berpengaruh ke kelancaran solve, bukan ke pemanggilan API-nya.
Kenapa token Turnstile saya ditolak padahal status solve sudah sukses?
Dua penyebab paling umum: token dipakai lewat dari masa berlakunya (sekitar 120–300 detik), atau pageurl yang dikirim saat submit task tidak persis sama dengan URL halaman form aslinya. Backend Turnstile mencocokkan token ke pageurl secara ketat.
Bisakah API ini dipakai untuk Turnstile di WebView aplikasi mobile?
Bisa, selama Anda tetap bisa mengekstrak sitekey dan pageurl dari halaman yang dirender WebView tersebut. Alurnya sama persis dengan browser desktop: kirim task, polling, lalu suntikkan token ke field cf-turnstile-response sebelum form disubmit.
Berapa thread yang idealnya dipakai untuk volume solve Turnstile harian?
Tergantung volume. Tim kecil yang baru uji coba biasanya cukup dengan BASIC ($15/bulan, 5 thread); begitu volume harian mulai stabil dan butuh solve paralel lebih banyak, naik ke STANDARD ($30/bulan, 15 thread) atau ADVANCE ($90/bulan, 50 thread). Karena tiap thread dapat solve tanpa batas, biaya bulanan tetap flat berapa pun jumlah task yang lewat.