Rate limits — per-plan caps, burst behavior, X-RateLimit-* headers and the right retry strategy.
DomainScan enforces three independent rate-limit layers: per-minute, per-day and per-second burst. Limits scale to your plan and are returned on every response via X-RateLimit-* headers. This page covers the exact caps, how 429 responses work, the right retry algorithm and the most common mistakes integrations make.
Caps by plan
All four numbers apply simultaneously — you hit 429 when any one is exhausted.
- Anonymous (no key) 20 req/min · 200 req/day · 1 req/sec burst · per-IP.
- Free 10 req/min · 1,000 req/day · 2 req/sec burst · 100 credits/mo.
- Starter ($5/mo) 30 req/min · 5,000 req/day · 5 req/sec burst · 5,000 credits/mo.
- Pro ($18/mo) 100 req/min · 25,000 req/day · 10 req/sec burst · 20,000 credits/mo. 99.5% SLA.
- Business ($82/mo) 300 req/min · 100,000 req/day · 20 req/sec burst · 100,000 credits/mo. 99.9% SLA.
Rate-limit headers on every response
Returned on both 2xx and 429 responses. Match the IETF draft-ietf-httpapi-ratelimit-headers naming where practical.
- X-RateLimit-Limit Cap for the current window. Per-minute cap by default; per-hour and per-day caps available via X-RateLimit-Limit-Hour / X-RateLimit-Limit-Day.
- X-RateLimit-Remaining Calls left in the current window. Use this to slow down preemptively before hitting 429.
- X-RateLimit-Reset Unix epoch (seconds) when the current window resets. Compute wait time as `Reset - now`.
- Retry-After Returned on 429 responses only. Seconds to wait before retrying. Honor this — bypassing it lengthens the cool-down.
HTTP/1.1 200 OK
Content-Type: application/json
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 87
X-RateLimit-Reset: 1750179600What to do when you hit a 429
Standard exponential backoff with jitter. Specifically:
async function callWithBackoff(url, opts, maxRetries = 5) {
let attempt = 0;
while (true) {
const res = await fetch(url, opts);
if (res.status !== 429) return res;
if (attempt >= maxRetries) throw new Error('rate_limited');
const retryAfter = Number(res.headers.get('Retry-After') || '1');
const jitter = Math.random() * 0.3 + 0.85; // 85-115%
const backoff = Math.min(60, retryAfter * Math.pow(2, attempt)) * jitter;
await new Promise(r => setTimeout(r, backoff * 1000));
attempt += 1;
}
}- Honor Retry-After It is the minimum suggested wait. Treating it as zero will get you re-throttled instantly.
- Add jitter If thousands of clients backoff in lockstep, they all retry at the same instant. Multiply the backoff by a random factor between 0.85 and 1.15.
- Cap the wait Cap at ~60s. Past that, surface the failure rather than blocking the calling thread indefinitely.
- Limit retry count 5 retries is plenty. Beyond that, escalate — either the limit is correctly enforced and you need to upgrade the plan, or there's a deeper issue.
Burst behavior — what the per-second cap actually does
Burst is independent of the per-minute and per-day caps. It absorbs short spikes from concurrent calls without immediately triggering 429:
- Token-bucket model Each plan has a per-second token budget (e.g. Pro = 10 tokens/sec). Each request consumes one token. Tokens refill continuously.
- Bucket size = burst The bucket can hold up to (burst limit × ~3) tokens before refusing. This is how short concurrent spikes pass without 429 — provided the average rate stays below the limit.
- Tip: concurrency = burst Set your client's concurrency to the burst limit. Higher concurrency just gets rate-limited.
Per-endpoint credit cost
Credits are independent of rate limits — credits track monthly volume, rate limits track instantaneous concurrency. Most endpoints cost 1 credit; a few are heavier:
- 1 credit Domain Lookup, DNS Query, IP Lookup, Ping, Subnet, Reverse DNS, MAC Info, SSL Info, Security Headers, SPF, DMARC, DKIM, single-port scan.
- 2 credits DNS Propagation (queries 4 resolvers in parallel), Common-Ports Sweep, SSL Chain validation.
- 5 credits Domain Trust Score composite, Domain Snapshot (Playwright render).
- AI credits Prism AI inference uses a separate AI-credit pool, bundled at the same monthly count as API credits.
Mistakes we see repeatedly
Four anti-patterns that cause the bulk of rate-limit support tickets:
- Ignoring Retry-After Retrying instantly on 429 just deepens the cool-down. Always honor Retry-After at minimum.
- No jitter Synchronized retries across a fleet of clients create a thundering herd. Add ±15% random jitter.
- Bursting from the dashboard Loading the dashboard with many tools open at once can flood your own per-minute limit. Pro plans scale through this; if you see 429s in the UI on Free, batch your audits.
- Anonymous in production Anonymous limits are intentionally tight (20/min). Production traffic should always go through an authenticated key, even on the free tier.