PHISHDESTROY / PUBLIC REST API

Threat intelligence.
Without the friction.

Give your tools a clearer view of phishing and crypto scams. Check a domain, query the blocklists, or build on the feeds.

BASE URLhttps://api.destroy.tools
Unique domains—
Primary list—
Community—
Active domains—
Loading counts from /v1/stats…
START HERE

One request. Real intelligence.

Try the public API from your browser. These are real requests, with the original response shown below.

Only the normalized hostname is sent. The submitted site is not visited.

GET/v1/check?domain=example.com
curl --fail-with-body 'https://api.destroy.tools/v1/check?domain=example.com'

Response

NOT RUN YET
Run a request to inspect the API response.

A missing blocklist match does not establish safety. Missing risk fields are not treated as a zero-risk verdict.

EIGHT ENDPOINTS. ONE OPEN API.

The reference.

GET

/v1/check

Look up a domain or URL and inspect its threat verdict and available detection signals. Input is normalized: scheme, credentials, port and path are removed and internationalized names are converted to punycode. Subdomains inherit a parent listing, except under shared-hosting suffixes such as appspot.com or pages.dev.

Single domain check parameters
ParameterTypeDescription
domain requiredstringA domain or URL to check. d and url are accepted as aliases.
REQUEST
curl --fail-with-body 'https://api.destroy.tools/v1/check?domain=example.com'
Understand the response fields
Domain check response fields
threatBoolean threat verdict returned by the API.
risk_scoreReported score from 0 to 100, when present.
severityReported severity label, when present.
listsLists that contain the matched domain. Only matching lists are present.
flagsDetection signal names, when present.
matched_domainThe listed name that matched: the input, its www. variant, or a parent domain.
listed_sinceWhen the matched domain was first listed. Confirmed entries carry the original detection time; null means unknown.
whitelistedPresent and true when the domain was reviewed and cleared as a false positive, with an appeal_url.
suspicious / heuristic_scoreFor unlisted domains with risky keywords or top-level domains. A heuristic signal, not a blocklist match.
checked_atThe check timestamp supplied by the API, when present.
POST

/v1/check/bulk

Check up to 500 domains in a single request. Send a JSON body and the Content-Type: application/json header. The body may be at most 256 KB. Results are keyed by the normalized domain, and non-string or unparsable entries are counted in summary.invalid and echoed (first 50) in invalid_inputs.

Bulk check request body
Body fieldTypeDescription
domains requiredstring[]An array of domain names, with a maximum of 500 entries.
REQUEST
curl --fail-with-body -X POST 'https://api.destroy.tools/v1/check/bulk' \
  -H 'Content-Type: application/json' \
  -d '{"domains":["example.com","example.org"]}'

Inspect the returned body and HTTP status. A failed request is not a clean verdict for the submitted domains.

GET

/v1/feed/{list}

Download a full list for firewalls, DNS filters and ad blockers. Feeds are static files regenerated only when a list changes. They support ETag and Last-Modified conditional requests and gzip, and are cacheable for 5 minutes. Append a format to the list name; without one you get JSON.

Feed formats
PathFormatUse with
/v1/feed/{list}.txtOne domain per lineScripts, SIEM, custom tooling
/v1/feed/{list}.json{list, count, updated_at, domains[]}Applications
/v1/feed/{list}.hosts0.0.0.0 domainPi-hole, hosts files
/v1/feed/{list}.adblock||domain^AdGuard, uBlock Origin
REQUEST
curl --fail-with-body --compressed -o primary.txt 'https://api.destroy.tools/v1/feed/primary.txt'
GET

/v1/stats

Retrieve current dataset counts, synchronization information, and the API version. Figures are precomputed after every synchronization, which runs every 15 minutes. No parameters are required.

REQUEST
curl --fail-with-body 'https://api.destroy.tools/v1/stats'

Counts describe the API dataset. They are not counts of confirmed takedowns.

GET

/v1/health

Open endpoint

Check database reachability and synchronization freshness before relying on results. Never cached. Returns HTTP 503 when the database is unreachable or the last synchronization is older than two hours.

REQUEST
curl --fail-with-body 'https://api.destroy.tools/v1/health'
Understand the response fields
Health response fields
statusok, degraded (last sync did not fully succeed but data is recent) or down.
dbok or error.
last_sync / sync_age_secondsTime of the last synchronization and its age.
GET

/v1/feeds

Open endpoint

List the available feeds with their entry counts, update times, and download URLs. Each file includes its size and SHA-256 checksum so you can verify downloads.

REQUEST
curl --fail-with-body 'https://api.destroy.tools/v1/feeds'
GET

/v1/feed/{list}/delta

Stay in sync without downloading full lists. Download the full .txt feed once, then request changes since the previous response's until. When truncated is true, continue from next_since. Removals are retained for 30 days; an older since returns HTTP 410 with the full feed URL.

Feed delta parameters
ParameterTypeDescription
since requiredstringISO-8601 timestamp, for example 2026-10-09T08:00:00Z, or the next_since cursor from a truncated response.
limitintegerMaximum entries per page (added and removed combined). Default 50,000; maximum 100,000.
REQUEST
curl --fail-with-body 'https://api.destroy.tools/v1/feed/primary/delta?since=2026-10-09T08:00:00Z'
Understand the response fields
Feed delta response fields
added / removedDomains added to or removed from the list in the window.
untilEnd of the window. Use it as the next since.
truncated / next_sinceMore changes are available; request again with since=next_since (an opaque cursor). Paging is lossless and keeps the same until.
GET

/v1/investigate

Open endpoint

One call that answers “what do we know about this link?” — for any domain or URL, listed or not. verdict is the authoritative blocklist result. assessment is a prediction from PhishDestroy data with a risk of high, elevated, low or none and the signals behind it. context is a plain-text summary with numbered sources, ready to hand to a language model.

Investigation signals
SignalMeaning
brand_in_nameThe name contains a brand that phishers put in domain names.
brand_homoglyphThe brand is spelled with look-alike characters, such as a Cyrillic “а” in “metamаsk”. display_name shows how the name renders.
lookalike_of_known_phishingClose spelling of a known phishing domain.
shared_name_patternKnown phishing domains built from the same words.
phishing_infrastructure_ipHosted on an IP that serves other known phishing domains and no established sites.
scam_terms / high_risk_tldWords such as verify, claim or recovery; a top-level domain heavily used for abuse.
newly_registeredRegistered within the last 90 days. Most phishing domains are under 30 days old when caught.
REQUEST
curl --fail-with-body 'https://api.destroy.tools/v1/investigate?domain=example.com'

Established high-traffic domains (Tranco top 1M) and registrations held for three years or more are capped at low risk, because phishing domains are almost always new; registration comes from the registry’s RDAP service, never from the domain itself. On a held-out sample, 68% of phishing domains detected in the last week scored elevated or high, against 1 of 300 established sites scored without the Tranco cap. A none result is not evidence of safety, and a prediction is not a confirmed listing.

GET

/v1/intel

Pull the full intelligence record for a confirmed domain: who it impersonates, how it scores across reputation sources, where it is hosted, its lifecycle, a fingerprint, and a machine-written analyst report. A domain that is not in the dataset returns found: false. WHOIS emails and personal data are never exposed, and the AI report is generated analysis, not a legal determination.

Domain intel parameters
ParameterTypeDescription
domain requiredstringA listed domain or URL. The www. variant is also tried.
REQUEST
curl --fail-with-body 'https://api.destroy.tools/v1/intel?domain=example.com'
Understand the response fields
Domain intel response groups
classificationtarget_brand, drainer_type, kit_name, scam_type.
reputationvt_detections, vt_vendors, gsb_flagged, blocklist_count, blocklist_hits, gs_trust_score.
hostingip_address, registrar, registrar_country, nameservers.
lifecycledetected_at, creation_date, site_status, last_alive, killed_at.
fingerprint / evidencefavicon_hash, technologies; screenshot_url, wayback_url, urlscan_uuid, case_id.
aiGenerated title, description, summary and generated_at.
GET

/v1/similar

Find other domains run by the same actor as a seed domain. Clustering uses a shared favicon hash, IP address or phishing kit, but only when that signal is specific to one actor — generic shared infrastructure such as a blank favicon, a shared CDN address or a broad kit is dropped so the cluster stays meaningful instead of sweeping in unrelated sites. The response reports which signals it clustered_by, and every row carries its own matched_by.

Similar domains parameters
ParameterTypeDescription
domain requiredstringThe seed domain or URL.
limitintegerMaximum rows. Default 50; maximum 500.
REQUEST
curl --fail-with-body 'https://api.destroy.tools/v1/similar?domain=example.com&limit=50'
GET

/v1/campaign

See a whole impersonation campaign at once. Pass brand (or kit) to get every tracked domain for that target with total, alive and distinct_ips and a page of domains. Pass nothing to get type: "brand_index", the top 50 brands by tracked-domain count. These counts describe tracked impersonation domains, not takedowns.

Campaign parameters
ParameterTypeDescription
brandstringImpersonated brand (case-insensitive). Mutually exclusive with kit.
kitstringPhishing kit name (case-insensitive).
limit / offsetintegerPage size (default 50, maximum 500) and offset.
REQUEST
curl --fail-with-body 'https://api.destroy.tools/v1/campaign?brand=Ledger'
PREDICTABLE FAILURES

Errors and limits.

Every error is JSON with an error field. An error is never a clean verdict.

Rate limits

Each client has two quotas that refill continuously. Public blocklist data is generous; intelligence costs more and also has a daily cap. Limits are per IP address (IPv6 per /64): no API key, no sign-up. Claude and ChatGPT connectors, which share a few IPs between many users, get the higher quota automatically.

Quotas
QuotaAnonymousClaude / ChatGPT connectorsCost
data300 units per minute3,000 per minutecheck, stats, feed: 1; search, delta: 2; bulk: 1 per 50 domains (500 domains = 10)
intel30 per minute, 1,000 per day300 per minute, 20,000 per dayintel: 1; similar, campaign, intel search: 2; investigate: 3

Responses that are not edge-cached carry RateLimit-Policy, RateLimit, X-RateLimit-Remaining and X-RateLimit-Cost. A 429 gives the exact wait in Retry-After and retry_after. Health checks, MCP connection and tool listing are free; MCP tool calls spend the same quota as their REST route. Checking thousands of domains an hour? Download a feed once and follow its delta instead.

HTTP status codes
StatusMeaningWhat to do
400Missing or invalid input, such as a domain or since.Fix the request.
404Unknown route or list.Use a documented path and list name.
405Method not allowed. The Allow header lists valid methods.Switch the method.
410Delta since is older than 30 days.Download the full feed again.
413Bulk body larger than 256 KB.Split the request.
429{"error":"rate_limited","retry_after":7,"bucket":"intel"} with an exact Retry-After header.Wait the given seconds; do not retry sooner.
500Unexpected server error.Retry later; do not treat it as clean.
503Only on /v1/health: the service is down or data is stale.Pause automated decisions.
READ THE SIGNALS

A score needs context.

The published API reference describes these signal weights. Use the server's returned verdict; don't reconstruct a verdict from a domain name alone.

Curated blocklist+40
DNS active+30
Community reported+20
Multiple sources+10
Suspicious keyword+5 each
Risky top-level domain+5

Documented severity bands

Critical70–100
High40–69
Medium20–39
Low1–19

Not every response includes a score. Missing data does not mean zero risk.

MACHINE-READABLE BY DESIGN

For the tools that use your tools.

Use an OpenAPI description for integrations, or a clean Markdown reference for agents. Both describe the same public endpoints.

Compatible browsers can expose check-phishing and bulk-check-threats through WebMCP. Both use this console's validation and results. REST remains the portable integration path.

POST

/mcp

A Model Context Protocol server (Streamable HTTP, JSON responses, no authentication). Add https://api.destroy.tools/mcp as a remote MCP server in an AI client and the model gets these tools: investigate_domain, check_domain, bulk_check_domains, search_threat_intel and get_campaign. Each tool runs the same code as its REST route and spends the same quota; connecting and listing tools is free.

In Claude, open Settings, Connectors, Add custom connector and paste the URL. In ChatGPT, turn on developer mode and create a connector with this URL and no authentication. Claude Code, Cursor and VS Code take the config below. The server needs no OAuth and never asks for a login.

CLIENT CONFIG
# Claude Code
claude mcp add --transport http phishdestroy https://api.destroy.tools/mcp

# Cursor: ~/.cursor/mcp.json
{"mcpServers":{"phishdestroy":{"url":"https://api.destroy.tools/mcp"}}}

# VS Code: .vscode/mcp.json
{"servers":{"phishdestroy":{"type":"http","url":"https://api.destroy.tools/mcp"}}}

# Clients that only run local (stdio) servers
{"mcpServers":{"phishdestroy":{"command":"npx","args":["-y","mcp-remote","https://api.destroy.tools/mcp"]}}}
REQUEST
curl --fail-with-body -X POST 'https://api.destroy.tools/mcp' \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"investigate_domain","arguments":{"domain":"example.com"}}}'
OPEN DATA. SHARED DEFENSE.

Intelligence has a community.

The project's public documentation lists these sources in its intelligence pipeline. A source appearing here does not imply endorsement or a formal partnership.

DestroyList on GitHub DestroyList on GitLab
BUILD WITH CLEAR EXPECTATIONS

Open access. Honest limits.

Requests can fail.

Handle unsuccessful HTTP statuses, timeouts, and invalid responses. Respect rate-limit responses and avoid tight retry loops. The documentation does not promise an availability SLA.

Unlisted isn't verified safe.

Combine threat intelligence with other evidence. New threats and false positives are possible. This API returns intelligence; it does not initiate takedowns.

Corrections are welcome.

Use the free appeals process for a false positive. For integration questions, email contact@phishdestroy.io.