Görevi gönderdiniz; şimdi geri gelen düz metni doğru okumanız gerekiyor. CaptchaAI, JSON yerine boru (|) ile ayrılmış küçük metin yanıtları döndürür — ayrıştırması hızlıdır, ama hangi metnin token, hangisinin hata olduğunu bilmeniz gerekir. Bu referans, in.php ve res.php üzerinden karşılaşacağınız her yanıt biçimini ayrıştırma örnekleriyle gösterir.
Yanıtları dört biçime indirgeyin
Gelen her yanıt gövdesi yalnızca dört durumdan biridir; kodunuzu tek bir karar akışıyla yazabilirsiniz:
- Gövde tam olarak
CAPCHA_NOT_READYise → görev hâlâ işleniyor, 5 saniye bekleyip yeniden sorgulayın. - Gövde
OK|ile başlıyorsa → başarı;OK|'den sonraki kısım yüktür (token, OCR metni ya da anahtar/değer çiftleri). - Gövde
ERROR_ile başlıyorsa → hata kodu; eylem tablosuna bakın. - Boş ya da beklenmedik gövde → ağ katmanı sorunu; API hatasından ayrı ele alın.
reCAPTCHA, Turnstile, GeeTest v3 veya görüntü CAPTCHA'sı çözüyor olun; akış aynıdır — yalnızca OK|'den sonraki yük değişir.
Görev gönderme yanıtı (in.php)
Başarılı yanıt
OK|TASK_ID
Örnek: OK|73548291 — TASK_ID sonucu sorgularken kullanılır.
Hata yanıtı
ERROR_CODE
Python ve Node.js ile ayrıştırma
Gönderim yanıtını ayrıştırmanın kalıbı her iki dilde de aynıdır: önce OK| önekini kontrol edin, sonra görev kimliğini | ayracından alın.
resp = requests.get("https://ocr.captchaai.com/in.php", params={...})
if resp.text.startswith("OK|"):
task_id = resp.text.split("|")[1]
else:
error = resp.text
raise Exception(f"Submit failed: {error}")
const resp = await axios.get("https://ocr.captchaai.com/in.php", { params });
if (resp.data.startsWith("OK|")) {
const taskId = resp.data.split("|")[1];
} else {
throw new Error(`Submit failed: ${resp.data}`);
}
Sonuç sorgulama yanıtı (res.php)
Görev kimliğini aldıktan sonra res.php'yi periyodik sorgularsınız. Sorgulama şu beş yanıttan biriyle karşılık verir:
- Henüz hazır değil — görev sırada, sorgulamayı sürdürün.
- Token tabanlı sonuç — reCAPTCHA ve Turnstile için tek uzun token.
- Görüntü / OCR sonucu — tanınan kısa metin.
- GeeTest v3 sonucu — virgülle ayrılmış üç alan.
- Cloudflare doğrulama akışı sonucu — çerez ve kullanıcı aracısı çifti.
Bir de hata durumu vardır; her birini sırayla görelim.
"Henüz hazır değil" yanıtı
CAPCHA_NOT_READY
Bu bir hata değildir:
- Görev hâlâ sırada; işlenmeyi bekliyor.
- 5 saniye bekleyip aynı görev kimliğiyle yeniden sorgulayın.
Token tabanlı CAPTCHA'lar (reCAPTCHA, Turnstile)
reCAPTCHA, Cloudflare Turnstile ve diğer token tabanlı doğrulamalar için OK|'den sonra tek bir uzun token gelir:
OK|03AGdBq24PBCbw...long_token_string
Görüntü / OCR CAPTCHA'ları
OK|abc123
OK|'den sonraki metin, görüntüden tanınan metindir.
GeeTest v3 yanıtı
OK|challenge:abc123,validate:def456,seccode:ghi789
Yanıt virgülle ayrılmış üç alan içerir; üçünü de ayrıştırıp hedef forma birlikte gönderin:
challengevalidateseccode
if result.text.startswith("OK|"):
data = result.text.split("|")[1]
parts = dict(item.split(":") for item in data.split(","))
challenge = parts["challenge"]
validate = parts["validate"]
seccode = parts["seccode"]
Cloudflare doğrulama akışı yanıtı
qa_session_cookie çerez değerini ve kullanıcı aracısını (user agent) noktalı virgülle ayrılmış olarak döndürür:
OK|qa_session_cookie=abc123;user_agent=Mozilla/5.0...
Hata yanıtı
ERROR_CODE
Tek fonksiyonda ayrıştırma şablonu
Dört durumu tek bir fonksiyonda toplarsanız çağrı tarafındaki kod sadeleşir:
def parse_result(response_text):
if response_text == "CAPCHA_NOT_READY":
return {"status": "pending"}
if response_text.startswith("OK|"):
return {"status": "solved", "result": response_text.split("|", 1)[1]}
return {"status": "error", "error": response_text}
CAPTCHA türüne göre yanıt içeriği
Aşağıdaki tablo, desteklenen her tür için OK|'den sonra ne geldiğini ve onu nasıl kullanacağınızı özetler. GeeTest v4 için destek çok yakında; hCaptcha ve FunCaptcha (Arkose Labs) ise henüz desteklenmemektedir.
| CAPTCHA türü | method |
OK| sonrası yük |
Nasıl kullanılır |
|---|---|---|---|
| reCAPTCHA v2 / v3 | userrecaptcha |
Tek token (~500 karakter) | g-recaptcha-response alanına gönderin |
| Cloudflare Turnstile | turnstile |
Tek token | cf-turnstile-response alanına gönderin |
| GeeTest v3 | geetest |
challenge:..,validate:..,seccode:.. |
Virgülden bölün, üç alanı da gönderin |
| Görüntü / OCR | post |
Tanınan metin | Metin yanıtı olarak gönderin |
| Cloudflare doğrulama akışı | cloudflare_challenge |
qa_session_cookie=..;user_agent=.. |
Çerez ve UA'yı HTTP istemcinize ayarlayın |
Tabloyu okurken iki noktaya dikkat edin:
- Hedef sayfadaki alan adı siteye özgüdür; kesin adı formdan ya da sayfa JavaScript'inden doğrulayın.
OK|sonrası yükü olduğu gibi saklayın; token'ı kırpmak ya da yeniden biçimlendirmek hedef sitede reddedilmesine yol açar.
Bakiye uç noktası (getbalance)
GET https://ocr.captchaai.com/res.php?key=API_KEY&action=getbalance
Yanıt:
1.234
Dönen gövde hakkında iki nokta:
- Değer her zaman ABD doları cinsinden bir ondalık sayıdır, TL değil.
- Ayrı bir durum sarmalayıcısı yoktur; sayıya dönüştürme başarısızsa yanıtı ağ hatası olarak ele alın.
balance = float(requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY, "action": "getbalance"
}).text)
print(f"Balance: ${balance:.2f}")
Çözüm bildirimi uç noktaları
Çözüm sonucunu geri bildirmek isteğe bağlıdır, ama doğruluğu iyileştirmeye yardımcı olur. İki uç nokta vardır:
İyi bildir (doğru çözüm)
GET https://ocr.captchaai.com/res.php?key=API_KEY&action=reportgood&id=TASK_ID
Yanıt: OK_REPORT_RECORDED
Kötü bildir (yanlış çözüm)
GET https://ocr.captchaai.com/res.php?key=API_KEY&action=reportbad&id=TASK_ID
Yanıt: OK_REPORT_RECORDED
Yanlış çözümleri bildirmek doğruluğun artmasına yardımcı olur ve bakiyenize yansıtılabilir.
Yaygın hata kodları
Tüm kodlar ve karşılığı
| Hata Kodu | Anlamı | Eylem |
|---|---|---|
ERROR_WRONG_USER_KEY |
Geçersiz API anahtarı | Anahtarınızı doğrulayın |
ERROR_KEY_DOES_NOT_EXIST |
Anahtar kayıtlı değil | Kontrol panelini kontrol edin |
ERROR_ZERO_BALANCE |
Yetersiz bakiye | Bakiye ekleyin |
ERROR_NO_SLOT_AVAILABLE |
Sunucu kapasitede | 5 saniye sonra yeniden deneyin |
ERROR_CAPTCHA_UNSOLVABLE |
CAPTCHA çok zor | Yeni bir CAPTCHA ile yeniden deneyin |
ERROR_BAD_DUPLICATES |
Yinelenen görev reddedildi | Yeniden göndermeden önce bekleyin |
ERROR_WRONG_CAPTCHA_ID |
Geçersiz görev kimliği | Görev kimliği değerini kontrol edin |
ERROR_EMPTY_ACTION |
action parametresi eksik |
action=get ekleyin |
IP_BANNED |
Çok fazla hatalı istek | API anahtarınızı düzeltin ve bekleyin |
Hata sınıfına göre tepki
Hata kodlarını tek tek ezberlemek yerine verilecek tepkiye göre gruplayın; bu, yeniden deneme mantığınızı temiz tutar:
| Sınıf | Örnekler | Tepki |
|---|---|---|
| Kimlik / hesap | ERROR_WRONG_USER_KEY, ERROR_ZERO_BALANCE, IP_BANNED |
Durun. Yapılandırmayı düzeltin veya bakiye ekleyin — yeniden denemeyin. |
| Parametre | ERROR_EMPTY_ACTION, ERROR_WRONG_CAPTCHA_ID |
Durun. İstek gövdesini düzeltin. |
| Geçici | ERROR_NO_SLOT_AVAILABLE, HTTP 429/5xx |
Üstel geri çekilme (exponential backoff) ile yeniden deneyin. |
| Göreve özgü | ERROR_CAPTCHA_UNSOLVABLE, ERROR_BAD_DUPLICATES |
Yeni bir görev gönderin. |
Boş yanıtlar ve ağ hataları
Dört durumdan sonuncusu — boş ya da beklenmedik gövde — bir API hatası değil, ağ katmanı sorunudur; bu yüzden ERROR_ kodlarından ayrı ele alın:
- Gövde boşsa ya da
OK|/ERROR_/CAPCHA_NOT_READYkalıplarının hiçbirine uymuyorsa, ayrıştırmadan önce HTTP durum kodunu kontrol edin. ConnectionErrorve zaman aşımı (timeout) durumlarında isteği kısa bir gecikmeyle birkaç kez yeniden deneyin; bunlar çoğunlukla geçici DNS, çıkış (egress) ya da TLS yapılandırması kaynaklıdır.- İstemci tarafındaki hata kalıcı hâle geliyorsa sorunu API tarafında değil kendi ağ yapılandırmanızda arayın.
Uçtan uca sorgulama örneği
Aşağıdaki fonksiyon gönderme, sorgulama, zaman aşımı ve hata durumlarını tek yerde toplar — kendi çözücünüzün iskeletini bunun üzerine kurabilirsiniz:
import requests
import time
API_KEY = "YOUR_API_KEY"
def solve_captcha(submit_params, timeout=300):
"""Generic solver with proper response handling."""
submit_params["key"] = API_KEY
# Submit
resp = requests.get("https://ocr.captchaai.com/in.php", params=submit_params)
if not resp.text.startswith("OK|"):
raise Exception(f"Submit error: {resp.text}")
task_id = resp.text.split("|")[1]
# Poll
deadline = time.time() + timeout
while time.time() < deadline:
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY,
"action": "get",
"id": task_id
})
parsed = parse_result(result.text)
if parsed["status"] == "pending":
continue
elif parsed["status"] == "solved":
return parsed["result"]
else:
raise Exception(f"Solve error: {parsed['error']}")
raise TimeoutError(f"Task {task_id} timed out after {timeout}s")
Yerel not: bakiye ve faturalama
Türkiye'deki geliştiriciler için USD faturalama bir avantajdır: CaptchaAI planları thread bazlı ve USD üzerinden faturalanır — örneğin BASIC ($15/ay, 5 thread) — böylece kur dalgalanmasından bağımsız, öngörülebilir bir aylık maliyet elde edersiniz. Ayrıca veri toplama otomasyonu kurarken, kazınan kişisel verilerin KVKK kapsamına girdiğini unutmayın.
Sık sorulan sorular
CAPCHA_NOT_READY yanıtı bir hata mı?
Hayır. Bu yanıt yalnızca görevin hâlâ işlendiği anlamına gelir. Onu hata gibi ele almayın; 5 saniye bekleyip OK| ya da bir ERROR_ kodu gelene kadar sorgulamayı sürdürün.
Bakiyem hangi para biriminde döner?
getbalance her zaman USD cinsinden bir ondalık sayı döndürür. TL'ye çevrilmiş bir değer beklemeyin; arayüzde de faturalandırma da USD üzerindendir.
Hangi hata kodlarında yeniden deneme yapmamalıyım?
Kimlik ve hesap sınıfındaki hatalarda (ERROR_WRONG_USER_KEY, ERROR_ZERO_BALANCE, IP_BANNED) yeniden denemeyin — bunlar yapılandırma veya bakiye sorunudur ve aynı istekte kalıcı olarak başarısız olur. Yalnızca geçici sınıftaki hataları (ERROR_NO_SLOT_AVAILABLE, HTTP 429/5xx) geri çekilmeyle yeniden deneyin.
Token'ı ayrıştırırken neden split("|", 1) kullanmalıyım?
reCAPTCHA token'ları ~500 karaktere kadar uzayabilir ve kendi içinde | karakteri barındırabilir. Bölme sayısını 1 ile sınırlayan split("|", 1), token'ın yanlışlıkla parçalanmasını engeller.
Yanıt neden JSON değil de | ayracı kullanıyor?
CaptchaAI'nin düz metin biçimi hız ve basitlik için tasarlanmıştır: boruyla ayrılmış yanıtlar JSON'a göre daha küçüktür ve ayrıştırılması daha hızlıdır. GeeTest gibi yapılandırılmış sonuçlarda OK|'den sonraki metin anahtar/değer çiftleri içerir.