Rate Limits
API requests are rate-limited based on your subscription plan to ensure fair usage and system stability.
Rate Limit Headers
Every API response includes rate limit headers:
| Header | Description |
|---|---|
X-RateLimit-Limit | Your maximum requests per minute |
X-RateLimit-Remaining | Remaining requests in the current window |
X-RateLimit-Reset | Unix timestamp when the limit resets |
Rate Limits by Plan
| Plan | Requests/Minute | Requests/Day |
|---|---|---|
| Free | 1 | 50 |
| Starter Monthly | 3 | 5,000 |
| Starter Yearly | 3 | 5,000 |
| Pro Monthly | 10 | 20,000 |
| Pro Yearly | 10 | 20,000 |
| Scale Monthly | 20 | 50,000 |
| Scale Yearly | 20 | 50,000 |
Handling Rate Limits
When you exceed your rate limit, you'll receive a 429 Too Many Requests response:
{
"error": "Too Many Requests",
"message": "Rate limit exceeded. Please retry after 60 seconds."
}Best Practices
1. Check Rate Limit Headers
const response = await fetch('https://api.appmarketscraper.com/v1/scrape/shopify/apps', {
headers: { 'x-api-key': 'your_api_key' }
});
const remaining = response.headers.get('X-RateLimit-Remaining');
const reset = response.headers.get('X-RateLimit-Reset');
if (remaining === '0') {
const waitTime = (parseInt(reset) * 1000) - Date.now();
await new Promise(resolve => setTimeout(resolve, waitTime));
}2. Implement Exponential Backoff
async function fetchWithRetry(url, options, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
const response = await fetch(url, options);
if (response.status !== 429) return response;
const waitTime = Math.pow(2, i) * 1000; // 1s, 2s, 4s
await new Promise(resolve => setTimeout(resolve, waitTime));
}
throw new Error('Max retries exceeded');
}3. Use Queuing for Batch Operations
When processing multiple items, use a queue system to control request rate:
class RateLimitedQueue {
constructor(requestsPerMinute) {
this.queue = [];
this.interval = 60000 / requestsPerMinute;
this.running = false;
}
async add(fn) {
return new Promise((resolve, reject) => {
this.queue.push({ fn, resolve, reject });
if (!this.running) this.process();
});
}
async process() {
this.running = true;
while (this.queue.length > 0) {
const { fn, resolve, reject } = this.queue.shift();
try {
const result = await fn();
resolve(result);
} catch (error) {
reject(error);
}
await new Promise(r => setTimeout(r, this.interval));
}
this.running = false;
}
}
// Usage
const queue = new RateLimitedQueue(3); // 3 requests per minute
const apps = await Promise.all([
queue.add(() => fetchApp('app1')),
queue.add(() => fetchApp('app2')),
queue.add(() => fetchApp('app3')),
]);Monthly Quotas
In addition to per-minute rate limits, each plan has a monthly credit quota. Credits are deducted for each API request based on the endpoint type.
| Endpoint Type | Credits per Request |
|---|---|
| List endpoints | 1 credit |
| Detail endpoints | 1 credit |
| Reviews endpoints | 1 credit |
When you exceed your monthly quota, you'll receive an error response. Paid plans can continue making requests with overage billing.
Q: What happens if I exceed my monthly quota?
A: For paid plans, you can continue making requests with overage billing. You'll be charged based on your plan's overage rate. Free tier accounts cannot exceed their monthly quota.
Q: Do unused credits roll over?
A: No, unused credits do not roll over to the next month. All quotas reset at the start of each billing cycle.
Q: Can I upgrade my plan mid-month?
A: Yes, you can upgrade your plan at any time. Visit /pricing to view available plans and upgrade. Your new quota will be available immediately, and you'll be prorated for the remainder of your billing cycle.