URLScan.io API
Base URL
https://urlscan.io/api/v1
Authentication
Header: API-Key: $URLSCAN_API_KEY
Rate Limits
- Free: 100 scans/day, 100 searches/day
- Paid: Higher limits based on plan
Key Endpoints
Submit URL for scanning
curl -s -X POST "https://urlscan.io/api/v1/scan/" \
-H "API-Key: $URLSCAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com", "visibility": "unlisted"}'
Response: {"uuid": "...", "api": "https://urlscan.io/api/v1/result/UUID/"}
Important: Scan is async. Wait ~30 seconds before retrieving results. Poll the result URL until status is not 404.
Retrieve scan results
curl -s "https://urlscan.io/api/v1/result/{uuid}/" \
-H "API-Key: $URLSCAN_API_KEY"
Useful response fields:
verdicts.overall— malicious/benign scorepage.url— final URL after redirectspage.ip— IP address resolvedpage.country— hosting countrypage.server— web serverlists.ips— all IPs contactedlists.domains— all domains contactedlists.urls— all URLs loadedstats.tlsPercentage— TLS usagetask.screenshotURL— screenshot of page
Search existing scans
curl -s "https://urlscan.io/api/v1/search/?q=domain:example.com" \
-H "API-Key: $URLSCAN_API_KEY"
Search operators: domain:, ip:, server:, filename:, hash:, page.url:
Scan Flow
- Submit URL → get UUID
- Wait 30 seconds
- Poll result endpoint (retry on 404, max 5 attempts with 10s delay)
- Extract and return key findings
Response Summary Format
url: <scanned URL>
final_url: <after redirects>
verdict: malicious|suspicious|benign|unknown
ip: <resolved IP>
country: <hosting country>
technologies: [<detected technologies>]
domains_contacted: [<list>]
ips_contacted: [<list>]
screenshot: <URL>