Captcha token süresi doldu: nedenleri ve nasıl düzeltilir
Captcha token'ı, bir doğrulamanın geçildiğine dair kısa ömürlü bir kanıttır. Scarnox'un PopularCaptcha token'ları, verildikten yaklaşık iki dakika sonra süresi dolar. Token'ı bu pencerenin dışında gönderirseniz site formu reddeder; çoğu zaman captcha'nın süresinin dolduğunu ya da geçersiz olduğunu söyleyen bir mesajla. Düzeltme neredeyse her zaman zamanlamayla ilgilidir: captcha'yı göndermeye mümkün olduğunca yakın çözün, her token'ı bir kez kullanın ve yalnızca ilk denemenin kabul edilmediğini bildiğinizde tekrar deneyin.
Token'lar neden süresi dolar
Token kalıcı bir kimlik bilgisi değildir. Site, bir insanın (ya da onun adına hareket eden bir solver'ın) doğrulamayı yakın zamanda tamamladığını bilmek ister; bu yüzden token'a kısa bir ömür verir. Saat, token'ın ilk API çağrısında değil, verildiği anda başlar. Çözme ile gönderim arasında olan her şey bu iki dakikadan yer.
Yaygın nedenler
- Çok erken çözmek. Bir grup token'ı önceden çözüp sonraya saklamak en sık nedendir. Token kullanıldığında bayatlamıştır.
- Çözme ile gönderim arasındaki yavaş kod. Uzun bir veritabanı yazımı, bir kuyruk ya da formu göndermeden önce yerleştirilmiş bir
time.sleep, token'ı pencerenin dışına itebilir. - Token'ı yeniden kullanmak. Zaten kabul edilmiş ya da başarısız bir deneme tarafından kullanılmış bir token tekrar çalışmaz. Her token'ı tek kullanımlık sayın.
- Sayfayı yeniden yüklemek. Çözümden sonra sayfa yenilenirse form yeni bir doğrulama üretebilir ve elinizdeki token geçersiz olur.
Düzeltme: göndermeden hemen önce çözün
En basit güvenilir kalıp, çözme ile göndermeyi tek bir adım yapmaktır. Bir token isteyin, formuna koyun, formu gönderin ve aradaki hiçbir yavaş işi yapmayın:
import requests
API_KEY = "scarnox_YOURAPIKEY"
CREATE_URL = "https://api.scarnox.com/api/tasks/create"
def fresh_token(sitekey: str, page_url: str) -> str:
r = requests.post(
CREATE_URL,
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"captcha_type": "PopularCaptchaTaskProxyless",
"site_key": sitekey,
"site_url": page_url,
},
timeout=185, # çağrı token hazır olana kadar bloke olur
)
data = r.json()
if data.get("errorId") != 0:
raise RuntimeError(f"{data.get('errorCode')}: {data.get('errorDescription')}")
return data["solution"]["token"]
def submit_form(page_url: str, sitekey: str, form: dict) -> requests.Response:
token = fresh_token(sitekey, page_url) # gönderimden hemen önce çöz
return requests.post(
page_url,
data={**form, "h-captcha-response": token, "g-recaptcha-response": token},
timeout=30,
)
submit_form token'ı bir önbellekte ya da kuyrukta tutmaz. Bir tane ister, gönderir ve devam eder. Başarısız çözümler ücretlendirilmediği için başarısız bir istek çözme tarafında size bir maliyet yüklemez.
Güvenli şekilde tekrar deneyin
Bazı siteler süresi dolmuş bir token'ı açık bir yanıtla reddeder. Diğerleri sayfa içinde bir hata mesajıyla normal bir sayfa döndürür; bu yüzden tek başına bir durum kodu size bir şey söylemez. Süresi dolmuş bir token için sitenin gerçekte döndürdüğü yanıta bakın ve kontrolünüzü ona göre kurun. Bir yeniden deneme döngüsü şöyle görünebilir:
def submit_with_retry(page_url: str, sitekey: str, form: dict, attempts: int = 2):
for _ in range(attempts):
resp = submit_form(page_url, sitekey, form)
if resp.status_code < 400 and "captcha" not in resp.text.lower():
return resp # kabul edildi, sitenin yanıtının gösterdiği kadarıyla
raise RuntimeError("captcha token rejected after retries")
Bir şey oluşturan formlarda tekrar denemeye dikkat edin. İlk deneme aslında kabul edilmişse ama kodunuz yanıtı yanlış okuduysa, bir tekrar yinelenen bir hesap, sipariş ya da mesaj oluşturabilir. Yalnızca ilk gönderimin kabul edilmediğinden eminseniz tekrar deneyin ve kontrolü çalıştığınız siteye özgü yapın.
Zamanlamayı dürüst tutun
- Sonra kullanacağınız token'lar için bir döngüde çözmeyin. Gönderim başına çözün.
- Çözme ile gönderim arasındaki işi en aza indirin.
- Çözme isteğinde yaklaşık 185 saniyelik bir zaman aşımı kullanın, çünkü çağrı token hazır olana kadar bloke olur. Kendi form gönderiminizdeki ayrı bir zamanlayıcı, token'ın ömründen çok daha kısa olmalıdır.
- Daha hızlı bir pipeline'a ihtiyacınız varsa, token'ları saklamadan paralel çözümleri anlatan captcha çözme hızı rehberine bakın.
Sık yapılan hatalar
- Token'ları daha sonra kullanmak için bir sözlükte ya da Redis'te önbelleğe almak. Önbellek zararsız görünür; ta ki bir token penceresinin dışında kullanılana ve her gönderim başarısız oluncaya kadar.
- Oturum başına bir kez çözmek. Uzun ömürlü bir oturum bile her form gönderimi için yeni bir token ister; çünkü her gönderim kendi doğrulama kontrolünü çalıştırabilir.
- Çözme ile gönderim arasında beklemek. Çözümden sonra yerleştirilen bir hız sınırlayıcı ya da bilerek konmuş bir duraklama, token'ın ömrünü harcar. Her türlü bekleme işini çözümden önce koyun.
- Her hatayı aynı saymak. Sizin tarafınızdaki bir zaman aşımı, reddedilen bir token ve bir site hatası farklı işlem gerektirir. Bunları ayrı loglayın.
Sorunu teşhis edecek kadar log tutun
Bir gönderim başarısız olduğunda şunları kaydedin: token'ın ne zaman verildiği, formun ne zaman gönderildiği, HTTP durumu ve yanıtın ilk birkaç yüz karakteri. Bu dört değerle token'ın yaşını mı doldurduğunu yoksa sitenin başka bir nedenle mi reddettiğini bir bakışta anlarsınız. Token'ın tamamını ortak loglara yazmayın; geçerli bir token, o tek captcha için bir kimlik bilgisidir.
Hâlâ başarısız oluyorsa neyi kontrol etmeli
- Token döndükten ile form gönderimi arasındaki süreyi yazdırın.
site_urldeğerinin captcha'yı gösteren sayfayla eşleştiğini doğrulayın.- Sitekey'in eski bir kopyadan değil, güncel sayfadan okunduğunu doğrulayın.
- Form alan adlarını kontrol edin. PopularCaptcha token'ları
h-captcha-responsealanına gider; çoğu zamang-recaptcha-responsealanına da.
Tüm hata yanıtlarının ve her birinin nasıl ele alınacağının tam listesi için captcha solver hata yönetimi rehberine bakın.