Library / SDK
vulnersCom/api avatar
vulnersCom/api

vulnersCom/api: the official Python SDK 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.

373 stars65 forksPythonMIT

At a glance

What is it?
The MIT-licensed Python client for Vulners wraps a queryable vulnerability-intelligence graph behind typed sync and async clients, and adds an MCP server so AI agents can read the same graph. It is a good fit if you already pay for Vulners API access and want typed Python objects instead of raw JSON.
Who is it for?
Adopt vulnersCom/api if you already hold a Vulners API key and you want typed bulletin models, async transport and an MCP endpoint without writing your own HTTP layer against the v3 API. Do not adopt it if the graph itself is the thing you are evaluating: the SDK is a client, it carries no data, and every call needs a key and network access.
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 1 day 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 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

What problem the Vulners SDK removes, and who still has to solve it themselves

The problem is not vulnerability data. It is the plumbing between a vulnerability graph and the Python code that has to act on it. The README describes Vulners as aggregating 230+ sources (CVEs, exploits, vendor advisories, CISA KEV, EPSS and AI risk scores) into one queryable graph, and states that it is API-first with no agents or network access required: you send asset data in standard formats and get back risk-prioritized intelligence. That is a service, not a library. The SDK is the client half. It gives you a Vulners class, an AsyncVulners class, typed bulletin models, and namespaces such as v.search, v.audit and v.archive, so a CVE lookup returns an object with .cvss.score and .cvss.vector rather than a dictionary you have to defend against.

The audience is narrow and specific. You need a Vulners API key, which the README points at vulners.com and the authentication quickstart. You need Python 3.10 or newer. You need to be comfortable sending asset data (product and version pairs, CPE 2.3 strings, installed package lists, SBOMs) to a third-party API. Teams that already run a scanner and only want a local CVE feed will find nothing here for them: the SDK holds no database and works only against the live service. The README also notes that the latest pre-release lives on the v4.0 branch and is not yet on PyPI, which tells you the project ships ahead of its published artifact.

Typed models, Lucene queries and the page object that hides pagination

The central mechanism is a thin, typed layer over HTTP. The quickstart opens a client with Vulners(api_key=...) as a context manager and calls v.search.get_bulletin("CVE-2021-44228"), which returns a typed model or None when the bulletin is not found. The README's example then reads log4shell.cvss.score and log4shell.cvss.vector, so the CVSS block is itself a model with a score and a vector, not a nested dictionary.

Search uses Lucene syntax. The README's example query is type:cve AND cvss.score:[9 TO 10] with limit=10, and it explains that limit is the page size and that iterating the page auto-paginates the whole result window. That detail matters more than it looks: page.data is the first page, and the page object is the cursor. If you treat the page as a list you get one page; if you iterate it you get everything the query matches. The distinction is the difference between a fast call and a long one, and the README does not state a default cap on the result window.

Errors are typed too. The README imports APIError and RateLimitError and catches RateLimitError separately, which implies the client distinguishes throttling from other API failures. The README text is truncated mid-sentence in that example, so the full set of error classes is not visible in the supplied material.

Audit, metadata and archive: the three namespaces that do the real work

Beyond search, the SDK exposes three namespaces the README demonstrates with runnable examples under samples/, in a v4 set and a matching v3 (legacy) set side by side.

v.audit.software takes a mixed list. The README passes a dict {"product": "openssl", "version": "1.0.1"} and a raw CPE 2.3 string "cpe:2.3:a:apache:log4j:2.14.1" in the same call, and each item comes back with matched_criteria and a vulnerabilities list. v.audit.linux_audit takes os_name, os_version and a packages list in the form "openssl 1.1.1d-0+deb10u3 amd64", returning a report whose issues carry a package field. That package string format is a constraint, not a convenience: you are expected to hand over dpkg-style version strings, not parsed tuples.

v.audit.metadata is the one to read carefully. It takes a registry, a name and a version, and returns a model whose license field is always a list, never a bare string. The README is explicit that an empty license with meta.found set to True means the package is known but has no recorded license, while meta.found False means the registry does not know the package name at all. Those are three distinct outcomes and conflating them will produce wrong compliance output. For Maven, the name is the groupId:artifactId coordinate and the README says the registry name is lower-cased for you, so the colon-versus-slash and casing details are handled inside the client.

v.archive.iter_collection("cve") is a generator. The README describes each record as yielded as it arrives, a lazily-streamed JSON array, which is the difference between a mirror job that runs in constant memory and one that buffers gigabytes.

Installation, key handling and the async client

Installation is one command: pip install -U vulners. The README states that a plain install pulls httpx, pydantic and orjson, plus HTTP/2 via h2, brotli and zstandard for compression, isal for accelerated gzip, and ijson with stream-unzip for streaming archive decode, all with prebuilt wheels and no build step. That is a deliberate dependency choice: the archive streaming and compression performance come from the dependency set rather than from hand-written parsing.

For unreleased code the README gives two routes: git clone -b v4.0 https://github.com/vulnersCom/api.git followed by pip install -e ., or pip install "git+https://github.com/vulnersCom/api.git@v4.0" to skip the clone. Note that the published releases listed for this repository are v4.3.0, v4.2.0 and v4.1.0, while the README still labels the v4.0 branch as not yet on PyPI. Treat the branch instructions as historical until you check what PyPI currently serves.

Key handling is environment-first. The README shows Vulners(api_key=os.environ["VULNERS_API_KEY"]) as the recommended pattern and notes the client can also pick the key up from the VULNERS_API_KEY environment variable. The async path is the same surface: AsyncVulners used with async with, awaited calls such as await v.search.query("Fortinet AND RCE", limit=20), driven by asyncio.run(main()). The README does not describe connection pooling or concurrency limits for the async client, so throughput behaviour is something you would have to measure yourself.

The MCP server, and why it is the most opinionated part of the package

The README lists a built-in MCP server under an "AI agents" heading and describes the SDK as AI-ready, with typed bulletin models and documented response shapes to ground agents on live vulnerability facts. The repository topics include mcp. Shipping an MCP endpoint inside a vendor SDK is a bet: it assumes your agent framework speaks MCP and that you want the agent reading the same graph your automation reads.

The supplied material does not show the command that starts the MCP server, the transport it uses, or which tools it exposes. If agent integration is your reason for looking at this package, that gap is the first thing to close: read the SDK documentation site linked from the README rather than relying on the README alone. The typed models are the real enabler here, because a model with a declared shape is what lets an agent produce a structured answer instead of prose about a CVE.

A client with no offline mode, and the alternative that inverts the dependency

The clearest limitation is structural. Every capability in this SDK is a network call to the Vulners API, keyed by an account. There is no local corpus, no cache layer described in the README, and no offline path. If your environment forbids sending an asset inventory to a third party, or if your build pipeline has no egress, the SDK cannot help you regardless of how good the typed models are. Rate limiting is real enough that the README ships a dedicated RateLimitError class, and the free tier referenced in the quickstart will not carry a full-fleet audit. The archive namespace is the one place where a rate limit turns into a long-running job rather than a failed call.

The honest alternative is the data itself rather than another client. The cve-bin-tool project takes the opposite approach: it downloads public CVE data and scanner signatures into a local database and matches binaries and package lists against that local copy, so it works without an API key and without network access at scan time. The trade is enrichment for autonomy. cve-bin-tool will not tell you about CISA KEV status or EPSS through a hosted graph, and it will not stream a vendor-curated bulletin set; vulnersCom/api will not run in an air-gapped build. If your requirement is "scan this container in CI with no secrets and no egress", the SDK is the wrong tool and no amount of typing fixes that.

Maintenance cost, versioning and the MIT licence

The repository is active, not archived, with a last push in September 2026 and three releases inside a month (v4.1.0, v4.2.0, v4.3.0). That cadence is a maintenance signal in both directions: you get fixes quickly, and you should expect the surface to move. The README's own v3 (legacy) sample set alongside the v4 samples is the migration story. The description claims 100% v3 compatibility, so the intended path is that existing v3 calls keep working while you move to typed models. Verify that claim against your own call sites rather than trusting the phrase.

The dependency set is the ongoing cost. httpx, pydantic, orjson, h2, brotli, zstandard, isal, ijson and stream-unzip all have to resolve in your environment, and pydantic in particular constrains which Python versions you can pin. Python 3.10 or newer is a hard floor, so a 3.9 runtime is a non-starter.

The licence is MIT, which permits commercial and closed-source use and requires preserving the copyright notice and permission text. That is a statement about the SDK code only. The vulnerability data behind the API is a separate commercial relationship governed by your Vulners account terms, and nothing in the MIT grant covers it. Do not read the permissive licence as permission to redistribute the graph.

Editorial conclusion

Adopt vulnersCom/api if you already hold a Vulners API key and you want typed bulletin models, async transport and an MCP endpoint without writing your own HTTP layer against the v3 API. Do not adopt it if the graph itself is the thing you are evaluating: the SDK is a client, it carries no data, and every call needs a key and network access. Before you commit, verify that the Python 3.10 floor matches your runtime, that the free key's query and archive limits cover your workload, and that the archived v3 sample set still matches whatever internal code you are migrating from.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. vulnersCom/api on GitHub
Community notes

Community notes