Allscreenshots
Getting started

Rate limits

Understand API rate limits and quotas

Rate limits

AllScreenshots applies rate limits to ensure fair usage and platform stability. This page explains how limits work and how to handle them.

How rate limiting works

Rate limits are applied per API key and measured in requests per hour. When you exceed the limit, the API returns a 429 Too Many Requests response.

Plan limits

PlanScreenshot requests per hourMonthly quota
Free25100 screenshots
Starter502,500 screenshots
Pro10010,000 screenshots
Business20040,000 screenshots
Scale400150,000 screenshots
Enterprise1,000Unlimited

Rate limit headers

Every response includes headers showing your current rate limit status:

X-RateLimit-Limit: 50
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1704067200
X-RateLimit-Type: screenshot
HeaderDescription
X-RateLimit-LimitMaximum requests allowed in the current hourly window
X-RateLimit-RemainingRequests remaining in current window
X-RateLimit-ResetUnix timestamp when the limit resets
X-RateLimit-Typescreenshot for capture endpoints, general for lightweight API endpoints

Handling rate limits

When you hit the rate limit, you'll receive:

HTTP/1.1 429 Too Many Requests
Retry-After: 30

{
  "error": {
    "code": "RATE_LIMITED",
    "message": "Too many requests. Please slow down.",
    "details": {
      "limit": 50,
      "type": "screenshot",
      "retry_after_seconds": 30
    }
  }
}

Retry with exponential backoff

Implement exponential backoff to handle rate limits gracefully:

async function captureWithRetry(url, maxRetries = 3) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    const response = await fetch('https://api.allscreenshots.com/v1/screenshots', {
      method: 'POST',
      headers: {
        'X-API-Key': process.env.API_KEY,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ url }),
    });

    if (response.status === 429) {
      const retryAfter = response.headers.get('Retry-After') || Math.pow(2, attempt);
      await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
      continue;
    }

    return response;
  }
  throw new Error('Max retries exceeded');
}

Best practices

Use bulk endpoints

Instead of making 100 individual requests, use the bulk endpoint to capture multiple URLs in one request:

{
  "urls": [
    { "url": "https://example1.com" },
    { "url": "https://example2.com" },
    { "url": "https://example3.com" }
  ]
}

Use async processing

For large workloads, use async jobs with webhooks instead of waiting synchronously:

{
  "url": "https://example.com",
  "webhookUrl": "https://your-server.com/webhook"
}

Cache results

Store screenshots locally and reuse them when possible:

const cacheKey = `screenshot:${url}:${JSON.stringify(options)}`;
const cached = await cache.get(cacheKey);

if (cached) {
  return cached;
}

const screenshot = await captureScreenshot(url, options);
await cache.set(cacheKey, screenshot, { ttl: 3600 });
return screenshot;

Need higher limits? Contact us about Enterprise plans with custom rate limits and dedicated capacity.

Monthly quotas

In addition to rate limits, your plan has a monthly screenshot quota. When you reach your quota:

  • Requests return 402 Payment Required
  • You can upgrade your plan to continue
  • Quotas reset at the start of each billing period

Track your usage in the dashboard under Usage.

On this page