Instant Snap API
Rate limits and quota
A capture holds a browser open for the whole request. Three ceilings apply to how fast you can ask for captures, and none of them is the same thing as your plan allowance.
The limits
| Value | Meaning |
|---|---|
Your plan's API rate limit | The requests a minute your plan accepts: 40 on Starter, 80 on Pro, 150 on Business, 200 on Business Plus and 10 on the free trial. It limits how fast requests are accepted, not how quickly captures finish. The allowance belongs to the workspace, not to a key, and it is shared with your Auto Schedules — unless you reserve part of it for each on the Capacity page. A request past it answers 429 rate_limited with the seconds until the next minute. |
60 requests per minute, per IP address | Counted before your key is even looked at. Several keys behind one address share this ceiling. |
300 reads of a capture per minute, per IP address | GET /captures/{id} has a window of its own, five times the one above, so polling an async capture never spends what your captures need. |
2 captures at a time per workspace | A request that arrives while two of your captures are still rendering waits briefly, then answers 503 capture_busy. |
100 async captures waiting or running per workspace | An async capture is not refused when your captures are busy: it waits its turn, for up to 15 minutes. Past 100 in the queue a new one answers 429 queue_full. |
No per-key or daily limits
Limits are not quota
Two different things can refuse a capture, and they need different responses from your code:
| Value | Meaning |
|---|---|
429 rate_limited | You are going too fast. Wait and the same request succeeds. Nothing has been spent. |
402 quota_exhausted | Your plan allowance for the period is gone. Waiting a minute changes nothing — the answer is a larger plan or the next billing period. |
403 feature_not_available | Your plan does not include a field you sent, such as proxy or cookies. No amount of usage or waiting turns this into a yes. |
Do not retry a 402 or a 403
429 and 503; surface 402 and 403 to a human.Concurrency and capture_busy
Separately from the rate limits, a workspace has at most two captures rendering at once. A request that arrives while both are in progress waits briefly, and if neither finishes in time it answers 503 capture_busy.
capture_busyis not your fault and does not count against your quota.- It is always worth retrying, and it usually succeeds on the next attempt.
- If you see it often, lower your own concurrency rather than raising your retry count — submitting more work to a full queue does not make it emptier.
Backing off correctly
A refusal tells you how long to wait, in both the Retry-After header and the retry_after_seconds field. Use it rather than a fixed sleep:
HTTP/1.1 429 Too Many Requests
Retry-After: 31
{
"success": false,
"error_code": "rate_limited",
"error_message": "Too many requests; please wait before retrying.",
"retry_after_seconds": 31
}async function capture(body, attempt = 0) {
const response = await fetch(url, { method: "POST", headers, body });
if (response.status === 429 || response.status === 503) {
const payload = await response.json();
const wait = (payload.retry_after_seconds ?? 2 ** attempt) * 1000;
if (attempt >= 4) throw new Error(payload.error_code);
await new Promise((resolve) => setTimeout(resolve, wait));
return capture(body, attempt + 1);
}
return response;
}- Honour the value you were given before falling back to exponential backoff.
- Cap the number of attempts. An unbounded retry is how one late capture becomes an outage.
- Add a little jitter if many workers share a key, or they will all wake up at the same instant and be refused together.
There are no X-RateLimit headers
The API does not publish X-RateLimit-Limit, X-RateLimit-Remaining or X-RateLimit-Reset on successful responses. You learn your remaining headroom by being refused, not by reading it off every answer — so count your own calls if you need to pace yourself, and treat a 429 as the signal it is rather than as an error.
Staying under them
- Queue work rather than firing it, and send at most two captures at a time. Pace the queue to your plan's rate limit rather than to how fast answers come back.
- Reserve capacity for the API on the Capacity page if your schedules and your code run at the same time, so one cannot hold up the other.
- Cache. A capture of a page that has not changed is a capture you did not need — the id is stable for 24 hours and reading it back does not consume a capture.
- For recurring captures, an Auto Schedule does the same work without spending Instant Snap API calls at all.
Did this page answer your question?
Tell us what is missing