Vulners Python SDK: the official client for the Vulners vulnerability graph
Official Python SDK for the Vulners vulnerability-intelligence API — search CVEs, exploits and advisories (CVSS/EPSS/KEV), audit software, Linux/Windows hosts and SBOMs, and stream the whole graph. Typed sync + async clients, 100% v3-compatible, with a built-in MCP server for AI agents.
At a glance
- What is it?
- The vulnersCom/api package wraps the Vulners vulnerability-intelligence API in typed sync and async Python clients, with audit helpers for software, hosts and SBOMs and a built-in MCP server. Here is what it does, how to install it, and where it stops being the right tool.
- Who is it for?
- Adopt the Vulners Python SDK if you already hold a Vulners API key and want typed, async-capable access to the same graph from Python, especially for software or SBOM audit work where the v.audit.software and v.audit.metadata helpers save you from hand-rolling CPE strings and registry lookups. Do not adopt it if you need an offline vulnerability database, if you cannot send asset data to a third-party API, or if you are not on Python 3.10 or newer.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 16 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 27, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What the Vulners Python SDK actually solves
Vulnerability data arrives in fragments. A CVE record lives in one feed, the CVSS vector in another, exploitation status somewhere else, and the proof-of-concept exploit in a fourth place. The Vulners Python SDK exists so that a Python program can ask one API for all of it and get back typed objects instead of raw dictionaries.
The README describes the underlying service as aggregating 230+ sources, including CVEs, exploits, vendor advisories, CISA KEV, EPSS and what it calls AI risk scores, into a single queryable graph. The SDK is the Python entry point to that graph. It is aimed at engineers building vulnerability management tooling: people who want to check whether a specific library version is affected, prioritize findings beyond a raw CVSS number, or pull exploit code for a given CVE.
Three audiences are visible in the repository layout. The first is the developer writing a one-off lookup, who uses v.search.get_bulletin. The second is the pipeline author who needs to stream the full archive into their own storage, which is what v.archive.iter_collection covers. The third is the AI tooling crowd: the README advertises a built-in MCP server under an mcp extra, and the repository carries an AGENTS.md and an llms.txt file, which suggests the project treats agent consumption as a first-class use case rather than an afterthought.
What it is not: it is not a scanner that runs on your machine, and it is not a local database. The README is explicit that it needs no agents or network access in the sense that you send asset data in standard formats and get intelligence back. Every query leaves your environment.
How the client is put together: typed models, sync and async, streaming archive
The package is built on httpx for transport, pydantic for the data models and orjson for parsing. The dependency list in pyproject.toml also pins h2 for HTTP/2, brotli and zstandard for response compression, isal for accelerated gzip, and ijson with stream-unzip for streaming archive decode. The README notes these ship as prebuilt wheels, so a plain install has no build step.
The data model layer is where the design shows. v.search.get_bulletin returns a typed bulletin object or None when the CVE is not found, and the README's example reaches into log4shell.cvss.score and log4shell.cvss.vector, so the CVSS block is a nested model rather than a loose dict. The README points at a dedicated data-models reference page for bulletins.
Both a synchronous Vulners class and an AsyncVulners class expose the same surface. The async example awaits v.search.query and iterates page.data, which means the pagination object is shared between the two flavours. Queries use Lucene syntax: the README shows type:cve AND cvss.score:[9 TO 10] and Fortinet AND RCE as valid query strings.
One detail worth reading twice. The quickstart comments that limit is the page size, and that iterating the page itself auto-paginates the whole result window. That is a meaningful distinction: reading page.data gives you one page, while iterating the page object walks everything. Getting this wrong in a large result set is the difference between ten records and a long-running loop.
Streaming is handled separately. v.archive.iter_collection yields each record as it arrives from a lazily-streamed JSON array, so the README's stated goal is to avoid buffering gigabytes. The Makefile backs this up with a branch-coverage gate that must stay at 100 percent for the new v4 core, with the legacy v3 layer omitted from measurement.
Installing the Vulners Python SDK and running a first CVE lookup
The README gives one install command. It requires Python 3.10 or newer, and the package name on PyPI is vulners.
pip install -U vulnersAfter that you need an API key. The README says to get a free key at vulners.com, or to export it as VULNERS_API_KEY. The SDK accepts the key either as a constructor argument or from the environment; the README's tip is to keep it out of source code.
import os
from vulners import Vulners
with Vulners(api_key=os.environ["VULNERS_API_KEY"]) as v:
log4shell = v.search.get_bulletin("CVE-2021-44228")
if log4shell is not None and log4shell.cvss is not None:
print(log4shell.id, log4shell.title)
print(log4shell.cvss.score, log4shell.cvss.vector)The Vulners object is a context manager, so the with block closes the underlying HTTP client. get_bulletin returns None when the CVE is not found, which is why the README guards on it before touching .cvss. If the key is wrong or the quota is exhausted, the README shows RateLimitError being caught explicitly alongside a general APIError, so both are importable from the top-level package.
For a query rather than a single lookup, the same client takes a Lucene string. The README's example reads the first page only, and notes that iterating the page object instead walks the whole result window.
page = v.search.query("type:cve AND cvss.score:[9 TO 10]", limit=10)
for bulletin in page.data:
print(bulletin.id, bulletin.title)If you prefer the async client, AsyncVulners mirrors the calls with await, and the README's sample wraps them in asyncio.run.
Auditing software, hosts and SBOMs with the audit helpers
The audit surface is the part that separates this SDK from a thin HTTP wrapper. v.audit.software accepts a mixed list: product and version dictionaries, and raw CPE 2.3 strings. The README's example passes both forms in one call and prints item["matched_criteria"] next to the count of vulnerabilities found for each entry.
for item in v.audit.software([{"product": "openssl", "version": "1.0.1"},
"cpe:2.3:a:apache:log4j:2.14.1"]):
print(item["matched_criteria"], "->", len(item["vulnerabilities"]), "vulnerabilities")There is a host-oriented variant too. v.audit.linux_audit takes an os_name, an os_version and a list of installed packages in the dpkg-style "name version arch" form, and returns a report whose issues list you iterate.
report = v.audit.linux_audit(os_name="debian", os_version="10",
packages=["openssl 1.1.1d-0+deb10u3 amd64"])
for issue in report["issues"]:
print(issue["package"])Package metadata lookup is the third helper, and it has the most carefully documented edge cases. v.audit.metadata takes a registry name, a package name and a version. The README states that license is always a list and never a bare string, that an empty license with meta.found set to True means the package is known but has no recorded license, and that meta.found is False when the registry does not know the name at all. For Maven, the name is the groupId:artifactId coordinate and the registry name is lower-cased for you.
meta = v.audit.metadata("pypi", "requests", "2.28.0")
print(meta.license) # ['ISC']
unknown = v.audit.metadata("pypi", "no-such-package", "9.9.9")
print(unknown.found) # False
guava = v.audit.metadata("maven", "com.google.guava:guava", "30.0-jre")
print(guava.license) # ['Apache-2.0']That distinction between found and licensed is a real design decision, and it is the kind of thing that bites a naive pipeline that treats an empty license as an error.
Where the Vulners Python SDK is the wrong tool
The first limitation is structural: everything depends on a remote API and a key. The README says the service is API-first and needs no agents, but that cuts both ways. If your environment cannot send asset inventories to a third party, or if you need vulnerability matching to keep working when the network is down, this SDK cannot help you. There is no local data file and no offline mode described anywhere in the README.
The second is the development status. The pyproject.toml classifier reads Development Status :: 4 - Beta, even though the package is at version 4.3.0 with three releases in August 2026. Treat the classifier as a signal about API stability expectations rather than a statement about the code's maturity. The README does not document a deprecation policy for the v4 surface, and it does not document rollback if an upgrade breaks your integration.
The third is the version split. The README points at a v4.0 branch for unreleased pre-release work and mentions a v3 legacy set of samples alongside the v4 set. If you have existing code written against the older client, the repository layout suggests a compatibility layer exists, but the README does not spell out which v3 calls map to which v4 equivalents. That is a migration you would have to read the source or the samples to plan.
Finally, the audit helpers are convenient but not transparent. The README shows the shape of the return values for software and metadata lookups, but it does not enumerate the full schema of a linux_audit report beyond the issues list and the package field. If your pipeline needs a specific field, verify it against a real response before you build on it.
How this differs from pulling NVD and CISA feeds yourself
The obvious alternative is to build the same capability from public feeds: NVD for CVE records and CVSS, the CISA KEV catalog for known exploited vulnerabilities, FIRST's EPSS for exploit prediction scores, and the Exploit-DB or Metasploit repositories for proof-of-concept code. All of those are free and, in most cases, downloadable as bulk files.
The difference is in what you own. Assembling those feeds means writing four or five ingest jobs, normalizing identifiers across them, and keeping a local store that you query. That store works offline and you control every field. The Vulners SDK trades that ownership for a single query interface: one Lucene string can combine a CVE type filter with a CVSS score range, and the audit helpers do the CPE matching for you. The README's claim that the service aggregates 230+ sources is exactly the work you would otherwise be doing yourself.
A second alternative worth naming is the vendor SDKs that ship with commercial vulnerability scanners. Those give you a local scanner plus an API, but they are tied to that vendor's detection logic. The Vulners SDK is the inverse: no scanning at all, just intelligence, which means it composes with whatever scanner or SBOM tool you already run.
If your requirement is a self-hosted database with no external calls, the feed-assembly route is the right one. If your requirement is fast access to correlation across many sources, the SDK is doing work you would otherwise duplicate.
Licence, maintenance and upgrade cost
The package is MIT licensed. The pyproject.toml declares license = "MIT" and points license-files at the LICENSE file. MIT is permissive: you can use the SDK in commercial and closed-source products, and the repository carries a SECURITY.md and a CONTRIBUTING.md for the project's own process. Note that the licence covers the client library only. The vulnerability data behind the API is a separate matter governed by your Vulners account terms, and the README does not describe those terms. That is a question for the service, not for the code.
On maintenance: the repository is not archived, and the last push was on 2026-09-07. Three releases landed in August 2026 (v4.1.0, v4.2.0 and v4.3.0), and the current version in pyproject.toml is 4.3.0.
Upgrade cost is where you should look before committing. The dependency pins are tight: httpx >=0.28,<1, pydantic >=2.13,<3, orjson >=3.11,<4. A project already on pydantic v1 cannot add this package without a major migration of its own models. The Makefile also reveals a real test burden if you fork or contribute: there are separate targets for the full suite, a backward-compatibility oracle, a 100 percent branch-coverage gate on the v4 core, and a separate coverage gate for the MCP server because it lives behind the mcp extra and cannot share the default environment. Live tests against the real API are opt-in and need VULNERS_API_KEY or a tests/live.local.toml file; they are skipped otherwise.
Editorial conclusion
Adopt the Vulners Python SDK if you already hold a Vulners API key and want typed, async-capable access to the same graph from Python, especially for software or SBOM audit work where the v.audit.software and v.audit.metadata helpers save you from hand-rolling CPE strings and registry lookups. Do not adopt it if you need an offline vulnerability database, if you cannot send asset data to a third-party API, or if you are not on Python 3.10 or newer. Before wiring it into anything, verify three things: that your key works against a live search call, that the audit helpers return the fields your pipeline expects (the README does not document the full response schema for every method), and that the legacy v3 surface you depend on is still present in the version you pin.
Frequently asked questions
What can someone do with my Vulners API key?
The README does not describe what a leaked key enables, so treat it as a credential for your account's query quota and keep it out of source control as the README advises. The SDK raises a RateLimitError when the quota is exhausted, which is the failure mode the README documents.
What is an API vulnerability?
The README does not define the term; it is a client for querying the Vulners vulnerability-intelligence API, and the data it returns is about CVEs, exploits and advisories rather than about API design flaws. The SDK's own scope is searching and auditing software, hosts and SBOMs.
Is the Vulners API trustworthy?
The README describes the service as aggregating 230+ sources including CVEs, exploits, vendor advisories, CISA KEV and EPSS, and points at a data-models reference for the response shapes. It does not make a trust or accuracy claim, so assess the underlying sources against your own requirements.
Is it safe to give your API key?
The README's guidance is to keep the key out of source code and read it from the environment as VULNERS_API_KEY, and it says to get a key at vulners.com. It does not describe key scoping or rotation, so those details are not answerable from the SDK documentation.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/vulnerscom-api)