Four endpoints, one API key, JSON everywhere. This page is the complete reference: parameters, response fields, error codes, rate limits and worked examples in four languages.
The Phishing Detection API provides real-time access to a continuously updated database of DNS-verified active phishing domains. The database currently contains 390,000+ actively resolving phishing domains and is updated every 24 hours.
Every entry in the database has passed a DNS resolution check before publication, so what you are querying is live infrastructure rather than a historical list of names. That constraint is the single most important thing to understand about the dataset, because it dictates both what the API is excellent at and where it deliberately stays silent. Domains that have been registered but are not yet serving do not appear; domains that have been suspended since the last build are dropped.
All API requests require an API key passed as a query parameter (apikey), or in the request body for POST endpoints. Your API key is your username from registration.
# API key as a query parameter
GET /api/v1/check?domain=example.com&apikey=your_api_key
# API key in a POST body
POST /api/v1/batch
{
"apikey": "your_api_key",
"domains": ["example1.com", "example2.com"]
}
All API endpoints are relative to a single host and version prefix. There is no regional routing to configure and no separate sandbox host.
https://phishingdetectionapi.com/api/v1/
Check whether a single domain is present in the phishing database. This is the most common endpoint and the one to use for real-time URL filtering, contact-centre lookups and interactive analyst tooling.
| Parameter | Type | Required | Description |
|---|---|---|---|
domain | string | Required | The domain to check, for example suspicious-site.com. The API automatically strips http://, https:// and path segments. |
apikey | string | Required | Your API key (the username from registration). |
curl "https://phishingdetectionapi.com/api/v1/check?domain=suspicious-login.example.com&apikey=YOUR_KEY"
{
"domain": "suspicious-login.example.com",
"is_phishing": true,
"dns_status": "resolves",
"last_checked": "2026-07-28",
"database_size": 120212553
}
{
"domain": "google.com",
"is_phishing": false,
"dns_status": "resolves",
"last_checked": "2026-07-28",
"database_size": 120212553
}
Note that a clean domain is a 200, not a 404. Both outcomes have the same response shape, so client code has exactly one branch to write and no error handling to conflate a "not phishing" verdict with a transport failure. The dns_status field is evaluated in real time on every request and is never null: a hostname that does not currently exist in DNS returns does_not_resolve. A syntactically invalid domain returns a 400 error instead of a verdict.
Check up to 100 domains in a single request. Each domain in the batch costs 1 API credit. This is the right endpoint for processing email link lists, log files and bulk URL scanning, because it removes the per-request round-trip cost from the hot path.
| Field | Type | Required | Description |
|---|---|---|---|
apikey | string | Required | Your API key. |
domains | array | Required | Array of domain strings to check. Maximum 100 per request. |
curl -X POST "https://phishingdetectionapi.com/api/v1/batch" \
-H "Content-Type: application/json" \
-d '{
"apikey": "YOUR_KEY",
"domains": [
"0-105.com",
"google.com",
"suspicious-bank-login.example.com"
]
}'
{
"results": [
{
"domain": "0-105.com",
"is_phishing": true,
"dns_status": "resolves"
},
{
"domain": "google.com",
"is_phishing": false,
"dns_status": "resolves"
},
{
"domain": "suspicious-bank-login.example.com",
"is_phishing": false,
"dns_status": "does_not_resolve"
}
],
"checked": 3,
"phishing_found": 1,
"credits_used": 3,
"database_size": 120212553
}
phishing_found as a routing key rather than a verdict on the whole payload. Zero means continue and log; one or more means quarantine, push the matched domains to your own blocklist, and open a case with the specific hostnames attached rather than a generic alert.
Download the complete phishing domain database as a CSV file. This endpoint requires a daily feed subscription. The database is updated at 04:30 UTC daily.
| Parameter | Type | Required | Description |
|---|---|---|---|
apikey | string | Required | Your API key. Must have an active feed subscription. |
format | string | Optional | Response format: csv (default) or json. |
# Download as CSV curl -o phishing_domains.csv "https://phishingdetectionapi.com/api/v1/feed?apikey=YOUR_KEY" # Download as JSON curl "https://phishingdetectionapi.com/api/v1/feed?apikey=YOUR_KEY&format=json"
domain,category,dns_status 0-105.com,phishing/malware,resolves 0-amazon.weebly.com,phishing/malware,resolves 0-amfc.firebaseapp.com,phishing/malware,resolves ...
Get current statistics about the phishing domain database, including total domains, last update time and data source information.
{
"total_active_domains": 212370,
"total_all_time": 496443,
"last_updated": "2025-07-09T04:30:00Z",
"update_frequency": "daily",
"dns_verification": true
}
All API responses are returned as JSON. The five fields below make up the single-check response.
Every field is always present and never null, so client code has exactly one shape to handle.
true if the domain is in the phishing database, false otherwise.resolves or does_not_resolve.YYYY-MM-DD.The API uses standard HTTP status codes. Error responses include a JSON body with an error field.
| Status | Meaning | Description |
|---|---|---|
| 400 | Bad Request | Missing required parameter, for example domain. |
| 401 | Unauthorized | Missing or invalid API key. |
| 405 | Method Not Allowed | Wrong HTTP method, for example a GET on a POST-only endpoint. |
| 429 | Too Many Requests | API credits exhausted or rate limit exceeded. |
| 500 | Server Error | Internal server error. Contact support if it persists. |
{
"error": "API credits exhausted. Please purchase more credits."
}
A 429 is the only status that changes behaviour depending on cause: it is returned both when the per-second rate limit is exceeded and when the credit balance reaches zero. Treat the first as retryable with backoff and the second as an operational alert, and read the error string to tell them apart.
Rate limits depend on your plan and credit balance. Each API call consumes 1 credit, and batch calls consume 1 credit per domain.
| Limit type | Value | Notes |
|---|---|---|
| Requests per second | 10 | Per API key. |
| Batch size | 100 domains | Per POST request. |
| Monthly credits | Per plan | See the pricing page. |
| Feed downloads | Unlimited | With an active feed subscription. |
The practical lever on both cost and throughput is deduplication rather than concurrency. A mail gateway sees enormous message volume but a comparatively small set of distinct external hostnames per day, and a short-lived in-process cache collapses most of what remains. Size your credit pack on distinct domains per day, batch them a hundred at a time, and the per-second ceiling stops being a constraint.
Four complete clients. Each one covers the single-check endpoint, and the first two also wrap the batch endpoint.
import requests
API_KEY = "your_api_key"
BASE_URL = "https://phishingdetectionapi.com/api/v1"
# Single domain check
def check_domain(domain):
response = requests.get(
f"{BASE_URL}/check",
params={"domain": domain, "apikey": API_KEY}
)
return response.json()
# Batch check
def batch_check(domains):
response = requests.post(
f"{BASE_URL}/batch",
json={"apikey": API_KEY, "domains": domains}
)
return response.json()
# Usage
result = check_domain("suspicious-site.com")
if result["is_phishing"]:
print(f"BLOCKED: {result['domain']} is phishing!")
# Batch usage
results = batch_check(["site1.com", "site2.com", "site3.com"])
for r in results["results"]:
if r["is_phishing"]:
print(f"Phishing: {r['domain']}")
const API_KEY = 'your_api_key';
const BASE_URL = 'https://phishingdetectionapi.com/api/v1';
// Single check
async function checkDomain(domain) {
const url = `${BASE_URL}/check?domain=${domain}&apikey=${API_KEY}`;
const res = await fetch(url);
return res.json();
}
// Batch check
async function batchCheck(domains) {
const res = await fetch(`${BASE_URL}/batch`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ apikey: API_KEY, domains })
});
return res.json();
}
// Usage
const result = await checkDomain('suspicious-site.com');
if (result.is_phishing) {
console.log(`BLOCKED: ${result.domain}`);
}
<?php
$apiKey = 'your_api_key';
$baseUrl = 'https://phishingdetectionapi.com/api/v1';
// Single check
function checkDomain($domain) {
global $apiKey, $baseUrl;
$url = $baseUrl . '/check?' . http_build_query([
'domain' => $domain,
'apikey' => $apiKey
]);
return json_decode(file_get_contents($url), true);
}
// Usage
$result = checkDomain('suspicious-site.com');
if ($result['is_phishing']) {
echo "BLOCKED: {$result['domain']} is phishing!\n";
}
# Single check
curl "https://phishingdetectionapi.com/api/v1/check?domain=suspicious.com&apikey=YOUR_KEY"
# Batch check
curl -X POST "https://phishingdetectionapi.com/api/v1/batch" \
-H "Content-Type: application/json" \
-d '{"apikey":"YOUR_KEY","domains":["site1.com","site2.com"]}'
# Download daily feed
curl -o phishing.csv "https://phishingdetectionapi.com/api/v1/feed?apikey=YOUR_KEY"
The API uses standard REST conventions, so any HTTP client works. No SDK is required. Make GET or POST requests with your API key and parse the JSON response.
Buy a credit pack, take your key from the dashboard, and run the Python block above against a domain you already suspect. If the pipeline has seen it, you will know in fifty milliseconds.