API-Tutorials

CaptchaAI IP-Whitelisting und API-Schlüsselsicherheit

Ein API-Schlüssel bei CaptchaAI ist bares Guthaben: Wer ihn besitzt, löst CAPTCHAs auf Ihre Kosten.

Die drei wirksamsten Schutzmaßnahmen sind schnell umgesetzt:

  • den Schlüssel ausschließlich in Umgebungsvariablen halten,
  • ihn regelmäßig rotieren,
  • und, sofern im Dashboard verfügbar, den Zugriff per IP-Whitelisting auf Ihre eigenen Server begrenzen.

Dieser Leitfaden zeigt jede Maßnahme mit lauffähigem Python-Code und ergänzt sie um redigierte Logs, Docker Secrets und eine CI/CD-Konfiguration, die den Schlüssel nie preisgibt.


Warum ein durchgesickerter Schlüssel doppelt teuer wird

CaptchaAI rechnet nicht pro Lösung ab, sondern pro gleichzeitigem Thread – jeder Tarif enthält unbegrenzte Lösungen pro Thread. Ein fremder Zugriff verbraucht also nicht nur Guthaben, sondern belegt auch Ihre Threads und bremst Ihre eigene Automatisierung aus.

Ein geleakter Schlüssel ist damit gleichzeitig ein finanzielles und ein betriebliches Problem.

Die meisten Vorfälle gehen auf dieselben wenigen Fehler zurück:

Exposed API key:
  ├── Leaked in Git repository
  ├── Hardcoded in client-side code
  ├── Shared in documentation
  └── Visible in logs

Impact:
  ├── Balance drained by unauthorized users
  ├── Usage spikes from abuse
  └── Key disabled by service provider

Ein weiterer Aspekt für Leser im DACH-Raum:

Hinweis (DSGVO): Der Schlüssel taucht in Logs oft zusammen mit der pageurl und damit mitunter mit IP-Adressen auf. IP-Adressen gelten als personenbezogenes Datum – schon deshalb lohnt es sich, Logs konsequent zu redigieren und nicht wahllos aufzubewahren.

Betrachten Sie das folgende Vorgehen als Prüfliste, nicht als optionale Kür.


Schlüssel sicher speichern statt hart codieren

Die häufigste Ursache für einen geleakten Schlüssel ist der einfachste Fehler: der Klartext-String im Quellcode, der irgendwann in Git landet. Trennen Sie Konfiguration und Code von Anfang an.

Niemals im Quellcode hinterlegen

# BAD — key in source code
API_KEY = "abc123def456"  # DO NOT DO THIS

# GOOD — environment variable
import os
API_KEY = os.environ["CAPTCHAAI_API_KEY"]

# GOOD — .env file (not committed to Git)
from dotenv import load_dotenv
load_dotenv()
API_KEY = os.environ["CAPTCHAAI_API_KEY"]

Die .env-Datei

Lokal ist eine .env-Datei praktisch – solange sie niemals in die Versionskontrolle gelangt.

# .env (add to .gitignore!)
CAPTCHAAI_API_KEY=your_api_key_here

Der Eintrag in .gitignore

# Always ignore .env files
.env
.env.local
.env.production

Prüfen Sie mit git status, dass die .env wirklich ignoriert wird, bevor Sie den ersten Commit absetzen.

Ist der Schlüssel einmal in der Historie, hilft kein späteres Löschen der Datei mehr – dann bleibt nur Rotation (siehe unten).


Konfiguration aus der Umgebung laden

Kapseln Sie das Laden des Schlüssels in einer Konfigurationsklasse.

So schlägt der Start früh und mit einer klaren Meldung fehl, wenn die Variable fehlt – statt mitten im Lauf mit einem kryptischen Fehler.

import os


class CaptchaConfig:
    """Load CaptchaAI config from environment."""

    def __init__(self):
        self.api_key = os.environ.get("CAPTCHAAI_API_KEY")
        if not self.api_key:
            raise EnvironmentError(
                "CAPTCHAAI_API_KEY not set. "
                "Set it in your environment or .env file."
            )
        self.base_url = os.environ.get(
            "CAPTCHAAI_URL", "https://ocr.captchaai.com"
        )

    def validate(self):
        """Verify the API key works."""
        import requests
        resp = requests.get(f"{self.base_url}/res.php", params={
            "key": self.api_key,
            "action": "getbalance",
            "json": 1,
        }, timeout=10)
        data = resp.json()
        if data.get("status") != 1:
            raise RuntimeError(f"Invalid API key: {data.get('request')}")
        return float(data["request"])


# Usage
config = CaptchaConfig()
balance = config.validate()
print(f"Key valid, balance: ${balance:.2f}")

Der getbalance-Aufruf dient hier doppelt: Er bestätigt, dass der Schlüssel gültig ist, und liefert das aktuelle Guthaben zurück.

Damit haben Sie zugleich einen guten Startpunkt für die spätere Überwachung – ein plötzlich schrumpfendes Guthaben ist eines der zuverlässigsten Frühwarnzeichen für einen kompromittierten Schlüssel.


Den API-Schlüssel rotieren

Rotation ist die zweite Verteidigungslinie: Selbst ein unbemerkt geleakter Schlüssel wird wertlos, sobald Sie ihn ersetzen.

Rotieren Sie in diesen Fällen:

  • turnusmäßig in einem festen Rhythmus, etwa alle 90 Tage,
  • sofort bei jedem Verdacht auf ein Leck,
  • beim Ausscheiden von Teammitgliedern mit Zugriff auf den Schlüssel.

Ein hinterlegter Zweitschlüssel erlaubt den Wechsel ohne Ausfallzeit.

import os
import datetime


class KeyManager:
    """Manage API key rotation."""

    def __init__(self):
        self.primary_key = os.environ.get("CAPTCHAAI_API_KEY")
        self.secondary_key = os.environ.get("CAPTCHAAI_API_KEY_BACKUP")
        self.active_key = self.primary_key

    def get_key(self):
        return self.active_key

    def rotate(self):
        """Switch to secondary key."""
        if self.secondary_key:
            self.active_key = self.secondary_key
            print("Rotated to secondary key")
        else:
            print("No secondary key configured")

    def test_key(self, key):
        """Verify a key is valid."""
        import requests
        resp = requests.get("https://ocr.captchaai.com/res.php", params={
            "key": key, "action": "getbalance", "json": 1,
        }, timeout=10)
        return resp.json().get("status") == 1


# Usage
keys = KeyManager()

# If primary fails, rotate to secondary
if not keys.test_key(keys.get_key()):
    keys.rotate()

Anfragen vor dem Senden validieren

Prüfen Sie Eingaben, bevor sie an die API gehen. Das verhindert nicht nur fehlerhafte Aufrufe, sondern stellt auch sicher, dass der Schlüssel nur mit sauberen, erwarteten Parametern verwendet wird.

import requests
import logging

logger = logging.getLogger(__name__)


class SecureSolver:
    """Solver with security best practices."""

    def __init__(self, api_key):
        self.api_key = api_key
        self.base = "https://ocr.captchaai.com"

    def solve(self, method, **params):
        # Validate inputs
        self._validate_params(method, params)

        data = {"key": self.api_key, "method": method, "json": 1}
        data.update(params)

        # Log without exposing key
        logger.info(
            "Submitting %s solve for %s",
            method, params.get("pageurl", "unknown"),
        )

        resp = requests.post(
            f"{self.base}/in.php", data=data, timeout=30,
        )
        return resp.json()

    def _validate_params(self, method, params):
        """Prevent common security mistakes."""
        # Ensure pageurl is a valid URL
        pageurl = params.get("pageurl", "")
        if pageurl and not pageurl.startswith(("http://", "https://")):
            raise ValueError(f"Invalid pageurl: {pageurl}")

        # Ensure method is valid
        valid_methods = {
            "userrecaptcha", "turnstile", "geetest",
            "base64", "post", "bls", "cloudflare_challenge",
        }
        if method not in valid_methods:
            raise ValueError(f"Unknown method: {method}")

Die zulässigen method-Werte spiegeln die von CaptchaAI unterstützten Typen wider:

  • userrecaptcha – reCAPTCHA v2/v3
  • turnstile – Cloudflare Turnstile
  • geetest – GeeTest v3
  • post und base64 – Bild-CAPTCHAs
  • bls – BLS-CAPTCHAs

Wer eine Liste erlaubter Methoden pflegt, fängt Tippfehler und falsch konfigurierte Aufrufe früh ab.


Logs führen, ohne den Schlüssel preiszugeben

Logs sind ein unterschätztes Leck.

Ein logging.Formatter, der bekannte Schlüsselmuster automatisch schwärzt, sorgt dafür, dass ein Schlüssel selbst dann nicht in Klartext erscheint, wenn er versehentlich in eine Log-Nachricht gerät.

import logging
import re

logger = logging.getLogger(__name__)


class SafeFormatter(logging.Formatter):
    """Redact API keys from log messages."""

    KEY_PATTERN = re.compile(r'[a-f0-9]{32}', re.IGNORECASE)

    def format(self, record):
        msg = super().format(record)
        return self.KEY_PATTERN.sub("[REDACTED]", msg)


# Configure safe logging
handler = logging.StreamHandler()
handler.setFormatter(SafeFormatter("%(levelname)s: %(message)s"))
logger.addHandler(handler)
logger.setLevel(logging.INFO)

# Key is automatically redacted in logs
logger.info(f"Using key: abc123def456ghi789jkl012mno345pq")
# Output: INFO: Using key: [REDACTED]

Schlüssel in Docker-Containern

Bei Container-Deployments – ob auf Hetzner, IONOS oder einem eigenen Kubernetes-Cluster – gehört der Schlüssel nie in das Image. Reichen Sie ihn zur Laufzeit über Umgebungsvariablen oder Docker Secrets ein.

# Dockerfile — DO NOT embed keys here
FROM python:3.11-slim
WORKDIR /app
COPY . .
RUN pip install requests
CMD ["python", "solver.py"]
# docker-compose.yml
services:
  solver:
    build: .
    environment:

      - CAPTCHAAI_API_KEY=${CAPTCHAAI_API_KEY}
    # Or use Docker secrets:
    secrets:

      - captchaai_key

secrets:
  captchaai_key:
    file: ./secrets/captchaai_key.txt

Docker Secrets sind der Umgebungsvariable vorzuziehen, sobald mehrere Dienste denselben Schlüssel teilen.

Warum Secrets: Ihr Inhalt landet nicht in docker inspect und nicht in der Prozessumgebung anderer Container – ein deutlich kleineres Angriffsfenster als eine offene Umgebungsvariable.


Sicherheit in der CI/CD-Pipeline

In der Pipeline gehört der Schlüssel in den Secret-Speicher des CI-Systems, nie in die Repository-Konfiguration. Je nach Plattform sieht das etwas anders aus:

  • GitHub Actions: verschlüsselte Repository-Secrets, per ${{ secrets.NAME }} referenziert.
  • GitLab CI/CD: maskierte und geschützte CI/CD-Variablen – in vielen DACH-Unternehmen der Standard.

GitHub Actions

# .github/workflows/test.yml
jobs:
  test:
    runs-on: ubuntu-latest
    steps:

      - uses: actions/checkout@v4
      - name: Run tests
        env:
          CAPTCHAAI_API_KEY: ${{ secrets.CAPTCHAAI_API_KEY }}
        run: python test_solver.py

Geben Sie das Secret niemals per echo in der CI-Ausgabe aus und wiederholen Sie es nicht in Log-Zeilen.

Pipeline-Logs sind für Teammitglieder oft breit einsehbar – und werden bei öffentlichen Repositorys mitunter sogar extern archiviert.


Getrennte Schlüssel für Entwicklung und Produktion

Verwenden Sie nicht denselben Schlüssel überall. Getrennte Schlüssel je Umgebung begrenzen den Schaden, falls einer davon abhandenkommt:

  • Entwicklung: ein Schlüssel mit knapp bemessenem Guthaben für lokale Tests.
  • Staging: ein eigener Schlüssel für die Vorproduktions-Pipeline.
  • Produktion: ein streng gehüteter Schlüssel, idealerweise per IP-Whitelisting eingeschränkt.

Leakt ein Entwicklungsschlüssel, bleibt der Produktivbetrieb unberührt – und Sie tauschen nur den betroffenen Schlüssel aus.


Fehlerbehebung

Die häufigsten Probleme rund um den API-Schlüssel und ihre schnelle Behebung:

Problem Ursache Lösung
ERROR_WRONG_USER_KEY Schlüssel falsch oder abgelaufen Schlüssel im CaptchaAI-Dashboard prüfen
Unerwarteter Guthabenverlust Schlüssel geleakt oder weitergegeben Schlüssel sofort rotieren, Zugriffe prüfen
Schlüssel funktioniert lokal, aber nicht in der CI Umgebungsvariable nicht gesetzt Zu den CI/CD-Secrets hinzufügen
Schlüssel in der Git-Historie Committete .env-Datei Schlüssel rotieren, .env in .gitignore aufnehmen, git filter-branch verwenden

Sicherheitscheckliste

Gehen Sie diese Punkte vor dem nächsten Produktiv-Deployment durch:

Maßnahme Umgesetzt
API-Schlüssel in Umgebungsvariable
.env in .gitignore aufgenommen
Keine Schlüssel im Quellcode
Schlüssel in Logs geschwärzt
CI/CD nutzt Secret-Speicher
Rotationsplan festgelegt
Guthabenüberwachung aktiv

Häufige Fragen

Woran erkenne ich, dass mein API-Schlüssel missbraucht wird?

An einem unerwarteten Guthabenverlust und an Nutzungsspitzen, die nicht zu Ihren eigenen Läufen passen. Fragen Sie das Guthaben regelmäßig über getbalance ab und lassen Sie sich bei ungewöhnlichem Verbrauch benachrichtigen – so bemerken Sie einen fremden Zugriff, bevor der Schlüssel spürbar Kosten verursacht.

Unterstützt CaptchaAI IP-Whitelisting für den API-Schlüssel?

Prüfen Sie die IP-Einschränkungen in Ihrem CaptchaAI-Dashboard. Wo verfügbar, setzen Sie ausschließlich die IP-Adressen Ihrer eigenen Server auf die Whitelist. Das begrenzt die Nutzung eines geleakten Schlüssels wirksam auf Ihre Infrastruktur.

Wie oft sollte ich den API-Schlüssel rotieren?

Ein fester Rhythmus von etwa 90 Tagen ist ein guter Ausgangspunkt, ergänzt um eine sofortige Rotation bei jedem Verdacht auf ein Leck. Mit einem hinterlegten Zweitschlüssel (CAPTCHAAI_API_KEY_BACKUP) wechseln Sie ohne Ausfallzeit.

Wie entferne ich einen versehentlich committeten Schlüssel wieder aus Git?

Das Löschen der Datei genügt nicht – der Schlüssel bleibt in der Historie. Rotieren Sie ihn zuerst im Dashboard, damit der alte Wert wertlos wird, nehmen Sie die .env in .gitignore auf und bereinigen Sie die Historie anschließend mit git filter-branch oder git filter-repo.


Verwandte Leitfäden

  • CaptchaAI-Zugangsdaten sicher über Umgebungsvariablen verwalten
  • Guthaben prüfen und automatisch auffüllen

Schützen Sie Ihre Investition – sichern Sie Ihren CaptchaAI-API-Schlüssel noch heute.

Kommentare sind für diesen Artikel deaktiviert.