Lỗi API

Cách xử lý lỗi từ API FourA.

Định dạng phản hồi lỗi

API trả về các đối tượng JSON phẳng cho tất cả các lỗi. Không có đối tượng error lồng nhau hoặc mã lỗi.

{
  "error": "Invalid API key"
}

Một số lỗi bao gồm các trường bổ sung như status, service, retryAfter, current, hoặc limits ở cấp cao nhất:

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

Theo dõi request

Mỗi response API (thành công hoặc lỗi) đều bao gồm một header X-FourA-Request-Id chứa UUID cho lệnh gọi đó. Hãy ghi log lại ở phía bạn. Nếu bạn cần hỏi bộ phận hỗ trợ xem điều gì đã xảy ra với một request cụ thể, ID đó sẽ giúp chúng tôi tìm thấy nó.

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
# ...

Các loại lỗi

400: Bad Request

Phần thân request thiếu các trường bắt buộc, chứa các giá trị không hợp lệ, hoặc chỉ định một mục tiêu mà API từ chối truy xuất.

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

Lỗi 400 tương tự cũng bao gồm bảo vệ SSRF. Nếu url của bạn phân giải thành dải IP private, loopback hoặc dải IP dành riêng khác (RFC 5735, RFC 6598, các khối IPv6 dành riêng), request sẽ bị từ chối trước khi rời khỏi mạng của FourA:

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

JSON bị lỗi định dạng trong body cũng bị từ chối theo cách tương tự, trước khi bất kỳ trường nào được đọc:

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

Các trường proxyignoreProxies có các lỗi 400 riêng. Cả hai đều nhận các proxy ID ẩn mà các phản hồi trước đó đã trả về, do đó bất kỳ thứ gì khác đều không thể giải mã:

Thông báo Chuyện gì đã xảy ra
Invalid proxy format Giá trị proxy không phải là proxy ID do FourA cấp. Một địa chỉ proxy thô đã được đưa vào đây.
Invalid ignoreProxies format Một trong các mục nhập trong ignoreProxies không phải là proxy ID.
Proxy not found ID đã được giải mã thành công nhưng không còn phân giải đến một exit đang hoạt động. Hãy chọn một ID mới.

Cách khắc phục: Kiểm tra xem request của bạn đã bao gồm tất cả các trường bắt buộc chưa, URL có sử dụng http:// hoặc https:// không, host có phân giải đến một địa chỉ công cộng không, và bất kỳ giá trị proxy nào cũng phải là ID được sao chép nguyên văn từ một phản hồi trước đó.

401: Unauthorized

API key của bạn bị thiếu hoặc không hợp lệ.

Thiếu key:

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

Khóa không hợp lệ:

{
  "error": "Invalid API key"
}

Cách khắc phục: Xác minh header X-API-Key của bạn chứa một key hợp lệ. Tạo một key mới từ Dashboard nếu cần.

429: Rate Limited

Bạn đã gửi quá nhiều request trong một khoảng thời gian ngắn.

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

Khắc phục: Đợi số giây trong retryAfter trước khi gửi thêm request. Xem Rate Limits để biết chi tiết.

500: Lỗi Server

Có lỗi xảy ra từ phía chúng tôi.

Khắc phục: Thử lại request sau một khoảng thời gian ngắn. Nếu lỗi vẫn tiếp diễn, hãy kiểm tra trang trạng thái hoặc liên hệ bộ phận hỗ trợ cùng với X-FourA-Request-Id từ response bị lỗi.

502: Upstream không khả dụng

FourA đã kết nối đến engine của mình nhưng không thể sử dụng phản hồi.

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

Cách khắc phục: Thử lại với khoảng trễ ngắn. Đây là lỗi từ phía chúng tôi, do đó bạn không bị tính phí: kết quả là service_error và chỉ success bị tính phí.

504: Upstream Timeout

Engine không hoàn thành trong thời gian cho phép của request này.

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

Lỗi 504 là do thời gian thực hiện công việc, không phải do khóa, tham số hoặc proxy của bạn. Mục tiêu chậm, việc giải quyết challenge từ đầu và các trang lớn là những nguyên nhân phổ biến.

Cách khắc phục: Tăng timeout_ms trên request (Single chấp nhận tối đa 120000, Browser tối đa 120000, Auto tối đa 180000) hoặc thử lại. FourA sẽ chờ theo ngân sách thời gian bạn đã khai báo cộng thêm một khoảng dư nhỏ, vì vậy việc yêu cầu thêm thời gian thực sự mang lại thêm thời gian xử lý.

503: Dịch vụ bị vô hiệu hóa hoặc quá tải

Lỗi 503 có nghĩa là dịch vụ tạm thời không khả dụng để bảo trì hoặc bạn đã đạt đến giới hạn đồng thời. Cả hai phản hồi đều bao gồm trường retryAfter. Phản hồi do giới hạn đồng thời cũng bao gồm currentlimits.

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

Khắc phục: Đợi retryAfter giây, sau đó thử lại. Trang trạng thái liệt kê các khoảng thời gian bảo trì đang diễn ra.

Dạng lỗi 503 thứ ba không có retryAfter. Điều này có nghĩa là engine phía sau endpoint của bạn đang khởi động lại khi lệnh gọi của bạn đến:

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

Thử lại sau một hoặc hai giây.

Đọc lỗi từ /api/auto/

POST /api/auto/ trả về HTTP 200 mỗi khi ladder chạy, ngay cả khi mọi rung đều thất bại. Kết quả thực tế nằm trong body:

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

Vì vậy đừng rẽ nhánh dựa trên trạng thái transport cho Auto. Thay vào đó hãy đọc statuserror từ body. Mã non-200 thực sự từ /api/auto/ có nghĩa là FourA đã từ chối lệnh gọi trước khi ladder bắt đầu: 401, 400, 429 hoặc 503, tất cả đã được ghi chú ở trên.

Lỗi từ phía mục tiêu bên trong 200 OK

Không phải mọi lỗi đều hiển thị dưới dạng trạng thái HTTP non-2xx. Khi trang mục tiêu trả về HTTP 200 kèm theo payload lỗi, FourA vẫn giao cho bạn body nhưng phân loại request đó là application_error. Khi mục tiêu trả về một mã non-2xx mà các quy tắc validate của bạn không chấp nhận, kết quả là application_fail và body được giữ nguyên.

Cả hai trường hợp đều bị tính phí như thể request đã hoạt động ở cấp độ mạng. Tài liệu tham khảo Outcomes bao gồm toàn bộ phân loại.

Encoding của Response

FourA tự động giải mã các response body sang UTF-8. Nếu mục tiêu phục vụ windows-1251, gbk, shift_jis, iso-8859-*, hoặc bất kỳ charset nào khác được khai báo trong header Content-Type hoặc thẻ HTML <meta charset>, bạn sẽ nhận được chuỗi UTF-8 sạch trong trường data (single, proxy) hoặc body (browser).

Đối với các binary payload (hình ảnh, protobuf, âm thanh thô), hãy đặt returnBuffer: true trên request. Body trả về dưới dạng base64 buffer mà không áp dụng chuyển đổi mã hóa charset.

Chiến lược Retry

Một chính sách retry thực tế:

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")

Liên quan

Cập nhật: 12 tháng 8, 2026