# CVE Scraper: NVD Vulnerabilities, CVSS & CPE (`arman-bd/cve-vulnerability-scraper`) Actor

Scrape the NIST National Vulnerability Database: CVE IDs, descriptions, CVSS v3 scores and vectors, CWE classification, affected CPE configurations and references. No login, no proxy, no browser.

- **URL**: https://apify.com/arman-bd/cve-vulnerability-scraper.md
- **Developed by:** [Arman Hossain](https://apify.com/arman-bd) (community)
- **Categories:** Developer tools, MCP servers
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.74 / 1,000 cve scrapeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## CVE Scraper: NVD Vulnerabilities, CVSS & CPE

![CVE Scraper: CVE records with CVSS v3 scores and vectors, CWE classification, affected CPE products and reference links](https://api.apify.com/v2/key-value-stores/ZQOcNAOHrIgTacAmy/records/cve-vulnerability-scraper.jpg)

Scrape the NIST National Vulnerability Database: CVE IDs, descriptions, CVSS v3 scores and vectors, CWE classification, affected CPE configurations and references. Give it a keyword and it returns one structured record per CVE.

**Agent skill: [SKILL.md](https://api.apify.com/v2/key-value-stores/t7YoTxpZEJOWvw4Ug/records/cve-vulnerability-scraper.md)**

```
https://api.apify.com/v2/key-value-stores/t7YoTxpZEJOWvw4Ug/records/cve-vulnerability-scraper.md
```

### What it does

The Actor covers the ~373,000 CVEs in NIST's National Vulnerability Database, and flattens each vulnerability into a single flat dataset row.

For every CVE it resolves:

- the English description and the current NVD analysis **status**,
- the **CVSS v3 base score, severity and vector**, preferring NIST's own "Primary" assessment over a vendor's secondary one, along with the exploitability and impact sub-scores,
- the **CWE** weakness classification,
- every **affected CPE configuration**, including version ranges, plus a de-duplicated `vendor:product` summary,
- every **reference URL** with its NVD tags (`Patch`, `Exploit`, `Vendor Advisory`, …).

Filters compose: a keyword, a CPE product, a published-date floor and a minimum CVSS score can all be applied at once. Date ranges longer than NVD's 120-day maximum are split into consecutive windows automatically and paged one after another.

### Input

| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| `keywordSearch` | string | | - | Keyword search across CVE descriptions. NVD requires **all** words to match, so `microsoft outlook` returns only CVEs mentioning both. |
| `cveIds` | array | | `[]` | Specific CVE identifiers, e.g. `CVE-2024-3094`. When set, NVD is queried one ID at a time and `keywordSearch` / `cpeName` are ignored, the API does not accept them alongside a CVE ID. |
| `cpeName` | string | | - | Return only CVEs affecting this CPE 2.3 product. Must be a complete, well-formed CPE 2.3 URI; NVD rejects partial ones. |
| `minCvssScore` | integer | | `0` | Keep only CVEs with a CVSS v3 base score at or above this value (0-10). Applied locally, so CVEs with no CVSS v3 metric are dropped when this is above `0`. |
| `publishedFrom` | string | | - | Only CVEs published on or after this date (`YYYY-MM-DD`). Ranges longer than 120 days are split into windows automatically. |
| `maxResults` | integer | | `100` | Cap the total CVEs saved across every query. `0` means no limit. |
| `nvdApiKey` | string | | - | Optional [free NVD API key](https://nvd.nist.gov/developers/request-an-api-key). Raises the pace from 5 to 50 requests per 30 seconds. |

#### Example input

```json
{
 "keywordSearch": "openssl",
 "minCvssScore": 7,
 "publishedFrom": "2026-01-01",
 "maxResults": 25
}
```

#### Which combinations make sense

- `keywordSearch` + `publishedFrom` is the workhorse: everything new about a technology you run.
- `cpeName` + `minCvssScore` is the precise form, exact product, only serious findings. Prefer it to a keyword when you know the CPE, because keyword matching is textual and will catch unrelated mentions.
- `cveIds` is a **lookup**, not a search. It ignores the other query filters (`minCvssScore` still applies locally) and costs one request per ID, so a long list is slow without an API key.
- Leaving everything empty is legal and walks the whole database from the oldest CVE forward, combine with `maxResults` or you will be there a while.

### Output

One dataset item per CVE. A real record from the example input above, abridged:

```jsonc
{
 "cveId": "CVE-2025-59464",
 "description": "A memory leak in Node.js's OpenSSL integration occurs when converting `X.509` certificate fields to UTF-8 without freeing the allocated buffer.",
 "publishedDate": "2026-01-20T21:16:03.900", // NVD publication timestamp
 "lastModified": "2026-06-17T09:46:12.450", // last NVD revision, watch this for re-scores
 "cvssV3Score": 7.5, // base score, NIST's Primary metric when present
 "cvssV3Severity": "HIGH", // NONE | LOW | MEDIUM | HIGH | CRITICAL
 "cvssV3Vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
 "cweIds": ["CWE-400"], // weakness classification, de-duplicated
 "affectedProducts": ["nodejs:node.js"], // vendor:product, derived from the CPE matches
 "cpeMatches": [ // full affected configurations with version bounds
 {
 "criteria": "cpe:2.3:a:nodejs:node.js:*:*:*:*:-:*:*:*",
 "vulnerable": true,
 "versionStartIncluding": "24.0.0",
 "versionStartExcluding": null,
 "versionEndIncluding": null,
 "versionEndExcluding": "24.12.0"
 }
 ],
 "references": [
 {
 "url": "https://nodejs.org/en/blog/vulnerability/december-2025-security-releases",
 "source": "support@hackerone.com",
 "tags": ["Release Notes", "Vendor Advisory"]
 }
 ],
 "exploitabilityScore": 3.9, // CVSS v3 sub-score
 "impactScore": 3.6, // CVSS v3 sub-score
 "status": "Analyzed", // NVD analysis state: Analyzed, Modified, Awaiting Analysis…
 "nvdUrl": "https://nvd.nist.gov/vuln/detail/CVE-2025-59464",
 "scrapedAt": "2026-08-06T11:32:03.941Z"
}
```

`cvssV3Score`, `cvssV3Severity`, `cvssV3Vector`, `exploitabilityScore` and `impactScore` are `null` for CVEs that predate CVSS v3 or are still awaiting analysis.

#### `RUN_SUMMARY`

Written to the key-value store as `RUN_SUMMARY`:

```json
{
 "queryUnits": 2,
 "queryUnitsFailed": 0,
 "requestsMade": 2,
 "cvesSaved": 25,
 "cvesBelowCvssThreshold": 19,
 "failures": [],
 "filters": {
 "keywordSearch": "openssl",
 "cveIds": [],
 "cpeName": null,
 "minCvssScore": 7,
 "publishedFrom": "2026-01-01",
 "maxResults": 25
 },
 "usedApiKey": false,
 "finishedAt": "2026-08-06T11:32:10.967Z"
}
```

A *query unit* is one independent piece of work: one CVE-ID lookup, or one 120-day date window, or the single unfiltered query. `failures` lists any unit that could not be fetched, with the `startIndex` it stopped at.

### Use cases

**1. Feed a vulnerability-management pipeline.** Pull every serious CVE published since your last sync and hand the dataset to your ticketing system. Schedule it daily and move `publishedFrom` forward.

```json
{ "publishedFrom": "2026-08-01", "minCvssScore": 7, "maxResults": 0 }
```

**2. Alert on CVEs affecting your stack.** Pin an exact product with a CPE and watch only that.

```json
{ "cpeName": "cpe:2.3:o:linux:linux_kernel:6.6:*:*:*:*:*:*:*", "minCvssScore": 8, "maxResults": 200 }
```

**3. Security research and reporting.** Look up a specific set of CVEs with full CVSS vectors, CWE classification and references for a write-up.

```json
{ "cveIds": ["CVE-2024-3094", "CVE-2021-44228", "CVE-2014-0160"] }
```

### Limits and behaviour

- **Rate limits.** The public API allows **5 requests per 30 seconds**; a free API key raises this to 50. The Actor sleeps 6.5 s between requests without a key and 0.8 s with one. This is baked in, you cannot outrun it, and a large unfiltered pull will take a while.
- **120-day date windows.** NVD rejects any published-date range wider than 120 days, and rejects `pubStartDate` without `pubEndDate`. A `publishedFrom` far in the past is therefore split into consecutive 120-day windows, each paged independently.
- **Page size.** Requests use NVD's maximum of 2,000 results per page, so most queries finish in one or two requests.
- **`minCvssScore` is applied locally.** NVD's API filters by severity band, not by numeric score, so the Actor fetches full pages and drops what falls below your floor. The count that was dropped appears in `RUN_SUMMARY.cvesBelowCvssThreshold`.
- **Failures never abort the run.** If one date window or CVE lookup fails after three retries. It is logged, recorded in `RUN_SUMMARY.failures`, and the run continues with the next. The run only fails outright if *every* query unit failed.
- **Retries.** 3 attempts with linear backoff. HTTP 403, 429 and 5xx are retried; a malformed query, which NVD reports as a 404 with the reason in a `message` header, fails immediately rather than burning retries.
- **De-duplication.** A CVE is never written twice, even if it matches several query units.

### FAQ

**Do I need a proxy?** No. Proxy configuration is not required to run this Actor.

**Do I need an account on the source?** No. You supply no credentials.

**What happens if a source is unavailable?** It is reported in `RUN_SUMMARY.failures` and the run continues. Only a total failure of every query aborts the run.

**Can I schedule it?** Yes, it is designed for scheduled runs. Set `publishedFrom` to your last sync date and run it daily.

**Why is `cvssV3Score` null on some records?** Those CVEs predate CVSS v3 (roughly pre-2016) or are still awaiting NVD analysis. Their `status` field will say so. Set `minCvssScore` above 0 to exclude them.

**Can I get CVSS v2 scores?** Not currently, the Actor reports CVSS v3.1/v3.0 only, matching the fields most vulnerability tooling expects.

# Actor input Schema

## `keywordSearch` (type: `string`):

Keyword search across CVE descriptions. NVD matches all words in the phrase, case-insensitively. 'microsoft outlook' returns only CVEs mentioning both. Leave empty to skip keyword filtering.

## `cveIds` (type: `array`):

Specific CVE identifiers to fetch, e.g. 'CVE-2024-3094'. When this is set NVD is queried one ID at a time and the keyword and CPE filters are ignored, because the NVD API does not accept them alongside a CVE ID.

## `cpeName` (type: `string`):

Return only CVEs affecting this CPE 2.3 product, e.g. 'cpe:2.3:o:linux:linux_kernel:6.6:*:*:*:*:*:*:\*'. Must be a full, well-formed CPE 2.3 URI. NVD rejects partial ones.

## `minCvssScore` (type: `integer`):

Keep only CVEs whose CVSS v3 base score is at least this value (0-10). Applied locally after fetching, so CVEs with no CVSS v3 metric at all are dropped when this is above 0. Set 0 to keep everything.

## `publishedFrom` (type: `string`):

Only CVEs published on or after this date, as YYYY-MM-DD. NVD caps a date range at 120 days, so longer ranges are automatically split into consecutive windows and paged one after another.

## `maxResults` (type: `integer`):

Cap the total number of CVEs saved across every query. Set 0 for no limit. but note the unfiltered database holds over 370,000 CVEs and the public API is rate limited to 5 requests per 30 seconds.

## `nvdApiKey` (type: `string`):

A free NVD API key from https://nvd.nist.gov/developers/request-an-api-key. Without one the Actor paces requests at 5 per 30 seconds; with one it goes ten times faster at 50 per 30 seconds. Not required.

## Actor input object example

```json
{
  "keywordSearch": "apache log4j",
  "cveIds": [
    "CVE-2024-3094",
    "CVE-2021-44228"
  ],
  "cpeName": "cpe:2.3:a:openssl:openssl:3.0.0:*:*:*:*:*:*:*",
  "minCvssScore": 0,
  "publishedFrom": "2026-01-01",
  "maxResults": 100
}
```

# Actor output Schema

## `items` (type: `string`):

Every record the run produced.

## `runsummary` (type: `string`):

The RUN_SUMMARY record from the run's key-value store.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "keywordSearch": "openssl"
};

// Run the Actor and wait for it to finish
const run = await client.actor("arman-bd/cve-vulnerability-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "keywordSearch": "openssl" }

# Run the Actor and wait for it to finish
run = client.actor("arman-bd/cve-vulnerability-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "keywordSearch": "openssl"
}' |
apify call arman-bd/cve-vulnerability-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,arman-bd/cve-vulnerability-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/1rv11xsmYRxOIuLv3/builds/mPvy1FIyS5OhHqJ1P/openapi.json
