Rate Limits & Plan Features
Two levels of limits apply to every API key, plus feature restrictions by plan.
Request limits by plan
| Plan | Per Minute | Per Month | Max Resolution | Price |
|---|---|---|---|---|
| Free | 5 | 100 | 1920×1080 | $0 |
| Starter | 30 | 5,000 | 3840×2160 | $19/mo |
| Growth | 60 | 25,000 | 3840×2160 | $49/mo |
| Business | 120 | 100,000 | 3840×2160 | $149/mo |
| Enterprise | 300 | Unlimited | 3840×2160 | Custom |
Feature access by plan
Not all features are available on every plan. Requests using a restricted feature return 403 with plan_required.
| Feature | Free | Starter | Growth | Business | Enterprise |
|---|---|---|---|---|---|
| Screenshot API | ✅ | ✅ | ✅ | ✅ | ✅ |
| PNG & JPEG | ✅ | ✅ | ✅ | ✅ | ✅ |
| Dark mode | ✅ | ✅ | ✅ | ✅ | ✅ |
| Device presets | ✅ | ✅ | ✅ | ✅ | ✅ |
| Caching | ✅ | ✅ | ✅ | ✅ | ✅ |
| WebP format | ❌ | ✅ | ✅ | ✅ | ✅ |
| Full page | ❌ | ✅ | ✅ | ✅ | ✅ |
| Retina (2× DPR) | ❌ | ✅ | ✅ | ✅ | ✅ |
| Ad blocking | ❌ | ✅ | ✅ | ✅ | ✅ |
| CSS injection | ❌ | ✅ | ✅ | ✅ | ✅ |
| OG Image API | ❌ | ✅ | ✅ | ✅ | ✅ |
| No watermark | ❌ | ✅ | ✅ | ✅ | ✅ |
| JS injection | ❌ | ❌ | ✅ | ✅ | ✅ |
| Stealth mode | ❌ | ❌ | ✅ | ✅ | ✅ |
| Custom proxy | ❌ | ❌ | ✅ | ✅ | ✅ |
| Custom templates | ❌ | ❌ | ✅ | ✅ | ✅ |
| Team members | ❌ | ❌ | 3 | 10 | Unlimited |
| Support | Community | Priority | Slack | Dedicated | |
| SLA | — | — | — | 99.9% | Custom |
Response headers
Every response includes rate limit info:
X-RateLimit-Limit: 30 # Your plan's per-minute limit
X-RateLimit-Remaining: 22 # Requests left this minute
X-RateLimit-Reset: 1711382400 # Unix timestamp when the window resetsWhen rate limited:
HTTP/1.1 429 Too Many Requests
Retry-After: 30Handling 429 errors
Per-minute rate limit exceeded:
{
"error": "rate_limited",
"message": "Rate limit exceeded. Retry after 30 seconds",
"status": 429,
"retry_after": 30
}Monthly quota exceeded:
{
"error": "quota_exceeded",
"message": "Monthly request quota exceeded. Upgrade plan.",
"status": 429
}Feature access denied (403)
When you use a feature above your plan:
{
"error": "plan_required",
"message": "Stealth mode requires Growth plan or above",
"required_plan": "growth",
"status": 403
}Retry strategy
Implement exponential backoff when you receive a 429. Start with the Retry-After value and double on each subsequent failure.
async function screenshotWithRetry(url, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const res = await fetch(`https://api.snapsharp.dev/v1/screenshot?url=${url}`, {
headers: { Authorization: `Bearer ${process.env.SNAPSHARP_KEY}` },
});
if (res.status === 429) {
const retryAfter = parseInt(res.headers.get('Retry-After') ?? '30');
await new Promise(r => setTimeout(r, retryAfter * 1000 * Math.pow(2, attempt)));
continue;
}
return res;
}
throw new Error('Max retries reached');
}