Rate Limits and Throttling
Every FourA API request passes through rate limiting. You'll encounter two types of limits: concurrency (simultaneous requests) and RPM (requests per minute). Both are enforced per service.
How Rate Limits Work
The API enforces limits at two levels:
- Overall API limit: applies to all requests regardless of endpoint.
- Per-service limit: applies separately to each endpoint (single, proxy, browser).
Each level tracks two metrics:
- Concurrency: how many requests are running at the same time.
- RPM: how many requests you've sent in the last 60 seconds.
A request must pass both the overall API check and the service-specific check before it reaches the backend.
Rate Limit Responses
When you hit a limit, the API returns a JSON response with your current usage and the limits in effect.
429: RPM Exceeded
{
"error": "Rate limit exceeded",
"status": 429,
"service": "single",
"retryAfter": 5,
"current": {
"concurrency": 12,
"rpm": 3000
},
"limits": {
"maxConcurrency": 500,
"maxRpm": 3000
}
}
You've sent too many requests in the last minute. Wait for the retryAfter period before sending more.
503: Concurrency Exceeded
{
"error": "Service at capacity",
"status": 503,
"service": "proxy",
"retryAfter": 2,
"current": {
"concurrency": 500,
"rpm": 1200
},
"limits": {
"maxConcurrency": 500,
"maxRpm": 3000
}
}
Too many requests are running at the same time. Some of your earlier requests haven't finished yet.
Response Fields
| Field | Type | Description |
|---|---|---|
error |
string | Human-readable error message |
status |
number | HTTP status code (429 or 503) |
service |
string | Which service hit the limit: single, proxy, browser, or api |
retryAfter |
number | Recommended wait time in seconds before retrying |
current.concurrency |
number | Your current number of active requests |
current.rpm |
number | Your requests in the last 60 seconds |
limits.maxConcurrency |
number | Maximum simultaneous requests allowed |
limits.maxRpm |
number | Maximum requests per minute allowed |
Handling Rate Limits
Use the retryAfter field to implement backoff:
import requests
import time
def fetch(url, max_retries=5):
for attempt in range(max_retries):
resp = requests.post(
"https://eu.api.foura.ai/api/single/",
headers={
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json"
},
json={"method": "GET", "url": url}
)
if resp.status_code in (429, 503):
data = resp.json()
wait = data.get("retryAfter", 5)
time.sleep(wait)
continue
return resp
raise Exception("Max retries exceeded")
Tips
- Check the
currentfields in rate limit responses to understand your usage patterns. - If you're consistently hitting concurrency limits, reduce the number of parallel requests.
- If you're hitting RPM limits, add a small delay between requests or batch them over a longer window.
- The
retryAftervalue varies by limit type: 2 seconds for concurrency, 5 seconds for RPM.
Related
- API Endpoints: Full parameter reference
- Error Handling: All error codes and responses
- Troubleshooting: Common problems and fixes