API-Fehler

So behandelst du Fehler von der FourA API.

Format der Fehlerantwort

Die API gibt für alle Fehler flache JSON-Objekte zurück. Es gibt kein verschachteltes error-Objekt oder Fehlercodes.

{
  "error": "Invalid API key"
}

Einige Fehler enthalten zusätzliche Felder wie status, service, retryAfter, current oder limits auf der obersten Ebene:

{
  "error": "Rate limit exceeded",
  "status": 429,
  "service": "single",
  "retryAfter": 5,
  "current": { "concurrency": 12, "rpm": 3000 },
  "limits": { "maxConcurrency": 500, "maxRpm": 3000 }
}

Einen Request nachverfolgen

Jede API-Response (Erfolg oder Fehler) enthält einen X-FourA-Request-Id Header mit einer UUID für diesen Aufruf. Logge sie bei dir. Wenn du den Support zu einem bestimmten Request befragen musst, hilft uns diese ID, ihn zu finden.

curl -i -X POST https://eu.api.foura.ai/api/single/ \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"method": "GET", "url": "https://example.com"}'
# HTTP/1.1 200 OK
# X-FourA-Request-Id: 9f1c4e6c-7b2a-4d3e-8a1f-2c9d8e4a3b15
# Content-Type: application/json
# ...

Fehlertypen

400: Bad Request

Im request body fehlen erforderliche Felder, er enthält ungültige Werte oder er benennt ein Ziel, das die API nicht abruft.

{
  "error": "Invalid request body format"
}

Der gleiche 400 deckt auch den SSRF-Schutz ab. Wenn dein url in einen privaten, Loopback- oder anderweitig reservierten IP-Bereich auflöst (RFC 5735, RFC 6598, IPv6-reservierte Blöcke), wird der Request abgelehnt, bevor er das Netzwerk von FourA verlässt:

{
  "error": "Target <ip> resolves to a private/reserved IP"
}

Fehlerhaftes JSON im Body wird ebenso abgelehnt, bevor ein Feld gelesen wird:

{
  "error": "Invalid JSON in request body"
}

Die Felder proxy und ignoreProxies haben ihre eigenen 400er-Fehler. Beide erfordern die opaken Proxy-IDs, die frühere Responses zurückgegeben haben, sodass bei allem anderen das Dekodieren fehlschlägt:

Nachricht Was passiert ist
Invalid proxy format Der Wert proxy ist keine von FourA ausgestellte Proxy-ID. Eine rohe Proxy-Adresse landet hier.
Invalid ignoreProxies format Einer der Einträge in ignoreProxies ist keine Proxy-ID.
Proxy not found Die ID wurde fehlerfrei dekodiert, verweist aber nicht mehr auf einen aktiven Exit. Wähle eine neue aus.

Lösung: Prüfe, ob dein Request alle erforderlichen Felder enthält, ob URLs http:// oder https:// verwenden, ob der Host in eine öffentliche Adresse aufgelöst wird und ob ein proxy-Wert eine wortwörtlich aus einer früheren Response kopierte ID ist.

401: Unauthorized

Dein API-Schlüssel fehlt oder ist ungültig.

Fehlender Schlüssel:

{
  "error": "Missing API key. Include X-API-Key header."
}

Ungültiger Key:

{
  "error": "Invalid API key"
}

Lösung: Stelle sicher, dass dein X-API-Key Header einen gültigen Schlüssel enthält. Generiere bei Bedarf einen neuen Schlüssel im Dashboard.

429: Rate Limited

Du hast in kurzer Zeit zu viele Requests gesendet.

{
  "error": "Rate limit exceeded",
  "status": 429,
  "service": "single",
  "retryAfter": 5,
  "current": { "concurrency": 12, "rpm": 3000 },
  "limits": { "maxConcurrency": 500, "maxRpm": 3000 }
}

Lösung: Warte die Anzahl an Sekunden in retryAfter, bevor du weitere Requests sendest. Siehe Rate Limits für Details.

500: Server Error

Auf unserer Seite ist etwas schiefgelaufen.

Lösung: Wiederhole den Request nach einer kurzen Verzögerung. Wenn der Fehler weiterhin besteht, prüfe die Statusseite oder kontaktiere den Support mit der X-FourA-Request-Id aus der fehlgeschlagenen Response.

502: Upstream Unavailable

FourA hat seine eigene Engine erreicht, konnte die Antwort aber nicht nutzen.

{
  "error": "Upstream unavailable",
  "details": "..."
}

Behebung: Wiederhole den Vorgang mit einem kurzen Backoff. Dies liegt auf unserer Seite, es kostet dich also nichts: das Ergebnis ist service_error und nur success wird berechnet.

504: Upstream Timeout

Die Engine wurde innerhalb des Zeitbudgets für diesen Request nicht fertig.

{
  "error": "Upstream timeout",
  "details": "the backend did not finish inside the time budget for this request"
}

Ein 504 bezieht sich auf die Dauer der Arbeit, nicht auf deinen Key, deine Parameter oder deinen Proxy. Langsame Ziele, kalte Challenge-Lösungen und große Seiten sind die üblichen Ursachen.

Lösung: Erhöhe timeout_ms im Request (Single akzeptiert bis zu 120000, Browser bis zu 120000, Auto bis zu 180000) oder versuche es erneut. FourA wartet auf das von dir deklarierte Budget plus eine kleine Marge, daher bringt das Anfordern von mehr Zeit auch wirklich mehr Zeit.

503: Service deaktiviert oder ausgelastet

Ein 503 bedeutet, dass der Service entweder wegen Wartung vorübergehend nicht verfügbar ist oder du das Concurrency-Limit erreicht hast. Beide Responses enthalten ein retryAfter-Feld. Die Concurrency-Variante enthält außerdem current und limits.

{
  "error": "Service disabled",
  "status": 503,
  "retryAfter": 60
}

Lösung: Warte retryAfter Sekunden und versuche es dann erneut. Die Statusseite listet aktive Wartungsfenster auf.

Eine dritte 503-Variante hat kein retryAfter. Das bedeutet, dass die Engine hinter deinem endpoint beim Eintreffen deiner Anfrage neu gestartet wurde:

{
  "error": "Backend service unavailable",
  "backend_status": 503
}

Versuche es nach ein bis zwei Sekunden erneut.

Fehler auslesen aus /api/auto/

POST /api/auto/ antwortet mit HTTP 200, wenn die Ladder lief, selbst wenn jeder Rung fehlschlug. Das tatsächliche Ergebnis befindet sich im Body:

{
  "status": 0,
  "error": "all attempts failed",
  "attempts": 7,
  "meta": { "rung": "fail", "solved": false, "attempts": 7, "credits": 47 }
}

Verzweige für Auto also nicht auf Basis des Transportstatus. Lies stattdessen status und error aus dem Body. Ein echter non-200 Status von /api/auto/ bedeutet, dass FourA den Aufruf abgelehnt hat, bevor die Leiter gestartet wurde: 401, 400, 429 oder 503, alle oben dokumentiert.

Zielseitige Fehler innerhalb von 200 OK

Nicht jeder Fehler zeigt sich als non-2xx HTTP-Status. Wenn die Zielseite HTTP 200 mit einem Fehler-Payload zurückgibt, übergibt FourA dir weiterhin den Body, klassifiziert die Request aber als application_error. Wenn das Ziel einen non-2xx Status zurückgibt, den deine validate Regeln nicht akzeptieren, ist das Ergebnis application_fail und der Body wird unverändert durchgereicht.

Beide Fälle sind abrechenbar, als hätte die Request auf Netzwerkebene funktioniert. Die Referenz Outcomes deckt die vollständige Taxonomie ab.

Response Encoding

FourA decodiert Response-Bodies automatisch nach UTF-8. Wenn das Ziel windows-1251, gbk, shift_jis, iso-8859-* oder ein anderes im Content-Type Header oder in einem HTML <meta charset> Tag deklariertes Charset liefert, erhältst du einen sauberen UTF-8 String im Feld data (single, proxy) oder body (browser).

Für binäre Payloads (Bilder, Protobuf, rohes Audio), setze returnBuffer: true auf der Request. Der Body kommt als base64-Puffer zurück, ohne dass eine Charset-Transcodierung angewendet wird.

Retry-Strategie

Eine praktische Retry-Richtlinie:

import time
import requests

def make_request(url, payload, api_key, max_retries=3):
    for attempt in range(max_retries):
        resp = requests.post(
            url,
            headers={"X-API-Key": api_key, "Content-Type": "application/json"},
            json=payload,
        )
        if resp.status_code == 200:
            return resp.json()

        body = resp.json() if resp.headers.get("content-type", "").startswith("application/json") else {}
        retry_after = body.get("retryAfter", 2 ** attempt)
        request_id = resp.headers.get("X-FourA-Request-Id", "?")

        if resp.status_code in (429, 503):
            time.sleep(retry_after)
            continue
        if resp.status_code >= 500:   # 500, 502, 503, 504 are all ours to fix
            time.sleep(2 ** attempt)
            continue

        # 400/401/404 won't fix themselves
        raise RuntimeError(f"{resp.status_code} (request {request_id}): {body.get('error')}")

    raise RuntimeError(f"Exhausted {max_retries} retries")

Verwandte Themen

Aktualisiert: 12. August 2026