POST
/api/v1/phishing/checkphishCheckPhish URL Scan
Scan URLs against CheckPhish.ai for phishing detection, brand impersonation, and malware hosting. Uses a submit-and-poll pattern with SSRF protection.
Credits
2
Per request
Max URLs
5
Per request
Timeout
60s
Polling up to 30s
Plans
All
Free, Starter, Professional, Enterprise
Disposition Types
| Disposition | Description |
|---|---|
| clean | URL is not flagged for any threats |
| phishing | URL identified as a phishing page attempting to steal credentials or data |
| malware | URL is hosting or distributing malicious software |
| suspicious | URL exhibits suspicious characteristics but is not definitively malicious |
| unknown | CheckPhish could not determine the disposition of the URL |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| urls | string[] | Yes | Array of 1-5 URLs to scan. Must use http:// or https:// scheme. Duplicates are removed before scanning. |
How It Works
- URLs are validated, deduplicated, and checked against SSRF protection (private/reserved IPs are blocked).
- Each URL is submitted to CheckPhish.ai sequentially (rate limit friendly).
- The API polls CheckPhish for results (up to 30s per URL) using a submit-and-poll pattern.
- Results are returned with disposition, brand detection, insights, and screenshot URL.
Code Examples
cURL
curl -X POST https://api.dfir-lab.ch/v1/phishing/checkphish \
-H "Authorization: Bearer sk-dfir-your-key-here" \
-H "Content-Type: application/json" \
-d '{
"urls": [
"https://suspicious-site.com",
"https://another-url.com"
]
}'Python
import requests
response = requests.post(
"https://api.dfir-lab.ch/v1/phishing/checkphish",
headers={
"Authorization": "Bearer sk-dfir-your-key-here",
"Content-Type": "application/json",
},
json={
"urls": [
"https://suspicious-site.com",
"https://another-url.com",
]
},
timeout=90, # Allow for polling time
)
data = response.json()
for result in data["data"]["results"]:
disposition = result["disposition"]
brand = result.get("brand", "N/A")
if disposition != "clean":
print(f"FLAGGED {result['url']}: {disposition} (brand: {brand})")
else:
print(f"CLEAN {result['url']}")TypeScript
const response = await fetch(
"https://api.dfir-lab.ch/v1/phishing/checkphish",
{
method: "POST",
headers: {
Authorization: "Bearer sk-dfir-your-key-here",
"Content-Type": "application/json",
},
body: JSON.stringify({
urls: [
"https://suspicious-site.com",
"https://another-url.com",
],
}),
}
);
const { data, meta } = await response.json();
console.log(`Credits used: ${meta.credits_used}`);
console.log(`Summary: ${data.summary.flagged} flagged / ${data.summary.total} total`);
for (const result of data.results) {
const status = result.disposition === "clean" ? "CLEAN" : "FLAGGED";
console.log(`[${status}] ${result.url} - ${result.disposition}`);
}Example Response
{
"data": {
"results": [
{
"url": "https://suspicious-site.com",
"jobID": "abc123",
"status": "done",
"disposition": "phishing",
"brand": "PayPal",
"insights": {},
"screenshot": "https://...",
"resolved": true
},
{
"url": "https://another-url.com",
"jobID": "def456",
"status": "done",
"disposition": "clean",
"brand": "",
"insights": {},
"screenshot": "https://...",
"resolved": true
}
],
"summary": {
"total": 2,
"clean": 1,
"flagged": 1,
"pending": 0
}
},
"meta": {
"request_id": "req_abc",
"credits_used": 2,
"credits_remaining": 98,
"processing_time_ms": 5000
}
}Response Fields
| Field | Type | Description |
|---|---|---|
| url | string | The scanned URL |
| jobID | string | CheckPhish job identifier |
| status | "done" | "pending" | "error" | Scan completion status |
| disposition | "clean" | "phishing" | "malware" | "suspicious" | "unknown" | Threat classification |
| brand | string | Impersonated brand detected (e.g. PayPal, Microsoft) |
| insights | object | Additional scan insights from CheckPhish |
| screenshot | string | URL to a screenshot of the scanned page |
| resolved | boolean | Whether the URL resolved successfully |
Results are powered by CheckPhish.ai by Bolster. The submit-and-poll pattern means responses may take longer than other endpoints (up to 60 seconds for 5 URLs).
SSRF protection blocks URLs that resolve to private or reserved IP ranges (127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, etc.). Each URL is scanned sequentially to respect upstream rate limits.
A clean disposition means CheckPhish did not flag the URL at the time of the scan. It is not a guarantee of safety.