Rate Limits

RenderScreenshot uses rate limiting to ensure fair usage and system stability. Limits vary by plan.

Rate Limits by Plan

Plan Requests/min Concurrent Batch Size
Free 10 2 5
Starter 60 5 20
Pro 300 20 100
Enterprise Custom Custom Custom

Requests per Minute

Maximum number of API requests allowed per minute. Resets every 60 seconds.

Concurrent Requests

Maximum number of requests that can be processing simultaneously. This affects how many screenshots can be rendered at the same time.

Batch Size

Maximum number of URLs allowed in a single batch request.

Rate Limit Headers

Every response includes rate limit information:

HTTP/1.1 200 OK
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 295
X-RateLimit-Reset: 1705600060
Header Description
X-RateLimit-Limit Maximum requests per window
X-RateLimit-Remaining Requests remaining in current window
X-RateLimit-Reset Unix timestamp when the window resets

429 Too Many Requests

When you exceed rate limits, you'll receive a 429 response:

HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1705600060
Retry-After: 45
Content-Type: application/json

{
  "error": {
    "type": "rate_limit_error",
    "code": "too_many_requests",
    "message": "Rate limit exceeded. Please retry after 45 seconds.",
    "retryable": true,
    "docs": "https://docs.renderscreenshot.com/errors/rate-limits"
  },
  "request_id": "req_abc123"
}

Retry-After Header

The Retry-After header indicates how many seconds to wait before retrying:

Retry-After: 45

Handling Rate Limits

Exponential Backoff

Implement exponential backoff for rate limit errors:

async function screenshotWithRetry(url, maxRetries = 3) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    const response = await fetch('https://api.renderscreenshot.com/v1/screenshot', {
      method: 'POST',
      headers: {
        'Authorization': 'Bearer rs_live_xxxxx',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ url })
    });

    if (response.status === 429) {
      const retryAfter = parseInt(response.headers.get('Retry-After') || '60');
      const delay = retryAfter * 1000 * Math.pow(2, attempt);
      console.log(`Rate limited. Waiting ${delay}ms before retry.`);
      await new Promise(resolve => setTimeout(resolve, delay));
      continue;
    }

    return response;
  }

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

Ruby Example

def screenshot_with_retry(url, max_retries: 3)
  attempt = 0

  loop do
    response = HTTParty.post(
      'https://api.renderscreenshot.com/v1/screenshot',
      headers: {
        'Authorization' => 'Bearer rs_live_xxxxx',
        'Content-Type' => 'application/json'
      },
      body: { url: url }.to_json
    )

    return response unless response.code == 429

    attempt += 1
    raise 'Max retries exceeded' if attempt >= max_retries

    retry_after = response.headers['Retry-After'].to_i
    delay = retry_after * (2 ** attempt)
    sleep(delay)
  end
end

Python Example

import time
import requests

def screenshot_with_retry(url, max_retries=3):
    for attempt in range(max_retries):
        response = requests.post(
            'https://api.renderscreenshot.com/v1/screenshot',
            headers={
                'Authorization': 'Bearer rs_live_xxxxx',
                'Content-Type': 'application/json'
            },
            json={'url': url}
        )

        if response.status_code == 429:
            retry_after = int(response.headers.get('Retry-After', 60))
            delay = retry_after * (2 ** attempt)
            print(f'Rate limited. Waiting {delay}s before retry.')
            time.sleep(delay)
            continue

        return response

    raise Exception('Max retries exceeded')

Concurrent Request Limits

If you exceed concurrent request limits:

{
  "error": {
    "type": "rate_limit_error",
    "code": "concurrent_limit",
    "message": "Too many concurrent requests. Maximum is 5.",
    "retryable": true
  }
}

Handle by queuing requests or implementing a semaphore.

Best Practices

1. Use Caching

Leverage caching to avoid redundant requests:

{
  "url": "https://example.com",
  "cache": {
    "enabled": true,
    "ttl": 86400
  }
}

2. Batch Multiple URLs

Use batch endpoint instead of multiple single requests:

{
  "urls": ["https://a.com", "https://b.com", "https://c.com"],
  "options": { "preset": "og_card" }
}

3. Use Webhooks for Large Jobs

For many screenshots, use async processing with webhooks:

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

4. Monitor Usage

Check your remaining limits before large operations:

curl https://api.renderscreenshot.com/v1/usage \
  -H "Authorization: Bearer rs_live_xxxxx"

5. Implement Request Queuing

For high-volume applications, implement a request queue that respects rate limits.

Requesting Higher Limits

Enterprise customers can request custom rate limits. Contact [email protected] with:

  • Your current plan and account ID
  • Expected request volume
  • Use case description

See Also

Was this page helpful?