Błędy API
Jak obsługiwać błędy z API FourA.
Format odpowiedzi z błędem
API zwraca płaskie obiekty JSON dla wszystkich błędów. Nie ma zagnieżdżonego obiektu error ani kodów błędów.
{
"error": "Invalid API key"
}
Niektóre błędy zawierają dodatkowe pola, takie jak status, service, retryAfter, current lub limits na najwyższym poziomie:
{
"error": "Rate limit exceeded",
"status": 429,
"service": "single",
"retryAfter": 5,
"current": { "concurrency": 12, "rpm": 3000 },
"limits": { "maxConcurrency": 500, "maxRpm": 3000 }
}
Śledzenie żądania
Każda odpowiedź API (sukces lub błąd) zawiera nagłówek X-FourA-Request-Id z identyfikatorem UUID dla tego wywołania. Zapisz go w logach po swojej stronie. Jeśli musisz zapytać dział wsparcia, co stało się z konkretnym żądaniem, ten identyfikator pozwoli nam je znaleźć.
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
# ...
Typy błędów
400: Błędne żądanie
W ciele żądania brakuje wymaganych pól, zawiera ono nieprawidłowe wartości lub wskazuje cel, którego API odmawia pobrania.
{
"error": "Invalid request body format"
}
Ten sam błąd 400 obejmuje również ochronę przed SSRF. Jeśli Twój url rozwiązuje się na prywatną, zwrotną lub inną zarezerwowaną pulę adresów IP (RFC 5735, RFC 6598, zarezerwowane bloki IPv6), żądanie jest odrzucane przed opuszczeniem sieci FourA:
{
"error": "Target <ip> resolves to a private/reserved IP"
}
Nieprawidłowy JSON w ciele jest odrzucany w ten sam sposób, przed odczytaniem jakiegokolwiek pola:
{
"error": "Invalid JSON in request body"
}
Pola proxy i ignoreProxies mają własne błędy 400. Oba przyjmują nieprzezroczyste identyfikatory proxy zwrócone we wcześniejszych odpowiedziach, więc zdekodowanie czegokolwiek innego zakończy się niepowodzeniem:
| Komunikat | Co się stało |
|---|---|
Invalid proxy format |
Wartość proxy nie jest identyfikatorem proxy wydanym przez FourA. Trafia tu surowy adres proxy. |
Invalid ignoreProxies format |
Jeden z wpisów w ignoreProxies nie jest identyfikatorem proxy. |
Proxy not found |
Identyfikator został poprawnie zdekodowany, ale nie wskazuje już na aktywny węzeł wyjściowy. Wybierz nowy. |
Rozwiązanie: Sprawdź, czy żądanie zawiera wszystkie wymagane pola, czy adresy URL używają http:// lub https://, czy host jest rozwiązywany na adres publiczny i czy jakakolwiek wartość proxy jest identyfikatorem skopiowanym dokładnie z wcześniejszej odpowiedzi.
401: Unauthorized
Brakuje klucza API lub jest on nieprawidłowy.
Brak klucza:
{
"error": "Missing API key. Include X-API-Key header."
}
Nieprawidłowy klucz:
{
"error": "Invalid API key"
}
Rozwiązanie: Sprawdź, czy header X-API-Key zawiera prawidłowy klucz. W razie potrzeby wygeneruj nowy klucz w Panelu.
429: Rate Limited
Wysłano zbyt wiele requestów w krótkim czasie.
{
"error": "Rate limit exceeded",
"status": 429,
"service": "single",
"retryAfter": 5,
"current": { "concurrency": 12, "rpm": 3000 },
"limits": { "maxConcurrency": 500, "maxRpm": 3000 }
}
Rozwiązanie: Poczekaj liczbę sekund wskazaną w retryAfter przed wysłaniem kolejnych żądań. Szczegółowe informacje znajdziesz w sekcji Limity żądań.
500: Server Error
Coś poszło nie tak po naszej stronie.
Rozwiązanie: Ponów żądanie po krótkim opóźnieniu. Jeśli błąd nadal występuje, sprawdź stronę statusu lub skontaktuj się z pomocą techniczną, podając X-FourA-Request-Id z nieudanej odpowiedzi.
502: Upstream Unavailable
System FourA dotarł do własnego silnika, ale nie mógł użyć odpowiedzi.
{
"error": "Upstream unavailable",
"details": "..."
}
Rozwiązanie: Ponów próbę z krótkim opóźnieniem. Błąd leży po naszej stronie, więc nic cię to nie kosztuje: wynik to service_error, a opłata jest pobierana tylko za success.
504: Upstream Timeout
Silnik nie zakończył pracy w wyznaczonym czasie dla tego requestu.
{
"error": "Upstream timeout",
"details": "the backend did not finish inside the time budget for this request"
}
Błąd 504 dotyczy tego, jak długo trwało zadanie, a nie twojego klucza, parametrów czy proxy. Wolne serwery docelowe, początkowe rozwiązywanie zabezpieczeń i duże strony to najczęstsze przyczyny.
Rozwiązanie: Zwiększ wartość timeout_ms w żądaniu (Single akceptuje do 120000, Browser do 120000, Auto do 180000) lub spróbuj ponownie. FourA czeka przez zadeklarowany budżet czasu plus mały margines, więc prośba o więcej czasu faktycznie go wydłuża.
503: Usługa wyłączona lub przeciążona
Błąd 503 oznacza, że usługa jest tymczasowo niedostępna z powodu prac konserwacyjnych lub osiągnięto limit współbieżności. Obie odpowiedzi zawierają pole retryAfter. Wersja dotycząca współbieżności zawiera również current i limits.
{
"error": "Service disabled",
"status": 503,
"retryAfter": 60
}
Rozwiązanie: Poczekaj retryAfter sekund, a następnie spróbuj ponownie. Strona statusu zawiera listę aktywnych okien serwisowych.
Trzeci wariant błędu 503 nie zawiera retryAfter. Oznacza to, że silnik obsługujący twój endpoint restartował się, gdy nadeszło twoje żądanie:
{
"error": "Backend service unavailable",
"backend_status": 503
}
Spróbuj ponownie po sekundzie lub dwóch.
Odczytywanie błędów z /api/auto/
POST /api/auto/ odpowiada kodem HTTP 200 zawsze, gdy drabina została uruchomiona, nawet jeśli każdy szczebel zawiódł. Rzeczywisty wynik znajduje się w body:
{
"status": 0,
"error": "all attempts failed",
"attempts": 7,
"meta": { "rung": "fail", "solved": false, "attempts": 7, "credits": 47 }
}
Dlatego nie opieraj logiki warunkowej na statusie transportu dla trybu Auto. Zamiast tego odczytaj status i error z ciała odpowiedzi. Prawdziwy status inny niż 200 z /api/auto/ oznacza, że FourA odrzuciło wywołanie przed uruchomieniem drabinki: 401, 400, 429 lub 503, które opisano powyżej.
Błędy po stronie celu wewnątrz 200 OK
Nie każdy błąd objawia się statusem HTTP innym niż 2xx. Gdy strona docelowa zwraca HTTP 200 z payloadem błędu, FourA nadal przekazuje ciało odpowiedzi, ale klasyfikuje request jako application_error. Gdy cel zwraca status inny niż 2xx, którego reguły validate nie akceptują, wynikiem jest application_fail, a ciało odpowiedzi przechodzi bez zmian.
Oba przypadki są płatne tak, jakby request zadziałał na poziomie sieciowym. Dokumentacja Outcomes zawiera pełną taksonomię.
Kodowanie odpowiedzi
FourA automatycznie dekoduje ciała odpowiedzi do UTF-8. Jeśli cel serwuje windows-1251, gbk, shift_jis, iso-8859-* lub dowolny inny charset zadeklarowany w nagłówku Content-Type albo w tagu HTML <meta charset>, otrzymasz czysty ciąg znaków UTF-8 w polu data (single, proxy) lub body (browser).
W przypadku binarnych payloadów (obrazy, protobuf, surowe audio), ustaw returnBuffer: true w żądaniu. Ciało odpowiedzi wraca jako bufor base64 bez zastosowanego transkodowania znaków.
Strategia ponowień
Praktyczna polityka ponowień:
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")
Powiązane
- Limity rate limit: Szczegóły współbieżności i RPM
- Wyniki requestów: Wyjaśnienie siedmiu możliwych wyników
- Częste problemy: Objawy, przyczyny i rozwiązania
- Zabezpieczenia przed botami: Kiedy body zawiera stronę weryfikacji zamiast błędu