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.0b1.tar.gz (18.1 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.0b1-py3-none-any.whl (21.1 kB view details)

Uploaded Python 3

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

Hashes for vulnradar-2.0.0b1.tar.gz
Algorithm Hash digest
SHA256 c4bcd9e64c0a1059fed1addfc514526392db04ab0bb49842ccfa48fbf0c59485
MD5 eee1f17dda408429d06ebf4dda5718e6
BLAKE2b-256 fbf7c855fe5e484efb2ee46a8aeeffa3f54ff34422125a7f1ae1caa1cb2c937a

See more details on using hashes here.

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

Hashes for vulnradar-2.0.0b1-py3-none-any.whl
Algorithm Hash digest
SHA256 bf864bf1081cfb79ff69c666514f9bcebd5d3e754f9ed9d1d286a2ff3880bc84
MD5 416e3dbc1dd032bbce72babd6e20095c
BLAKE2b-256 df5446d62762bee90b0bbcffac86093948aaeeeedef7fb2d73e23a316a4fa18f

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