Back to API Docs

Exposure Scanner

Try this endpoint in the playground →
POST/api/v1/exposure/scan

Scan a domain or IP address for attack surface exposure. Discovers subdomains, open ports, SSL certificates, DNS records, WHOIS data, network intelligence, and known vulnerabilities using 11 intelligence providers.

Permission

exposure:read

Credits

10 fresh / 0 cached

Plans

Starter, Professional, Enterprise

Timeout

Up to 180 seconds

Request Body

{
  "target": "example.com",
  "target_type": "auto"
}
FieldTypeDescription
targetstringDomain name or IP address to scan (required)
target_typestring"domain", "ip", or "auto" (optional — default: auto-detect)

Response

{
  "data": {
    "cached": false,
    "scan_id": "jd72k8m0x9...",
    "target": "example.com",
    "targetType": "domain",
    "status": "completed",
    "riskScore": 42,
    "riskLevel": "medium",
    "subdomains": [
      { "subdomain": "www.example.com", "source": "crt.sh", "isLive": true },
      { "subdomain": "mail.example.com", "source": "crt.sh, hackertarget" },
      { "subdomain": "api.example.com", "source": "securitytrails" }
    ],
    "ports": [
      { "host": "93.184.216.34", "port": 22, "protocol": "tcp", "state": "open", "service": "ssh", "product": "OpenSSH", "version": "8.9p1", "source": "shodan" },
      { "host": "93.184.216.34", "port": 80, "protocol": "tcp", "state": "open", "service": "http", "product": "nginx", "version": "1.24.0", "source": "shodan, criminalip" },
      { "host": "93.184.216.34", "port": 443, "protocol": "tcp", "state": "open", "service": "https", "product": "nginx", "version": "1.24.0", "source": "shodan" }
    ],
    "certificates": [
      {
        "host": "example.com",
        "port": 443,
        "subject": "*.example.com",
        "issuer": "R3",
        "issuerOrg": "Let's Encrypt",
        "validFrom": "2026-01-15T00:00:00Z",
        "validTo": "2026-04-15T00:00:00Z",
        "isExpired": false,
        "keySize": 2048,
        "signatureAlgorithm": "SHA256withRSA",
        "sans": ["*.example.com", "example.com"],
        "grade": "A",
        "source": "ssllabs"
      }
    ],
    "dns": [
      { "domain": "example.com", "recordType": "A", "values": ["93.184.216.34"], "ttl": 3600, "source": "hackertarget" },
      { "domain": "example.com", "recordType": "MX", "values": ["10 mail.example.com"], "source": "hackertarget" },
      { "domain": "example.com", "recordType": "NS", "values": ["ns1.example.com", "ns2.example.com"], "source": "hackertarget" }
    ],
    "whois": {
      "domain": "example.com",
      "registrar": "ICANN",
      "createdDate": "1995-08-14T04:00:00Z",
      "expiryDate": "2027-08-13T04:00:00Z",
      "updatedDate": "2024-08-14T07:01:44Z",
      "nameservers": ["ns1.example.com", "ns2.example.com"],
      "source": "WhoisXML"
    },
    "network": [
      { "ip": "93.184.216.34", "asn": 15133, "asnName": "Edgecast", "country": "US", "source": "ipapi, bgpview" }
    ],
    "vulnerabilities": [
      {
        "host": "93.184.216.34",
        "port": 443,
        "cveId": "CVE-2023-44487",
        "cvssScore": 7.5,
        "severity": "high",
        "description": "HTTP/2 Rapid Reset Attack",
        "affectedProduct": "nginx/1.24.0",
        "source": "shodan"
      }
    ],
    "providers": [
      { "name": "crt.sh", "status": "complete", "durationMs": 1200, "categories": ["subdomains"] },
      { "name": "shodan", "status": "complete", "durationMs": 890, "categories": ["ports", "vulnerabilities"] },
      { "name": "ssllabs", "status": "complete", "durationMs": 9500, "categories": ["certificates"] }
    ],
    "stats": {
      "subdomainCount": 3,
      "openPortCount": 3,
      "certificateCount": 1,
      "vulnerabilityCount": 1,
      "criticalVulnCount": 0,
      "highVulnCount": 1
    },
    "scannedAt": "2026-03-20T14:23:01Z",
    "durationMs": 12847
  },
  "meta": {
    "request_id": "req_a1b2c3d4-...",
    "credits_used": 10,
    "credits_remaining": 490,
    "processing_time_ms": 12903
  }
}
FieldTypeDescription
data.cachedbooleanWhether this result was served from cache (0 credits if true)
data.scan_idstringUnique Convex document ID for this scan result
data.targetstringThe normalized target that was scanned
data.targetTypestring"domain" or "ip"
data.statusstring"completed", "partial" (some providers failed), or "failed"
data.riskScorenumberOverall risk score from 0 (safe) to 100 (critical exposure)
data.riskLevelstring"info", "low", "medium", "high", or "critical"
data.subdomainsarrayDiscovered subdomains with source provider, resolved IPs, and live status
data.portsarrayOpen ports with host, protocol, state, service, product, version, and banner
data.certificatesarraySSL/TLS certificates with issuer, validity, key size, SANs, grade, and TLS vulnerabilities
data.dnsarrayDNS records as typed entries (A, AAAA, MX, NS, TXT, CNAME, etc.) with TTL
data.whoisobject | nullWHOIS registration data including registrar, dates, name servers, and DNSSEC status
data.networkarrayNetwork intelligence — ASN, CIDR, geolocation, hosting/VPN/proxy/Tor flags
data.vulnerabilitiesarrayKnown CVEs matched against discovered service versions with CVSS scores
data.providersarrayPer-provider status objects with name, status, duration, and data categories
data.statsobjectSummary counts: subdomainCount, openPortCount, certificateCount, vulnerabilityCount, criticalVulnCount, highVulnCount
data.scannedAtstringTimestamp of the scan in ISO 8601 format
data.durationMsnumberTotal scan duration in milliseconds
meta.request_idstringUnique request identifier for support and debugging
meta.credits_usednumberCredits consumed (10 for fresh scan, 0 for cache hit)
meta.credits_remainingnumberRemaining credit balance after this request
meta.processing_time_msnumberServer-side processing time in milliseconds

Intelligence Providers

Each scan queries multiple intelligence providers to build a comprehensive picture of the target's attack surface. Provider availability may vary; partial results are returned if some providers are unreachable.

ProviderData Collected
crt.shCertificate Transparency logs — discovers subdomains from issued SSL certificates
hackertargetDNS lookups, reverse DNS, and host search for subdomain enumeration
criminalipIP threat intelligence — open ports, banners, and risk scoring
shodanOpen ports, service banners, device fingerprinting, and known CVEs
ipapiIP geolocation — country, city, ASN, and hosting/VPN/proxy detection
bgpviewBGP routing data — ASN ownership, network CIDR, and prefix information
ssllabsSSL/TLS certificate analysis, grading, and protocol vulnerability detection
netlasInternet-wide scan data for hosts, open ports, and service detection
securitytrailsSubdomains, DNS history, and associated domains
WhoisXMLWHOIS registration data, registrar info, expiry dates, and name servers
OTX Passive DNSAlienVault OTX passive DNS resolution and indicator correlation

Caching

Results are cached for 24 hours. Subsequent scans of the same target within 24 hours return cached results. The response includes "cached": true when serving from cache.

Cached results cost 0 credits. Credits are only deducted for fresh scans. To force a fresh scan, wait for the cache to expire.

Code Examples

cURL
curl -X POST https://api.dfir-lab.ch/v1/exposure/scan \
  -H "Authorization: Bearer sk-dfir-your-key-here" \
  -H "Content-Type: application/json" \
  -d '{
    "target": "example.com",
    "target_type": "auto"
  }'
Python
import requests

url = "https://api.dfir-lab.ch/v1/exposure/scan"
headers = {
    "Authorization": "Bearer sk-dfir-your-key-here",
    "Content-Type": "application/json",
}

response = requests.post(
    url,
    json={"target": "example.com", "target_type": "auto"},
    headers=headers,
)
body = response.json()
scan = body["data"]
meta = body["meta"]

print(f"Risk score: {scan['riskScore']}/100 ({scan['riskLevel']})")
print(f"Subdomains found: {len(scan['subdomains'])}")
print(f"Open ports: {len(scan['ports'])}")
print(f"Vulnerabilities: {len(scan['vulnerabilities'])}")
print(f"Scan duration: {scan['durationMs']}ms")
print(f"Credits used: {meta['credits_used']}")

for vuln in scan["vulnerabilities"]:
    print(f"  [{vuln['severity']}] {vuln['cveId']}: {vuln.get('description', '')}")

Important Notes

  • Scans can take up to 3 minutes to complete. All providers are queried in parallel, but SSL Labs analysis is the slowest — the endpoint waits for all providers before returning the aggregated result.
  • Private and internal IP addresses (10.x.x.x, 192.168.x.x, 172.16-31.x.x, 127.0.0.1) are blocked and will return a 400 Bad Request.
  • Rate limits apply per API key: 3 scans/min (Starter), 10 scans/min (Professional). Enterprise plans have configurable limits.