Rate Limits
Understand the rate limits for the FreeFileTools API and how to handle them in your application.
Free Tier Limits
| Limit | Value |
|---|---|
| Requests per hour | 50 |
| Max file size per request | 25 MB |
| Rate limit window | Rolling 1 hour |
The rate limit is applied per API key. Each key gets its own independent counter that resets on a rolling hourly basis.
When Rate Limits Are Exceeded
When you exceed the rate limit, the API returns a 429 Too Many Requests response:
{
"error": "Rate limit exceeded",
"message": "You have exceeded the rate limit of 50 requests per hour. Please try again later.",
"retryAfter": 1742
}The retryAfter field indicates the number of seconds to wait before making another request.
Rate Limit Response Headers
Every API response includes headers to help you track your rate limit usage:
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum number of requests allowed per hour (50) |
X-RateLimit-Remaining | Number of requests remaining in the current window |
Retry-After | Seconds to wait before retrying (only on 429 responses) |
Example response headers
HTTP/1.1 200 OK
Content-Type: image/jpeg
X-RateLimit-Limit: 50
X-RateLimit-Remaining: 42Tips for Staying Within Limits
Check remaining requests
Monitor the X-RateLimit-Remaining header to know how many requests you have left.
Implement exponential backoff
When you receive a 429 response, wait and retry with increasing delays rather than hammering the API.
Cache results
If you are processing the same files repeatedly, cache the results locally to avoid unnecessary API calls.
Batch wisely
For batch processing, space out your requests over time rather than sending them all at once.
Example: Handling rate limits in JavaScript
async function apiCall(url, options, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const response = await fetch(url, options);
if (response.status === 429) {
const retryAfter = parseInt(response.headers.get("Retry-After") || "60");
console.log(`Rate limited. Waiting ${retryAfter} seconds...`);
await new Promise((resolve) => setTimeout(resolve, retryAfter * 1000));
continue;
}
return response;
}
throw new Error("Max retries exceeded");
}