Rate Limits
API usage is subject to fair-use limits that may change without notice.
Results per page. List endpoints return at most 100 results per page on all paid tiers (10 on Free), controlled by the per_page query parameter. There is no pagination depth cap on paid tiers, so the full result set is retrievable by paging through it — see Pagination for Large Datasets.
Monthly API-call allowance. Each organization has a monthly allowance for calls made with a bs_live_ API key: 25,000/month on Professional, unlimited on Enterprise. Every API-key response reports your current position via headers:
| Header | Meaning |
|---|---|
X-RateLimit-Limit | Your monthly allowance (unlimited on unlimited tiers) |
X-RateLimit-Used | Calls made so far this calendar month |
X-RateLimit-Remaining | Calls left this month (unlimited on unlimited tiers) |
These headers are informational: the allowance is currently tracked and reported but not enforced, so calls are not rejected for exceeding it. The counter resets at the start of each calendar month (UTC).
Burst rate. If you send too many requests in a short window you may receive HTTP 429 with error code RATE_LIMITED. Back off and retry.
Handling Rate Limits
When you receive HTTP 429 (error code RATE_LIMITED), back off and retry.
import time
import requests
def api_request(url, headers, max_retries=3):
for attempt in range(max_retries):
response = requests.get(url, headers=headers)
if response.status_code == 429:
retry_after = int(response.headers.get("Retry-After", 60))
time.sleep(retry_after)
continue
return response
raise Exception("Rate limit exceeded after retries")
Pagination for Large Datasets
Always paginate large requests rather than fetching all at once.
def fetch_all_cves(api_key, severity="CRITICAL"):
headers = {"Authorization": f"Bearer {api_key}"}
base_url = "https://breachspider.com/api/v1/cves"
page = 1
while True:
response = requests.get(
f"{base_url}?severity={severity}&page={page}&per_page=100",
headers=headers
)
data = response.json()
yield from data["data"]
if not data["pagination"]["has_next"]:
break
page += 1