Vulners Python SDK¶
The official Python client for the Vulners vulnerability intelligence database. Version 4 is a ground-up modernization of the library: a fully typed data model, mirrored sync and async clients, documentation shipped inside the package, first-class AI-agent support, and a built-in MCP server — while staying 100% backward compatible with existing v3 code.
Source and issues: github.com/vulnersCom/api · Package: pypi.org/project/vulners
Installation¶
Requires Python 3.10+. A plain install ships everything needed for fast, modern transport — HTTP/2, response compression, archive streaming — with prebuilt wheels, so there is no build step:
pip install -U vulners
Optional extras:
pip install -U "vulners[mcp]" # + built-in Model Context Protocol server
pip install -U "vulners[otel]" # + opt-in OpenTelemetry tracing
API key
All API calls require an API key. Sign in at vulners.com, open your personal menu, select the API KEYS tab and generate a key with the api scope — see Getting an API key for a step-by-step guide with screenshots.
The client accepts the key as an argument — Vulners(api_key="...") — or reads it from the VULNERS_API_KEY environment variable, so a plain Vulners() works too. Keep your API key confidential to prevent unauthorized access.
60-second tour¶
Search runs a Lucene query and returns a page of typed Bulletin models — fields are attributes, not dict keys:
from vulners import Vulners
with Vulners(api_key="YOUR_API_KEY_HERE") as v:
# Full-text search: CVEs known to be exploited in the wild
page = v.search.query(
"type:cve AND enchantments.exploitation.wildExploited:true", limit=10
)
print(page.total, "documents match")
for bulletin in page.data:
print(bulletin.id, "-", bulletin.title, "-", bulletin.cvss and bulletin.cvss.score)
# Fetch a single document by id -> Bulletin | None
cve = v.search.get_bulletin("CVE-2021-44228")
if cve is not None:
print(cve.title, cve.published)
import asyncio
from vulners import AsyncVulners
async def main() -> None:
async with AsyncVulners(api_key="YOUR_API_KEY_HERE") as v:
# Full-text search: CVEs known to be exploited in the wild
page = await v.search.query(
"type:cve AND enchantments.exploitation.wildExploited:true", limit=10
)
print(page.total, "documents match")
for bulletin in page.data:
print(bulletin.id, "-", bulletin.title, "-", bulletin.cvss and bulletin.cvss.score)
# Fetch a single document by id -> Bulletin | None
cve = await v.search.get_bulletin("CVE-2021-44228")
if cve is not None:
print(cve.title, cve.published)
asyncio.run(main())
page.data holds the current page of results; iterating the page itself (for b in page) transparently walks further pages up to the 10,000-document search window, and v.search.iter_query(...) streams the whole window as a generator.
Validating API Key¶
Ensure that API key is active and valid with this quick curl request. Replace
curl -X POST https://vulners.com/api/v4/audit/software/ \
-H "Content-Type: application/json" \
-H "X-Api-Key: <YOUR-API-KEY>" \
-d '{
"software": [{"product": "django", "version": "1.9"}], "fields": []
}'
In Python you get the same signal for free: on an invalid key the client raises AuthenticationError — a subclass of VulnersError — with the key redacted from the error payload, so it never leaks into logs.
What's new in v4¶
Fully typed data model¶
Every search and document call returns pydantic models instead of raw dicts. The hierarchy mirrors the Vulners data model: a base Bulletin → 18 family models (cve, exploit, unix, microsoft, scanner, …) → ~238 per-collection models. The most specific model is chosen automatically from the document's type, isinstance checks hold at every level, unknown collections fall back to GenericBulletin, and fields that are not modelled yet are still preserved on the object.
from vulners import CveBulletin, Vulners
with Vulners() as v:
cve = v.search.get_bulletin("CVE-2021-44228", fields=["*"])
print(cve.type, cve.bulletin_family) # snake_case attributes
print(cve.cvss.score if cve.cvss else None) # nested typed objects (CVSS, EPSS, ...)
print(cve.epss[0].epss if cve.epss else None) # EPSS probability
print(isinstance(cve, CveBulletin)) # True
raw = cve.model_dump() # plain dict when you need JSON
Field-by-field reference for every family and collection lives in the SDK repository: data models.
Sync and async, mirrored¶
Vulners and AsyncVulners expose identical resource namespaces with identical signatures — every method has an awaitable twin, and auto-paginating iterators get an a-prefix (iter_query → aiter_query, iter_collection → aiter_collection). Any example in this documentation converts to async by adding await and async with:
from vulners import Vulners
with Vulners() as v:
results = v.audit.software(["cpe:2.3:a:apache:log4j:2.14.1"])
import asyncio
from vulners import AsyncVulners
async def main() -> None:
async with AsyncVulners() as v:
results = await v.audit.software(["cpe:2.3:a:apache:log4j:2.14.1"])
asyncio.run(main())
Documentation built in¶
The package repository carries its entire documentation next to the code — readable offline, greppable, and indexable by your tools:
documentation/— quickstart tutorial, task-focused how-to guides, full API reference, and explanations of the network, error and pagination models.api.md— a generated one-file index of every method: signature, return type and HTTP route.llms.txt— an llms.txt-standard index of every documentation page.
100% agent-friendly¶
v4 is designed to be driven by AI coding agents as comfortably as by humans. Point Claude Code, Cursor or Codex at the repository (or the installed package) and it discovers everything it needs without guessing:
AGENTS.md— a task-oriented guide with install, authentication, the full namespace → method map, and agent-specific notes on pagination, errors and billing..agents/skills/vulners-api/— a ready-made skill folder that agents pick up in repository checkouts.- Fully typed models with docstrings — agents and IDEs read exact field names and signatures instead of reverse-engineering JSON.
- Safe by default — the API key is held as a secret and redacted from error messages, so it does not leak into agent transcripts or logs.
Built-in MCP server¶
The mcp extra ships a minimal, self-hosted Model Context Protocol server, so any MCP client — Claude Code, Claude Desktop, Cursor, VS Code — can call Vulners as tools:
pip install -U "vulners[mcp]"
export VULNERS_API_KEY=YOUR_API_KEY_HERE
vulners-mcp # serves MCP over stdio; python -m vulners.mcp also works
| Tool | Purpose |
|---|---|
search_bulletins(query, limit, offset) |
Lucene search across the whole database; paginated |
get_bulletin(id, fields, full) |
fetch one bulletin — compact summary by default |
search_exploits(query, limit, offset) |
exploits and PoCs for a CVE or product |
cve_lookup(cve) |
CVE risk attributes: CVSS, CWE, CPE, EPSS |
audit_software(software, match) |
vulnerabilities for CPE / software strings |
audit_linux(os_name, os_version, packages) |
vulnerabilities for a Linux package list |
smart_audit(software) |
free-form names → CPE/PURL + vulnerabilities (billed per string) |
Responses are deliberately compact — long strings are clipped and long lists are capped — so tool output stays inside an agent's context budget. The key is always passed via the environment, never on the command line:
claude mcp add vulners -e VULNERS_API_KEY=YOUR_API_KEY_HERE -- vulners-mcp
{
"mcpServers": {
"vulners": {
"command": "vulners-mcp",
"env": { "VULNERS_API_KEY": "YOUR_API_KEY_HERE" }
}
}
}
Claude Desktop: Settings → Developer → Edit Config (claude_desktop_config.json). Cursor: .cursor/mcp.json (project) or ~/.cursor/mcp.json (global).
Prefer zero setup?
The official fully managed MCP endpoint is hosted at mcp.vulners.com — nothing to install and always on. See Vulners MCP for connection details, available tools and usage patterns.
Upgrading from v3¶
v4 is 100% backward compatible: the legacy VulnersApi / VScannerApi classes keep working unchanged, so upgrading is just pip install -U vulners. New code should use the Vulners / AsyncVulners clients — the migration guide maps every v3 method to its v4 equivalent.
Next steps¶
- Quickstart — the three basic calls: search, audit, and archive.
- API Reference — every endpoint with curl and Python examples.
- Data model — the document schema behind the typed models.
- Vulners MCP — the hosted MCP endpoint for AI assistants.