Threat feed API
The Observatory publishes its licence-cleared intelligence as a stable JSON feed so DNS resolvers — including DNS Daddy — can consume it directly. No API key, no registration, no tracking. Responses are cacheable and carry strong ETags; conditional requests receive 304.
Endpoints
Base URL
https://threats.dnsdaddy.dev- GET
/api/v1/feed.jsonThe blocking feed. Domain-only, deduplicated, licence-checked. Poll every 15–60 minutes and honour the ETag.
parameters: none
- GET
/api/v1/indicatorsRicher recent intelligence with provenance and first-seen, including non-domain types.
parameters: hours (1–2160, default 24), limit (1–1000, default 100), category, severity, type
- GET
/api/v1/lookupWhat the Observatory holds about one value, with per-source provenance and infrastructure relationships.
parameters: indicator (domain, IP, URL or file hash) — required
- GET
/api/v1/healthFeed availability, indicator count and snapshot age. Sanitised: no internal telemetry.
parameters: none
Quick start
Blocking feed
curl -s https://threats.dnsdaddy.dev/api/v1/feed.json | jq '.indicator_count'
# Conditional polling: no body when nothing changed
curl -s -o /dev/null -w '%{http_code}\n' \
-H 'If-None-Match: "<etag from last response>"' \
https://threats.dnsdaddy.dev/api/v1/feed.jsonPoll no more than once per five minutes; the snapshot is rebuilt on that cadence and a repeated request otherwise just returns the same ETag.
Response shape
feed.json
{
"generated_at": "2026-01-01T00:00:00Z",
"source": "dnsdaddy-threat-observatory",
"version": 1,
"indicator_count": 4812,
"window_days": 90,
"attribution": ["abuse.ch ThreatFox (CC0)", "abuse.ch URLhaus (CC0)"],
"indicators": [
{
"value": "malicious-example.com",
"type": "domain",
"severity": "critical",
"categories": ["c2"],
"family": "AsyncRAT",
"last_seen": "2026-01-01T00:00:00Z"
}
]
}Publication rules
Why a value is or is not in the feed
- 01Only sources whose recorded licence permits full republication contribute a published value. Restricted and subscription-delivered datasets are used for internal correlation and counts only.
- 02Infrastructure-context sources never produce a blocking verdict, however confident they are about the hosting.
- 03Values must map to a canonical category — malware, phishing, c2 or cryptomining. Unclassified observations are withheld.
- 04IP literals, URLs, malformed hostnames and shared hosting or storage domains are excluded from the blocking feed.
- 05One row per logical indicator: categories are unioned, the highest defensible severity wins, the latest last_seen wins, and a malware family is kept only when the sources agree.
- 06Generation is atomic. If a build collapses to zero after previously publishing indicators, the endpoint returns 503 so your resolver keeps its last known-good copy instead of unblocking everything.
Attribution & limits
Terms of use
Every response carries the attribution strings for the sources that contributed to it. Reproduce them wherever you display or redistribute the data. Per-source licences are listed on the Sources page.
Rate limits are generous and per-caller: 120 requests per minute for the feed, 60 for indicators, 30 for lookup, 240 for health. Exceeding them returns 429 with a JSON error body. Every error response is JSON with a code and message.
This is defensive intelligence derived from third-party abuse feeds. It is not a guarantee: verify before acting on any single indicator, and treat the feed as one input to a blocking decision rather than the whole decision.