DEV Community

Alex Spinov
Alex Spinov

Posted on

NVD Has a Free API — Search 250,000+ Vulnerabilities Programmatically

The National Vulnerability Database (NVD) is the U.S. government's repository of vulnerability data. It contains 250,000+ CVEs — and it has a completely free API.

No API key required for basic queries. No authentication. Just HTTP requests.

Why This Matters

A security researcher I know was manually searching NVD's website for vulnerabilities affecting their stack. Copy-pasting CVE details into spreadsheets. It took hours every week.

Then they discovered the NVD API. Now a single script checks their entire dependency list against known vulnerabilities in seconds.

Quick Start — Search Vulnerabilities

Find all critical vulnerabilities from the last 7 days:

\`python
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:

\`python
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]}")
Enter fullscreen mode Exit fullscreen mode

`\

Search by CPE (Specific Software)

The real power — find ALL vulnerabilities for a specific product version:

\`python

All vulns for Python 3.11

params = {
"cpeName": "cpe:2.3🅰️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

\`python
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

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:

\`python
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")

    time.sleep(0.6)  # Rate limit: ~100 requests per minute
Enter fullscreen mode Exit fullscreen mode

scan_dependencies("requirements.txt")
`\

Rate Limits

Add your key as a header:

\python
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.


Building security tools? I create free APIs and developer tools — check my GitHub for more.

Top comments (0)