CVE API

JSON over HTTPS. No API key, no account, no signup. Everything below works from a terminal right now.

Try it
curl "https://vuln.mlab.sh/api/v1/cve/CVE-2021-44228"

Returns the full record: CVSS score and vector breakdown, CWEs, EPSS, CISA KEV status with its remediation deadline, affected products and references.

Endpoints
Endpoint What it returns
GET /api/v1/cve Search. q, severity, dateStart, dateEnd, minCvss, kevOnly, exact, minSeverity, page, limit (max 100). Actively-exploited matches lead the first page, then newest first; sort=recent or sort=severity to change it.
GET /api/v1/cve/{id} One CVE, in full. Served from a multi-source pool, so it keeps working when any single upstream is throttled.
GET /api/v1/cve/latest The newest CVEs, published in the last 7 days.
GET /api/v1/cve/dump Bulk export for a date range, filtered by minimum CVSS. Requires dateStart and dateEnd, max 31 days apart.
POST /api/v2/query OSV-compatible, package-scoped lookup. Send an OSV request body, get OSV's native {"vulns": […]} back: usable as a drop-in source for any OSV client.
POST /api/v2/scan Whole-manifest SBOM scan in one request, instead of one call per package.
GET /api/v1/stats Corpus totals and the severity breakdown.
GET /api/v1/sources Sync state of every data source and the national CERT feeds' health.
GET /rss · /feed RSS. Accepts the same filters as search, so you can subscribe to a query.
GET /export/csv CSV export of a search.
Limits

Read endpoints are unmetered and cached at the edge; use them freely.

/api/v1/cve/dump is the one exception: 12 calls per hour per IP, 15 seconds between calls, and a 31-day maximum range. Exceeding it returns 429 with Retry-After.

/api/v2/scan limits depend on the caller: anonymous 512 packages per scan, 4 MiB body, one scan every 10 seconds per IP; free account (session or API token) 1024 packages, 8 MiB, one every 5 seconds; paid plans 4096 packages, 32 MiB, no cooldown.

Every response states tier and limits. A bigger manifest is cut and reported in truncation (the packages past the cut are not scanned, never "clean"); an oversized body returns 413 and a scan inside the cooldown 429 with Retry-After, both with a message and, below the top tier, an upgrade block.

Reading a failure

Status codes are meant to be acted on, which matters if you gate a build on them:

200 with an empty list means no known vulnerabilities. 502 and 503 mean an upstream is down or throttled.

Never treat a 5xx as "clean": it is an outage, not an answer.

Full reference

Every parameter, response field and error, with worked examples.

Read the docs