NVD Has a Free API — Search 250,000+ Vulnerabilities Programmatically
Source: Dev.to
Why This Matters
A security researcher I know was manually searching the NVD website for vulnerabilities affecting their stack, copy‑pasting CVE details into spreadsheets. It took hours every week.
After discovering the NVD API, a single script now checks their entire dependency list against known vulnerabilities in seconds.
Quick Start — Search Vulnerabilities
Find all critical vulnerabilities from the last 7 days
import requests
from datetime import datetime, timedelta
base_url = "https://services.nvd.nist.gov/rest/json/cves/2.0"
# Last 7 days of critical CVEs
end = datetime.utcnow()
start = end - timedelta(days=7)
params = {
"pubStartDate": start.strftime("%Y-%m-%dT00:00:00.000"),
"pubEndDate": end.strftime("%Y-%m-%dT23:59:59.999"),
"cvssV3Severity": "CRITICAL"
}
response = requests.get(base_url, params=params)
data = response.json()
print(f"Found {data['totalResults']} critical CVEs this week")
for vuln in data.get("vulnerabilities", [])[:5]:
cve = vuln["cve"]
cve_id = cve["id"]
desc = cve["descriptions"][0]["value"][:100]
print(f"\n{cve_id}: {desc}...")No key. No signup. Just works.
Search by Keyword
Find vulnerabilities mentioning a specific technology:
params = {
"keywordSearch": "apache log4j",
"resultsPerPage": 5
}
response = requests.get(base_url, params=params)
data = response.json()
print(f"Total Log4j vulnerabilities: {data['totalResults']}")
for vuln in data["vulnerabilities"]:
cve = vuln["cve"]
metrics = cve.get("metrics", {})
# Get CVSS score if available
score = "N/A"
if "cvssMetricV31" in metrics:
score = metrics["cvssMetricV31"][0]["cvssData"]["baseScore"]
print(f"{cve['id']} | Score: {score} | {cve['descriptions'][0]['value'][:80]}")Search by CPE (Specific Software)
The real power — find all vulnerabilities for a specific product version:
# All vulns for Python 3.11
params = {
"cpeName": "cpe:2.3:a:python:python:3.11:*:*:*:*:*:*:*",
"resultsPerPage": 20
}
response = requests.get(base_url, params=params)
data = response.json()
print(f"Python 3.11 vulnerabilities: {data['totalResults']}")
for vuln in data["vulnerabilities"]:
cve = vuln["cve"]
print(f" {cve['id']}: {cve['descriptions'][0]['value'][:90]}")Get Full CVE Details
cve_id = "CVE-2021-44228" # Log4Shell
response = requests.get(f"{base_url}?cveId={cve_id}")
data = response.json()
cve = data["vulnerabilities"][0]["cve"]
print(f"ID: {cve['id']}")
print(f"Published: {cve['published']}")
print(f"Description: {cve['descriptions'][0]['value'][:200]}")
# CVSS v3.1 details
if "cvssMetricV31" in cve.get("metrics", {}):
cvss = cve["metrics"]["cvssMetricV31"][0]["cvssData"]
print(f"CVSS Score: {cvss['baseScore']} ({cvss['baseSeverity']})")
print(f"Attack Vector: {cvss['attackVector']}")
print(f"Attack Complexity: {cvss['attackComplexity']}")
# References (first three)
for ref in cve.get("references", [])[:3]:
print(f"Reference: {ref['url']}")Build a Dependency Vulnerability Scanner
Here’s something actually useful — scan your requirements.txt:
import requests
import time
def scan_dependencies(requirements_file):
"""Scan Python dependencies for known vulnerabilities."""
base_url = "https://services.nvd.nist.gov/rest/json/cves/2.0"
with open(requirements_file) as f:
deps = [
line.strip().split("==")[0]
for line in f
if line.strip() and not line.startswith("#")
]
print(f"Scanning {len(deps)} dependencies...\n")
for dep in deps:
params = {
"keywordSearch": dep,
"cvssV3Severity": "HIGH",
"resultsPerPage": 3
}
response = requests.get(base_url, params=params)
if response.status_code == 200:
data = response.json()
count = data["totalResults"]
if count > 0:
print(f"⚠ {dep}: {count} HIGH+ vulnerabilities")
for v in data["vulnerabilities"][:2]:
cve = v["cve"]
print(f" └─ {cve['id']}: {cve['descriptions'][0]['value'][:70]}")
else:
print(f"✓ {dep}: No high‑severity CVEs found")
else:
print(f"❌ {dep}: Request failed ({response.status_code})")
time.sleep(0.6) # Rate limit: ~100 requests per minute
# Example usage
scan_dependencies("requirements.txt")Rate Limits
| Access type | Requests per 30 seconds |
|---|---|
| Without API key | 5 |
| With API key (free) | 50 |
Get a key at:
Add your key as a header:
headers = {"apiKey": "your-api-key-here"}
response = requests.get(base_url, params=params, headers=headers)What You Can Build
- Vulnerability scanner for your CI/CD pipeline
- Security dashboard monitoring new CVEs daily
- Dependency checker for open‑source projects
- Threat‑intelligence feed for your security team
- Compliance tool tracking CVEs by severity and vendor
The NVD API gives you the same data that expensive security tools charge thousands for. The difference? This one is free and maintained by NIST.
Security tools? I create free APIs and developer tools — check my GitHub for more.
