Troubleshooting

ERROR_ZERO_BALANCE: Ödeme ve Faturalandırma Sorunlarını Giderme

Otomasyonunuz sorunsuz çalışırken birden her istek ERROR_ZERO_BALANCE dönmeye başladıysa neden tektir: CaptchaAI hesabınız görevleri işleyecek bakiyeye sahip değil. İyi haber, bu bir kod ya da entegrasyon hatası değildir — captchaai.com üzerinden bakiye ekleyerek saniyeler içinde çözülür. Asıl mesele hatanın tekrar etmemesidir. Bu rehber önce hatayı diğer geçici hatalardan ayırır, ardından bakiye kontrolü, otomatik uyarı ve zarif düşüş kalıplarıyla otomasyonunuzun bir daha sessizce durmamasını sağlar. Örnekler Python'la yazılmıştır ama mantık her dile taşınabilir.

Panik yapmadan önce ilk 60 saniyede şunları yapın:

  1. getbalance ile mevcut bakiyeyi sorgulayın (aşağıdaki fonksiyon işinizi görür).
  2. Bakiye sıfır ya da sıfıra yakınsa captchaai.com panelinden bakiye ekleyin.
  3. Doğru API anahtarını ve doğru hesabı kullandığınızı doğrulayın.

Bu hatayı ne tetikler?

ERROR_ZERO_BALANCE, CAPCHA_NOT_READY veya zaman aşımı gibi geçici bir hata değildir; yeniden denemek onu düzeltmez, yalnızca boşa istek harcar. Bakiye eklenene kadar her görev aynı hatayı döndürür. Pratikte dört tipik nedeni vardır:

Neden Sıklık Çözüm
Hesap bakiyesi tükendi En sık captchaai.com üzerinden bakiye ekleyin
Beklenenden yüksek kullanım Sık Bakiye izleme kurun
API anahtarının sızması Nadir Anahtarı döndürün, kullanımı inceleyin
Ödeme yönteminin süresi dolmuş Ara sıra Fatura bilgilerini güncelleyin

Dikkat: Hatayı gördüğünüzde retry döngüsünü sıkılaştırmak işe yaramaz. Bakiye sıfırken her yeniden deneme yalnızca boşa istek üretir; önce bakiyeyi eklemeniz, sonra kaldığınız yerden devam etmeniz gerekir.


Belirtiden düzeltmeye: hızlı başvuru

Koda geçmeden önce, en sık karşılaşılan belirtileri ve çözümlerini bir arada görelim:

Belirti Neden Düzeltme
Her istekte ERROR_ZERO_BALANCE Hesap boş captchaai.com üzerinden bakiye ekleyin
Bakiye beklenmedik hızda düşüyor Sızmış API anahtarı veya verimsiz kod Anahtarı döndürün, kullanım günlüklerini kontrol edin
Bakiye pozitif görünüyor ama hata sürüyor Önbellek/senkronizasyon gecikmesi 1 dakika bekleyip yeniden deneyin
Bakiye eklenemiyor Ödeme yöntemi sorunu Panelden ödeme yönteminizi güncelleyin

Bakiyeyi saniyeler içinde kontrol edin

Hatayı doğrulamanın en hızlı yolu, getbalance işlemiyle mevcut bakiyeyi sorgulamaktır. Aşağıdaki fonksiyon res.php uç noktasına tek bir istek atar ve bakiyeyi ondalık dolar olarak döndürür. Bu kontrolü şu noktalarda çalıştırın:

  • Otomasyon başlamadan önce, bir sağlık kontrolü olarak.
  • Bir CI adımı içinde, gece koşularının bakiyesiz başlamasını engellemek için.
  • Bakiye şüphesi doğuran bir hatadan hemen sonra, teşhisi doğrulamak için.

Sıfıra yakın bir değer görürseniz görev göndermeye kalkmadan önce bakiye ekleyin.

import requests


def check_balance(api_key):
    """Check current CaptchaAI balance."""
    resp = requests.get(
        "https://ocr.captchaai.com/res.php",
        params={"key": api_key, "action": "getbalance", "json": 1},
        timeout=10,
    )
    data = resp.json()

    if data.get("status") == 1:
        return float(data["request"])

    raise RuntimeError(f"Balance check failed: {data.get('request')}")


balance = check_balance("YOUR_API_KEY")
print(f"Balance: ${balance:.4f}")

Sıfır bakiyeyi çökme olmadan yönetin

Üretimde asıl istediğiniz, bakiye bittiğinde tüm sürecin çökmesi değil, hatanın kontrollü biçimde ele alınmasıdır. Aşağıdaki BalanceAwareSolver üç işi birden yapar:

  • Her görevden önce bakiyeyi önbellekten kontrol eder ve varsayılan olarak beş dakikada bir tazeler.
  • Bakiye eşiğin altına inince uyarı günlüğü yazar.
  • Sıfır bakiye durumunda kendi istisna tipini fırlatır.

Böylece çağıran kod, bir ağ hatasıyla bakiye hatasını birbirinden ayırt edebilir ve her birine farklı tepki verebilir — geçici hatada yeniden dener, bakiye hatasında ise sizi uyarır.

import requests
import time
import logging

logger = logging.getLogger(__name__)


class BalanceAwareSolver:
    """Solver that handles zero balance without crashing."""

    def __init__(self, api_key, min_balance=0.50):
        self.api_key = api_key
        self.min_balance = min_balance
        self._last_balance_check = 0
        self._cached_balance = None

    def solve(self, params):
        """Solve CAPTCHA with balance pre-check."""
        # Check balance every 5 minutes
        if time.time() - self._last_balance_check > 300:
            self._check_balance()

        if self._cached_balance is not None and self._cached_balance < 0.01:
            raise InsufficientBalanceError(
                f"Balance too low: ${self._cached_balance:.4f}. "
                "Add funds at https://captchaai.com"
            )

        try:
            return self._submit_and_poll(params)
        except ZeroBalanceError:
            self._cached_balance = 0.0
            logger.error("ERROR_ZERO_BALANCE — add funds at captchaai.com")
            raise

    def _check_balance(self):
        """Check and cache balance."""
        try:
            resp = requests.get(
                "https://ocr.captchaai.com/res.php",
                params={
                    "key": self.api_key,
                    "action": "getbalance",
                    "json": 1,
                },
                timeout=10,
            )
            data = resp.json()
            if data.get("status") == 1:
                self._cached_balance = float(data["request"])
                self._last_balance_check = time.time()

                if self._cached_balance < self.min_balance:
                    logger.warning(
                        f"Low balance: ${self._cached_balance:.4f} "
                        f"(threshold: ${self.min_balance:.2f})"
                    )
        except Exception as e:
            logger.debug(f"Balance check failed: {e}")

    def _submit_and_poll(self, params):
        """Submit task and poll for result."""
        data = {"key": self.api_key, "json": 1, **params}
        resp = requests.post(
            "https://ocr.captchaai.com/in.php", data=data, timeout=30,
        )
        result = resp.json()

        if result.get("status") != 1:
            error = result.get("request", "")
            if error == "ERROR_ZERO_BALANCE":
                raise ZeroBalanceError("Account balance is zero")
            raise RuntimeError(f"Submit failed: {error}")

        task_id = result["request"]

        time.sleep(10)
        for _ in range(24):
            resp = requests.get(
                "https://ocr.captchaai.com/res.php",
                params={
                    "key": self.api_key, "action": "get",
                    "id": task_id, "json": 1,
                },
                timeout=15,
            )
            data = resp.json()

            if data.get("status") == 1:
                return data["request"]
            if data["request"] != "CAPCHA_NOT_READY":
                raise RuntimeError(data["request"])
            time.sleep(5)

        raise TimeoutError("Solve timeout")


class ZeroBalanceError(Exception):
    """Raised when account has no balance."""
    pass


class InsufficientBalanceError(Exception):
    """Raised when balance is below minimum threshold."""
    pass

Düşük bakiye için otomatik uyarılar kurun

Bakiye hatasını tamamen önlemenin yolu, sıfıra ulaşmadan haber almaktır. BalanceMonitor arka planda bir thread'de bakiyeyi periyodik olarak sorgular ve eşik altına inince tek seferlik bir uyarı gönderir; bakiye yeniden dolduğunda uyarı bayrağını sıfırlar, böylece tekrar tekrar bildirim yağmuruna tutulmazsınız. _send_alert metodunu kendi bildirim kanalınızla değiştirmeniz yeterli; yaygın seçenekler:

  • E-posta (kod örneğindeki smtplib ile).
  • Slack veya Microsoft Teams webhook'u.
  • PagerDuty ya da Opsgenie gibi bir nöbet/çağrı sistemi.

İstanbul'daki bir e-ticaret ekibinin her gece staging ortamında çalıştırdığı ödeme akışı regresyon testlerini düşünün: testler Turnstile ve reCAPTCHA çözerken bakiye saat 03.00'te tükenirse, hiçbir uyarı olmadan tüm gece koşusu sessizce başarısız olur ve ekip sabah bozuk bir raporla uyanır. Düşük bakiye uyarısı tam da bu sessiz kesintiyi engeller.

İpucu: Uyarı eşiğini ortalama günlük harcamanızın en az iki katına ayarlayın; böylece bir hafta sonu bakiye eklemeseniz bile otomasyonunuz durmadan önce haberdar olursunuz.

import smtplib
from email.message import EmailMessage
import threading
import time
import logging

logger = logging.getLogger(__name__)


class BalanceMonitor:
    """Monitor balance and send alerts when low."""

    def __init__(self, api_key, alert_threshold=1.00, check_interval=600):
        self.api_key = api_key
        self.alert_threshold = alert_threshold
        self.check_interval = check_interval
        self._alert_sent = False
        self._running = False

    def start(self):
        """Start background monitoring."""
        self._running = True
        thread = threading.Thread(target=self._monitor_loop, daemon=True)
        thread.start()
        logger.info("Balance monitor started")

    def stop(self):
        """Stop monitoring."""
        self._running = False

    def _monitor_loop(self):
        """Check balance periodically."""
        while self._running:
            try:
                balance = self._get_balance()
                logger.info(f"Balance: ${balance:.4f}")

                if balance <= 0:
                    self._send_alert("CRITICAL: CaptchaAI Zero Balance", 
                        f"Balance is ${balance:.4f}. Solving will fail.")
                elif balance < self.alert_threshold and not self._alert_sent:
                    self._send_alert("WARNING: CaptchaAI Low Balance",
                        f"Balance: ${balance:.4f} (threshold: ${self.alert_threshold:.2f})")
                    self._alert_sent = True
                elif balance >= self.alert_threshold:
                    self._alert_sent = False  # Reset alert flag

            except Exception as e:
                logger.error(f"Monitor error: {e}")

            time.sleep(self.check_interval)

    def _get_balance(self):
        """Check account balance."""
        resp = requests.get(
            "https://ocr.captchaai.com/res.php",
            params={"key": self.api_key, "action": "getbalance", "json": 1},
            timeout=10,
        )
        data = resp.json()
        if data.get("status") == 1:
            return float(data["request"])
        raise RuntimeError(data.get("request"))

    def _send_alert(self, subject, body):
        """Send email alert. Replace with your notification method."""
        logger.critical(f"{subject}: {body}")
        # Implement email, Slack webhook, or other notification here


# Usage
monitor = BalanceMonitor("YOUR_API_KEY", alert_threshold=2.00)
monitor.start()

Toplu işten önce kullanımı tahmin edin

Büyük bir toplu işe başlamadan önce, mevcut bakiyenin planlanan çözüm sayısını karşılayıp karşılamayacağını kabaca doğrulayabilirsiniz. Aşağıdaki COST_PER_SOLVE değerleri yalnızca örnek/temsilîdir — gerçek CaptchaAI fiyatlandırması çözüm başına değil, thread bazlıdır: her plan o ay için sınırsız çözüm içerir ve çözüm başına ek ücret yoktur. Türkiye'deki geliştiriciler için bu önemli bir avantajdır; TL'nin oynaklığı bütçelemeyi zorlaştırırken thread bazlı planlar aylık gideri USD cinsinden sabit tutar. Örneğin BASIC ($15/ay, 5 thread) planıyla aylık maliyetiniz çözüm hacminizden bağımsız olarak öngörülebilir kalır.

Not: Aşağıdaki değerler yalnızca kaba bir bütçe kontrolü içindir; gerçek fiyatlandırma için captchaai.com/pricing sayfasındaki güncel plan ve thread bilgilerini esas alın.

# Approximate costs per CAPTCHA type
COST_PER_SOLVE = {
    "recaptcha_v2": 0.003,
    "recaptcha_v3": 0.004,
    "turnstile": 0.002,
    "geetest": 0.003,
    "image": 0.001,
    "bls": 0.002,
}


def estimate_cost(captcha_type, quantity):
    """Estimate cost for a batch of solves."""
    rate = COST_PER_SOLVE.get(captcha_type, 0.003)
    total = rate * quantity
    return total


def check_budget(api_key, captcha_type, planned_solves):
    """Check if balance covers planned solves."""
    balance = check_balance(api_key)
    estimated = estimate_cost(captcha_type, planned_solves)

    if balance >= estimated:
        print(f"Budget OK: ${balance:.4f} covers ~{int(balance / COST_PER_SOLVE[captcha_type])} solves")
        return True
    else:
        shortfall = estimated - balance
        print(f"Need ${shortfall:.4f} more for {planned_solves} {captcha_type} solves")
        return False


# Check before a large batch
check_budget("YOUR_API_KEY", "recaptcha_v2", 5000)

Bakiye bittiğinde zarif düşüş

Bakiye sıfırlandığında otomasyonunuzun ne yapması gerektiğini önceden kararlaştırın. GracefulSolver üç strateji sunar:

  • skip — görevi atla ve devam et; kayıp tolere edilebilen işler için.
  • queue — sonradan yeniden denemek üzere kuyruğa al; bakiye eklenince retry_pending ile bekleyen görevleri tekrar işlersiniz.
  • raise — süreci durdur; sessiz veri kaybındansa açık bir hata tercih edildiğinde.

Hangi stratejinin doğru olduğu iş akışınıza bağlıdır: bir veri kazıma işinde görevi atlamak kabul edilebilirken, ödeme akışı testinde kuyruğa almak çok daha güvenlidir.

class GracefulSolver:
    """Fall back to manual or skip when balance is zero."""

    def __init__(self, api_key, on_zero_balance="skip"):
        self.api_key = api_key
        self.on_zero_balance = on_zero_balance  # "skip", "queue", "raise"
        self._pending_queue = []
        self.solver = BalanceAwareSolver(api_key)

    def solve_or_degrade(self, params, item_id=None):
        """Try to solve, degrade gracefully on zero balance."""
        try:
            return self.solver.solve(params)
        except (ZeroBalanceError, InsufficientBalanceError):
            return self._handle_zero(params, item_id)

    def _handle_zero(self, params, item_id):
        """Handle zero balance based on configured strategy."""
        if self.on_zero_balance == "skip":
            logger.warning(f"Skipping CAPTCHA for item {item_id} — no balance")
            return None

        elif self.on_zero_balance == "queue":
            self._pending_queue.append({"params": params, "item_id": item_id})
            logger.info(f"Queued item {item_id} — {len(self._pending_queue)} pending")
            return None

        else:  # "raise"
            raise ZeroBalanceError("No balance — stopping automation")

    def retry_pending(self):
        """Retry queued items after balance is refilled."""
        if not self._pending_queue:
            return []

        results = []
        remaining = []

        for item in self._pending_queue:
            try:
                token = self.solver.solve(item["params"])
                results.append({"item_id": item["item_id"], "token": token})
            except (ZeroBalanceError, InsufficientBalanceError):
                remaining.append(item)
                break  # Stop retrying — still no balance

        self._pending_queue = remaining + self._pending_queue[len(results) + len(remaining):]
        return results

Sık sorulan sorular

Bakiyem yeterli görünüyor ama yine de ERROR_ZERO_BALANCE alıyorum, neden?

Çoğu zaman önbellek veya senkronizasyon gecikmesidir. Bir dakika bekleyip yeniden deneyin; hata sürüyorsa doğru API anahtarını kullandığınızdan ve bakiyeyi eklediğiniz hesabın aynı hesap olduğundan emin olun.

Bakiyem neden beklediğimden hızlı düşüyor?

İki yaygın neden var: API anahtarınızın sızması (başkası da kullanıyor olabilir) veya başarısız görevleri sonsuz döngüde yeniden gönderen verimsiz bir retry mantığı. Anahtarı döndürün ve kullanım günlüklerinizi inceleyin.

CaptchaAI çözüm başına mı yoksa thread başına mı ücretlendiriyor?

Planlar thread (eşzamanlı çözüm) bazlıdır ve her plan ay boyunca sınırsız çözüm içerir; çözüm başına ek ücret yoktur. BASIC ($15/ay, 5 thread) ile başlayıp hacminiz arttıkça üst planlara geçebilirsiniz.

Başarısız çözümler bakiyemden düşülür mü?

Hayır. Yalnızca token veya yanıt döndüren başarılı çözümler için ücretlendirilirsiniz; zaman aşımına uğrayan ya da reddedilen görevler bakiyenizden düşülmez.

Bakiye kontrolünü CI/CD hattımda nasıl otomatikleştiririm?

getbalance çağrısını dağıtım öncesi bir adım olarak ekleyin ve bakiye belirlediğiniz eşiğin altındaysa işi başarısız sayın. Böylece bir toplu iş, yeterli bakiye olmadan hiç başlamaz ve yarıda ERROR_ZERO_BALANCE ile durmaz.


İlgili kılavuzlar


Otomasyonunuzu duraksız tutun — CaptchaAI hesabınıza bakiye ekleyin.

Bu makale için yorumlar devre dışı bırakılmıştır.