Skip to content

Collections

This page documents the collection catalogue and the archive endpoints built on it: listing every available collection, fetching published collections from the CDN, and getting collection updates from the database. Except for the public catalogue endpoint, every example authenticates with an API key via the X-Api-Key header.

Open interactive specs

Python SDK v4

Python examples use the v4 sync client: from vulners import Vulners, then v = Vulners(api_key="YOUR_API_KEY_HERE"). Every method shown has an identical awaitable mirror on AsyncVulners. For multi-gigabyte collections the SDK can also stream records lazily (v.archive.iter_collection(...), async aiter_collection) or save the archive straight to disk (v.archive.download_collection(...)) with constant memory use. See the Python SDK page for details.

List available collections

Return the catalogue of every collection Vulners stores: identifier, human-readable name, family, a one-sentence description, the current record count and the last time any of its records changed. This is the authoritative list of collection names — pass them as ?type= to /api/v4/archive/collection and /api/v4/archive/collection-update, or as the type: filter of a search query. Descriptions are written for machine consumption, so an LLM agent can pick the right collection before querying it.

Auth: public — no API key required, and the call is not charged against your request quota. Keep sending X-Api-Key from code anyway: the header is accepted here, and a request without it can be stopped by the edge bot protection before it reaches the API.

Parameters:

None.

Response:

An object with a single result array, one entry per collection, sorted by count from the largest collection to the smallest. Field names are snake_case here, and all timestamps are UTC.

Field Type Description
type string Collection identifier, e.g. exploitdb. The value to pass as ?type= to the archive endpoints and as type: in search queries.
display_name string Human-readable source name as declared by the robot that fills the collection (Exploit DB). Falls back to type when the robot declares none.
bulletin_family string Family the collection belongs to — cve, unix, software, exploit, bugbounty, … Same taxonomy as the bulletinFamily document field; casing is not normalised, so compare it case-insensitively. Empty string for a collection the stats task has not classified yet.
description string One-sentence description of the source and what it publishes. Falls back to type while no description has been generated.
count integer Records currently held in the collection.
last_updated string | null Newest modified timestamp across the collection (YYYY-MM-DDTHH:MM:SS). null for a collection with no computed timestamp yet.
archived boolean true when the source is no longer collected. Its documents stay in the database and remain searchable, and the catalogue keeps listing it — filter client-side if you only want live sources.

Freshness

count and last_updated come from a pre-computed summary that a background task refreshes roughly once an hour, and the response itself is cached for 5 minutes. Treat both as a recent snapshot rather than a live count: for an exact figure run a search query with type:<name> and read data.total.

Usage:

Query:

GET /api/v4/search/collections

Query example:

curl -sS "https://vulners.com/api/v4/search/collections" -H "X-Api-Key: YOUR_API_KEY" --compressed
collections = v.search.collections()   # dicts: type, display_name, bulletin_family, description, count, last_updated, archived
live = [c for c in collections if not c["archived"]]
exploits = [c["type"] for c in live if c["bulletin_family"].lower() == "exploit"]
{
  "result": [
    {
      "type": "openbugbounty",
      "display_name": "Openbugbounty",
      "bulletin_family": "bugbounty",
      "description": "OpenBugBounty is a community-driven platform that catalogs security advisories and vulnerabilities reported by researchers across various vendors and products.",
      "count": 1261610,
      "last_updated": "2025-07-23T13:56:00",
      "archived": false
    },
    {
      "type": "cve",
      "display_name": "CVE",
      "bulletin_family": "cve",
      "description": "The CVE collection from MITRE provides a comprehensive list of publicly disclosed vulnerabilities across various vendors, OS, and products, including CVEs and related advisories.",
      "count": 354266,
      "last_updated": "2026-05-10T08:16:08",
      "archived": false
    },
    {
      "type": "exploitdb",
      "display_name": "Exploit DB",
      "bulletin_family": "exploit",
      "description": "ExploitDB is a database of exploits and vulnerable software, primarily focusing on various applications and operating systems, providing detailed advisories and proof-of-concept code.",
      "count": 47833,
      "last_updated": "2026-05-07T00:00:00",
      "archived": false
    }
  ]
}

Get collection by name

Python examples use the Vulners Python SDK v4 (pip install -U vulners).

Fetch the full collection archive file (records) for a named collection from the CDN. Collections are updated on the CDN every 4 hours; records are sorted by timestamps.updated (newest → oldest). Timestamps are UTC.

Streaming response

Unlike the rest of the v4 API, archive endpoints do not return JSON-wrapped responses. The server either streams gzipped NDJSON (one bulletin per line, Content-Encoding: gzip, Content-Type: application/x-ndjson or application/gzip) or responds with 302 Redirect to a CDN-hosted gzipped NDJSON URL. Free-tier API keys receive 403 Forbidden.

Parameters:

Name In Type Required Description
type query string yes Collection type name (see available collections on the Vulners stats page, e.g. exploitdb)

Returns list of records from the collection archive stored on CDN. These archives are updated every 4 hours.

The records in response are sorted by timestamps.updated from newest to oldest. All timestamps are in UTC.

Usage:

Query:

GET /api/v4/archive/collection/

Query example:

curl -GOJL "https://vulners.com/api/v4/archive/collection/" -H "X-Api-Key: YOUR_API_KEY" \
    --data-urlencode "type=exploitdb"
records = v.archive.fetch_collection(type="exploitdb")
# or stream lazily with constant memory:
# for record in v.archive.iter_collection("exploitdb"): ...
[
    {'id': 'EDB-ID:20048', ... 'timestamps.updated': '2025-05-21T13:14:26.791000+00:00', ...},
    {'id': 'EDB-ID:18781', ... 'timestamps.updated': '2025-05-21T13:14:26.648000+00:00', ...},
    {'id': 'EDB-ID:30807', ... 'timestamps.updated': '2025-05-21T11:54:55.905000+00:00', ...},
    {'id': 'EDB-ID:31180', ... 'timestamps.updated': '2025-05-21T11:54:55.150000+00:00', ...},
    ...,
    {'id': 'EDB-ID:46363', ... 'timestamps.updated': '2025-04-02T20:47:28+00:00', ...}
]

Get collection update by name

Note: Python examples use the Vulners Python SDK v4 (pip install -U vulners).

Get recently updated records for a collection directly from the database. Useful for incremental synchronization.

Auth: X-Api-Key header required.

Parameters:

Name In Type Required Description
type query string yes Collection type name (e.g. exploitdb)
after query string (ISO 8601) yes Return records updated after this UTC timestamp. Must not be more than 169 hours (7 days + 1 hour) from the current time. Example: 2025-05-21T13:14:26

Returns list of records for the collection directly from the database.

The records in response are sorted by timestamps.updated from newest to oldest. All timestamps are in UTC.

Response headers:

Name Type Description
X-Total-Count integer Number of records in this update, counted when the request is received. Read it to size the update before downloading the body. A record updated while the response is being streamed is still sent, so the body can occasionally hold a few more records than announced.

The body is streamed, so the header is the only way to know the size of the update in advance. With curl, add -D - to print the response headers:

curl -GOJL -D - "https://vulners.com/api/v4/archive/collection-update/" -H "X-Api-Key: YOUR_API_KEY" \
    --data-urlencode "type=exploitdb" \
    --data-urlencode "after=2025-05-21T13:14:26"
HTTP/1.1 200 OK
Content-Type: application/x-gzip-compressed
Content-Disposition: attachment; filename="exploitdb.json.gz"
X-Total-Count: 3

Usage:

Query:

GET /api/v4/archive/collection-update/

Query example:

curl -GOJL "https://vulners.com/api/v4/archive/collection-update/" -H "X-Api-Key: YOUR_API_KEY" \
    --data-urlencode "type=exploitdb" \
    --data-urlencode "after=2025-05-21T13:14:26" \
from datetime import datetime

updates = v.archive.fetch_collection_update(type="exploitdb", after=datetime(2025, 5, 21, 13, 14, 26))
[
    {'id': 'EDB-ID:30632', ... 'timestamps.updated': '2025-05-21T14:59:28.854000+00:00', ...},
    {'id': 'EDB-ID:4779', ... 'timestamps.updated': '2025-05-21T14:04:18.852000+00:00', ...},
    {'id': 'EDB-ID:4779', ... 'timestamps.updated': '2025-05-21T14:04:18.852000+00:00', ...}
]

Get collection state

Return the current sync cursor and metadata for a CDN-cached collection. Pair with Get collection update by name to drive incremental syncs.

Auth: X-Api-Key header required.

Parameters:

Name In Type Required Description
type query string yes Collection type name (see available collections on the Vulners stats page, e.g. exploitdb)

Usage:

Query:

GET /api/v4/archive/collection-state/

Query example:

curl -G "https://vulners.com/api/v4/archive/collection-state/" -H "X-Api-Key: YOUR_API_KEY" \
    --data-urlencode "type=exploitdb"
state = v.archive.collection_state("exploitdb")
# feed state["cursor"] back as `after` to fetch_collection_update
{
    "result": {
        "cursor": "2025-05-21T13:14:26Z",
        "upload_time": "2025-05-21T13:18:00Z",
        "write_time": "2025-05-21T13:14:30Z",
        "total_docs": 47238
    }
}

Deprecated: collection family endpoints

GET /api/v4/archive/family, /api/v4/archive/family-update and /api/v4/archive/family-state are deprecated and no longer documented here. A family only bundles several collections, which the per-collection endpoints above already cover one type at a time.

Migrate to the per-collection endpoints: read the bulletin_family of each entry in /api/v4/search/collections to get the type values that made up the family, then pull each one with /api/v4/archive/collection and keep it in sync through /api/v4/archive/collection-update and /api/v4/archive/collection-state.

Planned wind-down: during a deprecation period the family endpoints will keep answering for the exploit, info, blog and cve families, flagged with a deprecation notice, and will stop serving the remaining families.