Rate limits
One budget, per IP address, for every request under /api/: 120 requests every 60 seconds. It is sized so that reading every dataset several times a minute never reaches it. The numbers on this page are read from the same setting the server enforces, so the two cannot disagree.
The limit
Pages, the CLI bundle and the install script are not counted; only requests under /api/ are.
| Budget | Requests | Window | Counted by |
|---|---|---|---|
Every /api/ request | 120 | 60 seconds, fixed, starting on the minute | client IP address (IPv6 grouped by /64) |
Unknown paths count against the budget like any other request, so it cannot be spent probing for free. A request refused with 429 is not added on top, because the window is already full. Preflight OPTIONS requests are not counted.
Headers on every answer
Every /api/ answer, a 404 or a 429 included, carries these, and browsers may read them (they are listed in Access-Control-Expose-Headers).
| Header | Meaning |
|---|---|
RateLimit-Limit | Requests allowed per window: 120. |
RateLimit-Remaining | Requests left in this window, this one counted. |
RateLimit-Reset | Seconds until the window ends and the count starts again. |
RateLimit-Policy | The budget as 120;w=60: 120 requests per 60-second window. |
Retry-After | On a 429 only: whole seconds to wait. Waiting that long always lands in a fresh window. |
If the counter itself is briefly unreachable, requests are served uncounted and the answer leaves out RateLimit-Remaining and RateLimit-Reset rather than guess them.
Over the limit
The answer is HTTP 429 with a JSON body that says when to come back.
HTTP/2 429
retry-after: 17
ratelimit-limit: 120
ratelimit-remaining: 0
ratelimit-reset: 17
{"error": "Rate limit exceeded: 120 requests per 60 seconds per IP address. Retry in 17s.", "status": 429, "retry_after": 17, "limit": 120, "window_seconds": 60, "docs": "https://vulnerabilitydata.io/docs/rate-limits"}
The vulnerabilitydata command turns that into exit code 4 with retry_after in its JSON error. A path that is not a dataset answers 404 with {"error": "Not found", …} and the index URL. CLI →