Python SDK for the VulnRadar security scanning API
Project description
VulnRadar Python SDK
A production-ready Python SDK for the VulnRadar security scanning API. Clean, fully typed, and designed for developer-friendly integration.
Overview
VulnRadar scans web targets for security vulnerabilities, exposing findings categorized by severity (critical, high, medium, low, info). This SDK wraps the REST API with:
- Full type hints and dataclass-based response models
- Automatic authentication header injection
- Structured error handling with custom exceptions
- Rate limit awareness via response header parsing
- Configurable timeout and retry logic
- Support for single scans, deep crawl scans, URL discovery, and history retrieval
Installation
pip install vulnradar
Requires Python 3.10+.
Quickstart
from vulnradar import VulnRadar
client = VulnRadar(api_key="your-api-key")
result = client.scan("https://example.com")
print(f"Total findings: {result.summary.total}")
print(f"Critical: {result.summary.critical}")
for finding in result.findings:
print(f"[{finding.severity.value.upper()}] {finding.title}")
Authentication
All requests are authenticated using a Bearer token in the Authorization header. Pass your API key when constructing the client:
client = VulnRadar(api_key="your-api-key")
Configuration
client = VulnRadar(
api_key="your-api-key",
timeout=60, # HTTP timeout in seconds (default: 30)
retries=5, # Retry attempts on server errors (default: 3)
base_url="https://vulnradar.dev/api/v2", # Custom base URL (optional)
)
Running Scans
Single URL Scan
result = client.scan("https://example.com")
# Optional: run only selected scanners.
result = client.scan("https://example.com", scanners=["headers", "ssl"])
print(result.url)
print(result.scanned_at)
print(result.duration)
print(result.scan_history_id)
for finding in result.findings:
print(finding.type, finding.severity, finding.title)
print(finding.description)
print(finding.remediation)
Supported target protocols: http://, https://, ws://, wss://, ftp://, ftps://.
ScanResult fields:
| Field | Type | Description |
|---|---|---|
url |
str |
Scanned URL |
scanned_at |
datetime |
Timestamp of the scan |
duration |
float |
Scan duration in seconds |
findings |
list[Finding] |
List of security findings |
summary |
Summary |
Aggregated finding counts |
response_headers |
dict[str, str] |
HTTP headers from the target |
scan_history_id |
int | None |
ID in scan history |
notes |
str | None |
Optional scan notes |
Crawl Scans
Perform a deep crawl across multiple pages of a target:
result = client.scan_crawl("https://example.com")
print(f"Pages scanned: {result.crawl.total_pages}")
print(f"Total findings: {result.crawl.total_findings}")
for page in result.pages:
print(f"{page.url} — {page.summary.total} findings")
You can also provide a list of specific URLs to include:
result = client.scan_crawl(
"https://example.com",
urls=["https://example.com/login", "https://example.com/admin"],
)
Discover URLs
Discover all crawlable URLs for a target before running a crawl scan:
discovery = client.discover_urls("https://example.com")
print(f"Found {discovery.total} URLs")
for url in discovery.urls:
print(url)
Scan History
List Recent Scans
history = client.history.list()
for scan in history.scans:
print(scan.id, scan.url, scan.scanned_at)
print(f" Findings: {scan.findings_count}")
Get a Specific Scan
result = client.history.get(123)
print(result.url)
for finding in result.findings:
print(finding.title, finding.severity)
Delete a Scan
deleted = client.history.delete(123)
print(deleted.success)
print(deleted.message)
Finding Types
Retrieve the full catalog of supported finding types:
catalog = client.metadata.finding_types()
print(f"Version: {catalog.version}")
print(f"Total types: {catalog.count}")
for ft in catalog.types:
print(f"[{ft.severity.value}] {ft.title} ({ft.category})")
Version Check
info = client.version()
print(info.current)
print(info.latest)
print(info.engine)
print(info.status)
Error Handling
All exceptions inherit from VulnRadarError:
from vulnradar import (
VulnRadar,
VulnRadarError,
AuthenticationError,
BadRequestError,
ForbiddenError,
NotFoundError,
RateLimitError,
ServerError,
InvalidURLError,
UnprocessableEntityError,
)
client = VulnRadar(api_key="your-api-key")
try:
result = client.scan("https://example.com")
except InvalidURLError as e:
print(f"Bad URL: {e.url}")
except AuthenticationError:
print("Invalid or expired API key.")
except RateLimitError as e:
print(f"Rate limited. Resets at: {e.resets_at}")
print(f"Limit: {e.limit}, Remaining: {e.remaining}")
except NotFoundError:
print("Resource not found.")
except ServerError as e:
print(f"Server error {e.status_code}: {e.message}")
except VulnRadarError as e:
print(f"SDK error: {e.message}")
Exception Reference
| Exception | HTTP Status | Description |
|---|---|---|
AuthenticationError |
401 | Invalid or missing API key |
BadRequestError |
400 | Malformed request or invalid params |
ForbiddenError |
403 | Authenticated but not permitted |
NotFoundError |
404 | Requested resource does not exist |
UnprocessableEntityError |
422 | Target is unreachable/not processable |
RateLimitError |
429 | Rate limit exceeded |
ServerError |
5xx | API-side internal error |
InvalidURLError |
— | URL failed client-side validation |
Rate Limits
The SDK automatically parses rate limit headers from every response. When you hit a rate limit, the RateLimitError exception exposes:
except RateLimitError as e:
print(e.limit) # Total allowed requests
print(e.used) # Requests used
print(e.remaining) # Requests remaining
print(e.resets_at) # datetime when limit resets
Headers parsed:
X-RateLimit-LimitX-RateLimit-RemainingX-RateLimit-ResetRetry-After
Default API key quota: 50 requests per 24 hours.
Severity Enum
from vulnradar import Severity
Severity.CRITICAL # "critical"
Severity.HIGH # "high"
Severity.MEDIUM # "medium"
Severity.LOW # "low"
Severity.INFO # "info"
Filter findings by severity:
critical = [f for f in result.findings if f.severity == Severity.CRITICAL]
Best Practices
Handle rate limits gracefully:
import time
from vulnradar import VulnRadar, RateLimitError
client = VulnRadar(api_key="your-api-key")
def safe_scan(url: str):
try:
return client.scan(url)
except RateLimitError as e:
if e.resets_at:
wait = (e.resets_at - datetime.now(timezone.utc)).total_seconds()
time.sleep(max(wait, 1))
return client.scan(url)
Use history to avoid redundant scans:
history = client.history.list()
already_scanned = {s.url for s in history.scans}
if target_url not in already_scanned:
result = client.scan(target_url)
Pre-discover URLs before crawling:
discovery = client.discover_urls("https://example.com")
if discovery.total > 0:
result = client.scan_crawl("https://example.com", urls=discovery.urls)
Contributing
- Fork the repository
- Create a feature branch:
git checkout -b feature/my-feature - Make your changes with full type hints
- Run tests:
pytest - Submit a pull request
All contributions must pass lint and type checking.
License
MIT — see LICENSE for details.
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 vulnradar-2.0.0b1.tar.gz.
File metadata
- Download URL: vulnradar-2.0.0b1.tar.gz
- Upload date:
- Size: 18.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.21 {"installer":{"name":"uv","version":"0.9.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Arch Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c4bcd9e64c0a1059fed1addfc514526392db04ab0bb49842ccfa48fbf0c59485
|
|
| MD5 |
eee1f17dda408429d06ebf4dda5718e6
|
|
| BLAKE2b-256 |
fbf7c855fe5e484efb2ee46a8aeeffa3f54ff34422125a7f1ae1caa1cb2c937a
|
File details
Details for the file vulnradar-2.0.0b1-py3-none-any.whl.
File metadata
- Download URL: vulnradar-2.0.0b1-py3-none-any.whl
- Upload date:
- Size: 21.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.21 {"installer":{"name":"uv","version":"0.9.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Arch Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bf864bf1081cfb79ff69c666514f9bcebd5d3e754f9ed9d1d286a2ff3880bc84
|
|
| MD5 |
416e3dbc1dd032bbce72babd6e20095c
|
|
| BLAKE2b-256 |
df5446d62762bee90b0bbcffac86093948aaeeeedef7fb2d73e23a316a4fa18f
|