Quickstart¶
This tutorial walks you from an empty file to your first search and first audit, in
both the synchronous and asynchronous styles. It assumes you have installed the SDK
(pip install vulners) and have a Vulners API key.
1. Authenticate¶
The client takes the key as an argument, or reads it from the VULNERS_API_KEY
environment variable:
Use it as a context manager so the underlying connection pool is released on exit:
2. Your first search¶
search.query runs a Lucene query and returns a
SearchPage of typed Bulletin objects. page.data holds this page's results;
iterating the page itself (for b in page) transparently walks further pages, up to the
10,000-document window:
Each row is a Bulletin model — access fields as attributes (not dict keys):
b = page[0]
print(b.id, b.type, b.published)
if b.cvss:
print(b.cvss.score, getattr(b.cvss, "severity", None))
Fetch a single document by id:
3. Your first audit¶
Audit a list of software for known vulnerabilities. Entries can be CPE 2.3 strings or
simple {"product": ..., "version": ...} dicts:
To audit a Linux host by its installed packages, see Audit a host.
4. The same, asynchronously¶
Every resource method exists on AsyncVulners with an identical signature; you just
await it. (Iterating a page with async for auto-paginates, exactly like the sync
for.) A complete program looks like this:
import asyncio
from vulners import AsyncVulners
async def main() -> None:
async with AsyncVulners() as v:
page = await v.search.query("bulletinFamily:exploit AND wordpress", limit=10)
for exploit in page.data:
print(exploit.id, exploit.href)
results = await v.audit.software(["cpe:2.3:a:apache:log4j:2.14.1"])
print(len(results), "products audited")
asyncio.run(main())
5. Handle errors¶
Failed requests raise a subclass of VulnersError. Catch the whole family, or a specific
one such as RateLimitError:
The full hierarchy is described in Error model.
Next steps¶
- How-to guides — practical, task-focused recipes.
- API reference — every method and model.