Four steps, one script, no SDK. By the end of this page you will have run a real list of hostnames against 390,000+ DNS-verified phishing domains and written the hits out to a file your blocklist can consume.
$ curl "https://phishingdetectionapi.com/api/v1/check?domain=0-105.com&apikey=YOUR_KEY"
{
"domain": "0-105.com",
"is_phishing": true,
"category": "phishing/malware",
"dns_status": "resolves",
"last_checked": "2025-07-09",
"confidence": 0.98,
"database_size": 212370
}
# that is the whole API. everything below is
# about running it over a list instead of one name.
None of them will slow you down, but all four change how you write the script.
Send a domain, get back whether it is present in a database of DNS-verified active phishing hosts, rebuilt every 24 hours at 04:30 UTC. A hit returns is_phishing: true with a category of phishing/malware, a dns_status of resolves and a confidence of 0.98.
is_phishing: false. That is not "this domain is safe" — it means it is not one of the live phishing hosts currently tracked. Design around that distinction and it will never surprise you.Follow these in order. Steps one and two take a minute between them; step three is a copy-paste.
Subscribe to a monthly plan on the pricing page — the Growth plan at $99/month gives you 25,000 lookups, which is more than enough to screen a first list and prove the integration. After payment, sign in and your API key is shown in the dashboard. Your key is your username from registration.
apikey query param or POST body field.os.environ for exactly that reason.
Put one hostname per line in a plain text file called domains.txt. Where the list comes from depends on what you are trying to prove: distinct sender and link hostnames from a day of mail logs, distinct external destinations from a day of proxy or DNS logs, or the domains already attached to an open investigation.
0-105.com
0-amazon.weebly.com
00-ede.pages.dev
000-access-secure.web.app
google.com
example.com
mail.supplier-invoices.example.org
# build one from proxy logs:
$ awk '{print $7}' access.log | cut -d/ -f3 | sort -u > domains.txt
Save the following as screen_domains.py. It reads domains.txt, chunks it into batches of 100, posts each batch to the batch endpoint, and writes every result to results.csv while printing the hits as it goes.
# pip install requests
import os, csv, time, requests
API_KEY = os.environ["PDA_API_KEY"] # never hard-code the key
BASE_URL = "https://phishingdetectionapi.com/api/v1"
BATCH = 100 # hard cap enforced by the API
def load_domains(path="domains.txt"):
with open(path) as f:
names = (line.strip().lower() for line in f)
return sorted({n for n in names if n and not n.startswith("#")})
def chunks(seq, size):
for i in range(0, len(seq), size):
yield seq[i:i + size]
def screen(domains):
results = []
for group in chunks(domains, BATCH):
r = requests.post(
f"{BASE_URL}/batch",
json={"apikey": API_KEY, "domains": group},
timeout=20,
)
if r.status_code == 429: # rate limit or credits exhausted
print("429:", r.json().get("error"))
time.sleep(2)
continue
r.raise_for_status()
payload = r.json()
results.extend(payload["results"])
print(f"checked {payload['checked']}, "
f"phishing_found {payload['phishing_found']}, "
f"credits_used {payload['credits_used']}")
time.sleep(0.15) # stay under 10 req/s
return results
if __name__ == "__main__":
domains = load_domains()
results = screen(domains)
with open("results.csv", "w", newline="") as out:
w = csv.writer(out)
w.writerow(["domain", "is_phishing", "category", "dns_status"])
for row in results:
w.writerow([row["domain"], row["is_phishing"],
row["category"], row["dns_status"]])
hits = [r for r in results if r["is_phishing"]]
print(f"\n{len(hits)} phishing domains out of {len(results)} checked")
for h in hits:
print(" ", h["domain"])
export PDA_API_KEY=your_key followed by python3 screen_domains.py. The 0.15-second pause keeps you comfortably under the documented ceiling of 10 requests per second per key.
You now have results.csv with one row per domain and a printed summary of the hits. What happens next is the part that matters, and it should be proportionate to how expensive a wrong answer is to reverse.
domain,is_phishing,category,dns_status
0-105.com,True,phishing/malware,resolves
0-amazon.weebly.com,True,phishing/malware,resolves
00-ede.pages.dev,True,phishing/malware,resolves
000-access-secure.web.app,True,phishing/malware,resolves
google.com,False,,
example.com,False,,
mail.supplier-invoices.example.org,False,,
$ awk -F, '$2=="True"{print $1}' results.csv > blocklist.txt
The script you just ran is the whole integration. Productionising it is about where you put each stage, not about adding code.
An MTA hook, a proxy log shipper, or a SIEM search returning distinct external destinations for the last interval. You are not creating a new data source — you are reading one you already have.
It does two jobs at once: it removes the domains you already trust, and it collapses repeats. That is what keeps a high-volume pipeline inside a sensible monthly allowance.
Treat phishing_found as a routing key, not a verdict on the payload. An analyst handed three named domains starts work; an analyst handed "suspicious activity" starts by reproducing your query.
One exception worth naming: if your enforcement point is a DNS resolver or a firewall rather than an application, stop using per-lookup API calls for it entirely and switch to the bulk export. The economics and the latency both favour it, and there is no per-query network dependency at decision time — that path is described on the daily threat feed page.
Reference material, commercial detail and the integration shapes for specific systems.
Every parameter, every response field, every error code, plus clients in four languages.
Read the docsWhat 400, 401, 405, 429 and 500 mean, and how to tell a rate limit from an empty balance.
See the tableFour monthly plans compared, from 25,000 to 750,000 lookups per month.
Compare plansThe whole database as a daily CSV or JSON export, for resolvers and firewalls.
See the feedWhat the phishing/malware label covers, and the campaign shapes behind it.
Integration walkthroughs for gateways, SIEMs, browsers, resolvers and whole industries.
Browse use casesSubscribe to a plan, export your key as PDA_API_KEY, and run the screening script against yesterday's proxy log. Most teams find something on the first pass.