/api/v1/phishing/urlscanURLScan.io Analysis
Submit URLs to URLScan.io for full-page rendering, screenshot capture, and threat analysis. Returns verdicts, page metadata, hosting details, and screenshot links.
Credits
3
Per request
Max URLs
5
Per request
Timeout
60s
Polling up to 30s per URL
Plans
All
Free, Starter, Professional, Enterprise
How It Works
| Step | Description |
|---|---|
| 1. Submit | Each URL is submitted to URLScan.io with unlisted visibility (your URLs are not publicly exposed) |
| 2. Render | URLScan loads the page in a real browser, capturing screenshots, DOM, network requests, and certificates |
| 3. Analyze | Community and engine verdicts are computed based on page behavior, content, and known threat patterns |
| 4. Return | Results include verdicts, screenshot links, effective URLs (after redirects), page metadata, and hosting details |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| urls | string[] | Yes | Array of 1-5 URLs to scan. Must use http:// or https:// scheme. |
Code Examples
cURL
curl -X POST https://api.dfir-lab.ch/v1/phishing/urlscan \
-H "Authorization: Bearer sk-dfir-your-key-here" \
-H "Content-Type: application/json" \
-d '{
"urls": [
"https://suspicious-login.com",
"https://another-url.net"
]
}'Python
import requests
response = requests.post(
"https://api.dfir-lab.ch/v1/phishing/urlscan",
headers={
"Authorization": "Bearer sk-dfir-your-key-here",
"Content-Type": "application/json",
},
json={
"urls": [
"https://suspicious-login.com",
"https://another-url.net",
]
},
timeout=90, # Allow for URLScan polling (up to 60s server-side)
)
data = response.json()
for result in data["data"]["results"]:
verdict = result["verdicts"]["overall"]
status = "MALICIOUS" if verdict["malicious"] else "clean"
print(f"{result['url']}: {status} (score: {verdict['score']})")
if result["screenshotUrl"]:
print(f" Screenshot: {result['screenshotUrl']}")TypeScript
const response = await fetch(
"https://api.dfir-lab.ch/v1/phishing/urlscan",
{
method: "POST",
headers: {
Authorization: "Bearer sk-dfir-your-key-here",
"Content-Type": "application/json",
},
body: JSON.stringify({
urls: [
"https://suspicious-login.com",
"https://another-url.net",
],
}),
signal: AbortSignal.timeout(90_000),
}
);
const { data, meta } = await response.json();
for (const result of data.results) {
const { overall } = result.verdicts;
console.log(
`${result.url}: ${overall.malicious ? "MALICIOUS" : "clean"}`,
`(score: ${overall.score})`
);
if (result.screenshotUrl) {
console.log(` Screenshot: ${result.screenshotUrl}`);
}
}
console.log(`Credits used: ${meta.credits_used}`);Example Response
{
"data": {
"results": [
{
"url": "https://suspicious-login.com",
"uuid": "12345678-abcd-1234-abcd-123456789012",
"verdicts": {
"overall": { "score": 75, "malicious": true },
"engines": [
{ "engine": "community", "result": "malicious" }
]
},
"screenshotUrl": "https://urlscan.io/screenshots/12345678-abcd.png",
"pageTitle": "Login - Secure Account",
"pageIp": "203.0.113.42",
"pageCountry": "CN",
"effectiveUrl": "https://suspicious-login.com/phish",
"error": null
},
{
"url": "https://another-url.net",
"uuid": "87654321-dcba-4321-dcba-210987654321",
"verdicts": {
"overall": { "score": 0, "malicious": false },
"engines": []
},
"screenshotUrl": "https://urlscan.io/screenshots/87654321-dcba.png",
"pageTitle": "Another URL - Home",
"pageIp": "198.51.100.10",
"pageCountry": "US",
"effectiveUrl": "https://another-url.net",
"error": null
}
],
"summary": {
"total": 2,
"malicious": 1,
"screenshotsAvailable": 2
}
},
"meta": {
"request_id": "req_abc",
"credits_used": 3,
"credits_remaining": 97,
"processing_time_ms": 15000
}
}Response Fields
| Field | Type | Description |
|---|---|---|
| url | string | The originally submitted URL |
| uuid | string | URLScan scan ID — use to view full results at urlscan.io/result/{uuid} |
| verdicts.overall.score | number | Threat score from 0 (clean) to 100 (malicious) |
| verdicts.overall.malicious | boolean | Whether the URL is considered malicious |
| verdicts.engines | array | Individual engine verdicts (community, third-party scanners) |
| screenshotUrl | string | null | Direct link to the rendered page screenshot |
| pageTitle | string | null | HTML title of the rendered page |
| pageIp | string | null | IP address hosting the scanned page |
| pageCountry | string | null | Country code of the hosting IP |
| effectiveUrl | string | null | Final URL after following all redirects |
| error | string | null | Error message if the scan failed for this URL |
URLScan polling may take up to 30 seconds per URL. URLs are scanned sequentially due to URLScan.io rate limits. Set client-side timeouts to at least 90 seconds to account for the 60-second server timeout.
If a scan times out before results are ready, a partial result is returned with the uuid and screenshotUrl fields (the screenshot is usually available shortly after submission).
All scans are submitted with unlisted visibility on URLScan.io. Your submitted URLs will not appear in public search results.
A score of 0 with malicious: false means no threats were detected at the time of scanning. It is not a guarantee of safety.