Python client and CLI for the EPSS (Exploit Prediction Scoring System) API
Project description
epss-client
A Python client and CLI for the EPSS (Exploit Prediction Scoring System) API.
Fetch exploit prediction scores for CVEs, search with filters, track score changes over time, and download bulk data with this lightweight, zero-overhead client.
Installation
pip install epss-client
Quick Start (Python API)
from epss import EPSSClient
client = EPSSClient()
# Get EPSS score for a single CVE
resp = client.get("CVE-2022-27225")
print(resp.data[0]) # EPSSScore object
# Batch lookup
resp = client.get(["CVE-2022-27225", "CVE-2022-27223"])
# Search with filters
resp = client.search(epss_gt=0.9, limit=50)
# Top 10 CVEs by EPSS score
resp = client.top(10, by="epss")
# Stream all matching records
for page in client.iter_pages(epss_gt=0.5):
for score in page.data:
print(score.cve, score.epss, score.risk_label())
# Historical data
resp = client.get("CVE-2022-27225", date="2022-03-05")
# Time series (last 30 days)
resp = client.get("CVE-2022-25204", scope="time-series")
for ts in resp.data[0].time_series:
print(ts.date, ts.epss)
# Compare scores between two dates
comparison = client.compare("CVE-2022-27225", date1="2022-03-01", date2="2022-04-01")
# Download bulk CSV data
records = client.get_bulk_csv(date="2022-03-05", min_epss=0.5)
Quick Start (CLI)
# Get EPSS score
epss get CVE-2022-27225
# Batch lookup
epss get CVE-2022-27225 CVE-2022-27223
# Search (default: top 100 by EPSS descending)
epss search --epss-gt 0.9
# Top 20 CVEs
epss top 20
# Top 10 by percentile
epss top 10 --by percentile
# Time series (last 30 days)
epss time-series CVE-2022-25204
# Compare between two dates
epss compare CVE-2022-27225 --date1 2022-03-01 --date2 2022-04-01
# Download bulk CSV
epss bulk --date 2022-03-05
# Filter bulk data by EPSS score
epss bulk --min-epss 0.5
# JSON output
epss search --epss-gt 0.9 -o json
# CSV output
epss search --percentile-gt 0.95 -o csv
Client Reference
EPSSClient
from epss import EPSSClient
client = EPSSClient(timeout=30)
Parameters:
timeout(int): HTTP timeout in seconds. Default: 30.session(requests.Session, optional): Pre-configured requests session for custom proxies, retry logic, or TLS verification.user_agent(str, optional): Custom User-Agent header. Default:epss-client/{version} (python-requests).
get()
Fetch EPSS scores for one or more CVEs.
# Single CVE
resp = client.get("CVE-2022-27225")
# Batch lookup
resp = client.get(["CVE-2022-27225", "CVE-2022-27223"])
# Historical data (specific date)
resp = client.get("CVE-2022-27225", date="2022-03-05")
# Time series (last 30 days)
resp = client.get("CVE-2022-25204", scope="time-series")
Returns: EPSSResponse with .data list of EPSSScore objects.
search()
Query the database with optional filters. All parameters are combinable.
# Top CVEs by EPSS (default)
resp = client.search(epss_gt=0.9, limit=100)
# CVEs above a percentile threshold
resp = client.search(percentile_gt=0.95)
# By date
resp = client.search(date="2022-03-05", epss_gt=0.7)
# With custom ordering and pagination
resp = client.search(
epss_gt=0.5,
order="!epss", # descending
limit=50,
offset=100,
)
Parameters:
date(str or datetime.date): Restrict to a specific date. Format:YYYY-MM-DD.epss_gt(float): Only return CVEs with EPSS score greater than this value.epss_lt(float): Only return CVEs with EPSS score less than this value.percentile_gt(float): Only return CVEs with percentile greater than this.percentile_lt(float): Only return CVEs with percentile less than this.order(str): Sort order. Options:epss,!epss,percentile,!percentile. Default:!epss.limit(int): Results per page. Default: 100.offset(int): Pagination offset. Default: 0.
Returns: EPSSResponse.
top()
Convenience wrapper around search() to get the top N CVEs.
resp = client.top(100, by="epss", date="2022-03-05")
Parameters:
n(int): Number of results. Default: 100.by(str): Sort byepssorpercentile. Default:epss.date(str or datetime.date, optional): Restrict to a specific date.
Returns: EPSSResponse.
iter_pages()
Memory-safe pagination generator. Yields EPSSResponse objects until all results are exhausted.
for page in client.iter_pages(epss_gt=0.5, page_size=1000):
for score in page.data:
process(score)
Useful for traversing large result sets without loading everything into memory.
get_all()
Fetch all matching records across all pages into a single list.
# All CVEs with EPSS > 0.9
scores = client.get_all(epss_gt=0.9)
# Cap results to avoid memory issues
scores = client.get_all(epss_gt=0.5, max_records=10000)
Parameters:
max_records(int, optional): Stop after this many records. Useful for large queries.
Returns: list[EPSSScore].
compare()
Compare EPSS scores for one or more CVEs between two dates.
comparison = client.compare(
["CVE-2022-27225", "CVE-2022-27223"],
date1="2022-03-01",
date2="2022-04-01",
)
for cve_id, (score1, score2) in comparison.items():
delta = score2.epss - score1.epss
print(f"{cve_id}: {delta:+.4f}")
Returns: dict[str, tuple[EPSSScore, EPSSScore]] where values are (score_at_date1, score_at_date2).
get_bulk_csv()
Download and parse the bulk EPSS CSV for a specific date from empiricalsecurity.com.
# Today's data
records = client.get_bulk_csv()
# Specific date
records = client.get_bulk_csv(date="2022-03-05")
# Filter by EPSS score
records = client.get_bulk_csv(min_epss=0.5)
Returns: list[CSVRecord].
Data Models
EPSSScore
Represents a single CVE EPSS score.
score = resp.data[0]
print(score.cve) # "CVE-2022-27225"
print(score.epss) # 0.001870000
print(score.percentile) # 0.401060000
print(score.date) # datetime.date(2026, 5, 4)
print(score.risk_label()) # "INFORMATIONAL"
Risk labels:
CRITICAL: epss >= 0.7HIGH: epss >= 0.4MEDIUM: epss >= 0.1LOW: epss >= 0.01INFORMATIONAL: epss < 0.01
EPSSResponse
A paginated API response.
resp = client.search()
print(resp.status) # "OK"
print(resp.total) # 100000
print(resp.offset) # 0
print(resp.limit) # 100
print(resp.has_more) # True
print(resp.next_offset) # 100
print(resp.data) # list[EPSSScore]
EPSSTimePoint
A single entry in a time-series response.
resp = client.get("CVE-2022-25204", scope="time-series")
for ts in resp.data[0].time_series:
print(ts.date, ts.epss, ts.percentile)
CSVRecord
A single row from bulk CSV data.
records = client.get_bulk_csv()
for record in records:
print(record.cve, record.epss, record.percentile, record.date)
Error Handling
All exceptions inherit from EPSSError for convenient catching.
from epss import (
EPSSError,
EPSSAPIError,
EPSSValidationError,
EPSSNetworkError,
EPSSCSVError,
)
try:
resp = client.get("CVE-2022-27225")
except EPSSAPIError as e:
print(f"API error: {e.status_code}")
if e.response_body:
print(e.response_body)
except EPSSNetworkError as e:
print(f"Network error: {e}")
except EPSSValidationError as e:
print(f"Invalid request: {e}")
except EPSSCSVError as e:
print(f"CSV download failed: {e}")
Pagination Guide
Small result sets
Use search() directly:
resp = client.search(epss_gt=0.9, limit=100)
all_records = resp.data
Large result sets
Use iter_pages() for memory efficiency:
for page in client.iter_pages(epss_gt=0.5, page_size=1000):
for score in page.data:
# process one at a time
process(score)
Or get_all() with a safety cap:
scores = client.get_all(epss_gt=0.5, max_records=10000)
Output Formats (CLI)
Table (default)
CVE | EPSS | Percentile | Risk | Date
...
epss search --epss-gt 0.9
JSON
epss search --epss-gt 0.9 -o json
CSV
epss search --epss-gt 0.9 -o csv > results.csv
Development
Install with dev dependencies
pip install -e ".[dev]"
Run tests
pytest -v
Type checking
mypy src/epss
Linting
ruff check src/epss
black src/epss
Build package
python -m build
Publish to PyPI
twine upload dist/*
License
MIT License. See LICENSE for details.
Links
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file epss_py-0.1.0.tar.gz.
File metadata
- Download URL: epss_py-0.1.0.tar.gz
- Upload date:
- Size: 18.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7d780450eebdef878bfc7b1f6cca318255325b044415f67505d2542c0b2866e0
|
|
| MD5 |
ec1b3bbfdc535f39cecc302bb043f219
|
|
| BLAKE2b-256 |
c75e365ce94e74b29fd040c0ad7f98f9969445bd7ed0e1b4242fcdaef507f56d
|
File details
Details for the file epss_py-0.1.0-py3-none-any.whl.
File metadata
- Download URL: epss_py-0.1.0-py3-none-any.whl
- Upload date:
- Size: 14.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
856e68e21e24fa46b67dec3df5f3b8f679867e2c7a237e08e27b36475ca06e6a
|
|
| MD5 |
0eb366a6621a303f338ef45821dacaed
|
|
| BLAKE2b-256 |
57cd7bdd0a0206c22573036982c67f01c64c67b0184a723620114a4160e29bf2
|