Anda solve CAPTCHA Turnstile dan mendapat token yang valid, tapi situs target masih mengembalikan 403 Forbidden. Panduan ini mencakup setiap penyebab.
Mengapa 403 Setelah Token Valid?
| Penyebab | Kemungkinan |
|---|---|
| Cookie qa_validation_cookie tidak ada | Sangat umum |
| Token kedaluwarsa | Umum |
| Endpoint submit salah | Umum |
| Header request tidak ada | Sedang |
| IP mismatch antara solving dan submit | Sedang |
| Cloudflare Challenge (bukan Turnstile) | Kadang tertukar |
Penyebab 1: Cookie qa_validation_cookie Tidak Ada
Turnstile menetapkan cookie selama validasi. Jika Anda tidak menyertakan cookie ini dalam request berikutnya, Cloudflare akan memblokir Anda.
import requests
session = requests.Session()
# Step 1: Load the page to get initial cookies
session.get("https://example.com")
# Step 2: Solve Turnstile
token = solve_turnstile(
api_key="YOUR_API_KEY",
sitekey="TURNSTILE_SITEKEY",
pageurl="https://example.com",
)
# Step 3: Submit token to the validation endpoint
# This sets qa_validation_cookie cookie
resp = session.post("https://example.com/api/verify", data={
"cf-turnstile-response": token,
}, headers={
"Content-Type": "application/x-www-form-urlencoded",
"Origin": "https://example.com",
"Referer": "https://example.com/",
})
# Step 4: Now make your actual request WITH the session cookies
resp = session.get("https://example.com/protected-page")
print(resp.status_code) # Should be 200 now
Penyebab 2: Token Kedaluwarsa
Token Turnstile bertahan ~300 detik, tapi gunakan segera untuk hasil terbaik.
import time
# Solve
start = time.time()
token = solve_turnstile(...)
solve_time = time.time() - start
# Check if token is still fresh
if solve_time > 240: # > 4 minutes is risky
print("Token may be too old, solving again...")
token = solve_turnstile(...)
# Submit immediately
submit_token(token)
Penyebab 3: Cara Submit yang Salah
Cari tahu cara situs mengirimkan token Turnstile:
# Some sites use a hidden form field
data = {
"cf-turnstile-response": token,
"username": "user",
"password": "pass",
}
# Some sites use a custom header
headers = {
"X-Turnstile-Token": token,
}
# Some sites use JSON body
json_data = {
"turnstileToken": token,
"email": "user@example.com",
}
Cara menemukan nama field yang benar:
- Buka tab Network di browser DevTools
- Solve challenge Turnstile secara manual
- Temukan request submit form
- Lihat isi request untuk nama field token
Penyebab 4: Header Hilang
Cloudflare memeriksa header permintaan untuk konsistensi:
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.9",
"Origin": "https://example.com",
"Referer": "https://staging.example.com/qa-login",
"Sec-Fetch-Dest": "document",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Site": "same-origin",
}
session.headers.update(headers)
Penyebab 5: Cloudflare Challenge vs Turnstile
Turnstile dan Cloudflare Challenge adalah sistem yang berbeda:
| Fitur | Turnstile | Cloudflare Challenge |
|---|---|---|
| Widget | Kotak centang terlihat di halaman | Challenge full-page |
| Metode CaptchaAI | turnstile |
cloudflare_challenge |
| Field token | cf-turnstile-response |
N/A (berbasis cookie) |
Jika Anda melihat challenge full-page, gunakan method=cloudflare_challenge sebagai gantinya.
Contoh Kerja Lengkap
import requests
import time
import re
def solve_turnstile_and_access(target_url, api_key):
"""Complete flow: solve Turnstile and access protected page."""
session = requests.Session()
session.headers.update({
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
})
# Load page, get cookies and sitekey
resp = session.get(target_url)
match = re.search(r'data-sitekey="([^"]+)"', resp.text)
if not match:
raise RuntimeError("Turnstile sitekey not found")
sitekey = match.group(1)
# Solve via CaptchaAI
submit_resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": api_key,
"method": "turnstile",
"sitekey": sitekey,
"pageurl": target_url,
"json": 1,
}, timeout=30)
task_id = submit_resp.json()["request"]
# Poll
for _ in range(12):
time.sleep(5)
poll = requests.get("https://ocr.captchaai.com/res.php", params={
"key": api_key, "action": "get",
"id": task_id, "json": 1,
}, timeout=15)
data = poll.json()
if data.get("status") == 1:
token = data["request"]
break
else:
raise TimeoutError("Solve timeout")
# Submit token using the same session
form_resp = session.post(target_url, data={
"cf-turnstile-response": token,
}, headers={
"Origin": f"https://{requests.utils.urlparse(target_url).netloc}",
"Referer": target_url,
})
return session, form_resp
# Usage
session, resp = solve_turnstile_and_access(
"https://staging.example.com/qa-login",
"YOUR_API_KEY",
)
# session now has valid cookies for subsequent requests
Pemecahan Masalah
| Masalah | Penyebab | Solusi |
|---|---|---|
| 403 meskipun token valid | Cookie sesi tidak ada | Gunakan sesi yang sama untuk semua request |
| 403 di halaman berikutnya | qa_validation_cookie tidak di-set | Validasi token harus mengembalikan cookie |
| Berhasil sekali, lalu 403 | Cookie kedaluwarsa | Solve ulang untuk cookie baru |
| Selalu 403 | Challenge full-page, bukan Turnstile | Gunakan metode cloudflare_challenge |
Pertanyaan Umum
Berapa lama qa_validation_cookie bertahan?
Biasanya 30 menit hingga 24 jam. Jika request berikutnya mulai gagal, solve ulang Turnstile.
Apakah saya perlu proxy untuk Turnstile?
Seringkali tidak — tingkat keberhasilan CaptchaAI di Turnstile biasanya bekerja tanpa proxy. Tambahkan proxy hanya jika situs memeriksa konsistensi IP.
Bisakah saya meneruskan qa_validation_cookie ke sesi lain?
Ya, tapi terikat pada User-Agent dan mungkin terikat pada IP. Jaga keduanya konsisten.
Panduan Terkait
- Diagnosis Tingkat Keberhasilan Solve CAPTCHA
- Cara Solve Cloudflare Turnstile via API