Skip to main content

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-Limit
  • X-RateLimit-Remaining
  • X-RateLimit-Reset
  • Retry-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

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/my-feature
  3. Make your changes with full type hints
  4. Run tests: pytest
  5. Submit a pull request

All contributions must pass lint and type checking.


License

MIT — see LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

vulnradar-2.0.0b2.tar.gz (18.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

vulnradar-2.0.0b2-py3-none-any.whl (21.6 kB view details)

Uploaded Python 3

File details

Details for the file vulnradar-2.0.0b2.tar.gz.

File metadata

  • Download URL: vulnradar-2.0.0b2.tar.gz
  • Upload date:
  • Size: 18.5 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

Hashes for vulnradar-2.0.0b2.tar.gz
Algorithm Hash digest
SHA256 ffab07875be1e54551e4bb8fbf280e4fd7d2b6394e991fa179413ea7c4092b2f
MD5 3c1365b905075359fe7be7d11985d53c
BLAKE2b-256 cb4f6230c8ab2cb59ca9e1b5c49267f78ac16ad278ae88017333ffdb24a61d7b

See more details on using hashes here.

File details

Details for the file vulnradar-2.0.0b2-py3-none-any.whl.

File metadata

  • Download URL: vulnradar-2.0.0b2-py3-none-any.whl
  • Upload date:
  • Size: 21.6 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

Hashes for vulnradar-2.0.0b2-py3-none-any.whl
Algorithm Hash digest
SHA256 c5530f86fbeaab53fe44fc27924d018a89f0bb2efa9c6705b907d9fd91eded87
MD5 2d6f84dbb0021cd0c874785a4d34a025
BLAKE2b-256 ce145240fcd367926eb9b9270e7a5c1231212f7d0b041b62ce92b25009e53297

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page