Documentation
Overview
MultiRBL checks an IPv4/IPv6 address or a domain against many free DNS blocklists (DNSBL/RBL) and reports reverse DNS (PTR) with forward-confirmed reverse DNS (FCrDNS). It is available as a web page, a JSON API and an MCP server. All three return the same report.
The API is key-less: there is no account, token or captcha. Honestly, that means it is protected only by caching and limits (see Limits). If it gets abused, a free API key may be introduced without changing the response shape.
Machine-readable descriptions: /openapi.json (OpenAPI 3.1), /.well-known/api-catalog (RFC 9727), /.well-known/mcp/server-card.json (MCP server card, a draft convention, not a final standard), /llms.txt.
Quickstart
curl 'https://multirbl.wojtek.ovh/api/v1/check?target=203.0.113.10'
curl 'https://multirbl.wojtek.ovh/api/v1/check?target=example.com&mx=1'
Read summary first: listed is the number of real listings, blocked and error mean the answer is incomplete.
How to read results
- listed: the list returned an answer in 127.0.0.0/8 for this target.
codesandreason(TXT) explain why, when the list provides it. - clean: the list answered NXDOMAIN (not listed).
- blocked: the list refused the query (answers such as 127.255.255.252/254/255, typical when asking via a public resolver). This is not a listing and says nothing about the target.
- error: no usable answer (timeout, SERVFAIL, unexpected answer). Try again later.
- collateral lists (UCEPROTECT L2 and L3: whole subnets or ASNs) are marked
collateral: true. A listing there is informational and is counted insummary.collateral, not insummary.listed. - FCrDNS (per IP):
okthe PTR name resolves back to the same IP;mismatchit does not;noneno PTR;errorlookup failed. Mail servers expectok. - Only IPv4 addresses are checked against IP lists; IPv6 gets reverse DNS only.
- Outlook / Microsoft has no public DNSBL, so it cannot be checked over DNS. A clean result does not rule out a block there; use sender.office.com.
API (v1)
Base URL https://multirbl.wojtek.ovh. Methods: GET, HEAD, OPTIONS. JSON responses. CORS is open (*) for GET, without credentials.
GET /api/v1/check
Parameters: target (required; public IP or domain), mx (optional, 1 also checks MX hosts; domains only).
curl 'https://multirbl.wojtek.ovh/api/v1/check?target=example.com&mx=1'
Response (abridged):
{
"target": "example.com",
"kind": "domain",
"dns": { "a": ["203.0.113.10"], "aaaa": [], "mx": [{ "pref": 10, "host": "mx.example.com" }] },
"ips": [{
"ip": "203.0.113.10", "source": "a",
"ptr": ["mail.example.com"], "fcrdns": "ok",
"zones": [{ "zone": "bl.spamcop.net", "region": "US", "note": "SpamCop",
"query": "10.113.0.203.bl.spamcop.net", "status": "clean" }]
}],
"domains": [{ "name": "example.com", "source": "target", "zones": [] }],
"options": { "mx": true },
"summary": { "listed": 0, "collateral": 0, "clean": 41, "blocked": 0, "error": 0 }
}
GET /api/v1/zones
The list of checked DNSBLs: zone, kind, region, note, collateral.
curl 'https://multirbl.wojtek.ovh/api/v1/zones'
GET /api/v1/status
Health check, free: {"ok":true,"zones":N,"version":"..."}.
curl 'https://multirbl.wojtek.ovh/api/v1/status'
Results are cached for 15 minutes; a cache hit is free and does not count against limits. 429 responses carry Retry-After: 60.
MCP server
Endpoint POST https://multirbl.wojtek.ovh/mcp, Streamable HTTP, no authentication, stateless, single application/json responses (no SSE, no sessions). GET and DELETE return 405. If an Origin header is sent it must be https://multirbl.wojtek.ovh; otherwise 403. Supported protocol versions: 2026-07-28 (stateless), 2025-11-25, 2025-06-18.
Methods: server/discover, tools/list, tools/call, ping, and legacy initialize. Tools (read-only):
check_blacklistswith{ "target": string, "include_mx"?: boolean }: returns the report asstructuredContentplus a short text summary.list_blacklistswith{}.
Modern request (2026-07-28)
Required headers: MCP-Protocol-Version, Mcp-Method (must equal method) and, for tools/call, Mcp-Name (must equal params.name). The body carries the version in _meta, which must match the header.
curl -X POST 'https://multirbl.wojtek.ovh/mcp' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'MCP-Protocol-Version: 2026-07-28' \
-H 'Mcp-Method: tools/call' \
-H 'Mcp-Name: check_blacklists' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call",
"params":{"name":"check_blacklists",
"arguments":{"target":"example.com","include_mx":true},
"_meta":{"io.modelcontextprotocol/protocolVersion":"2026-07-28"}}}'
Legacy initialize (2025-11-25, 2025-06-18)
curl -X POST 'https://multirbl.wojtek.ovh/mcp' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize",
"params":{"protocolVersion":"2025-11-25","capabilities":{},
"clientInfo":{"name":"curl","version":"1"}}}'
The server answers statelessly (no Mcp-Session-Id); notifications/initialized returns 202.
Tool failures (bad target, rate limit) return a result with isError: true. Malformed requests return JSON-RPC errors: -32020 header mismatch (400), -32022 unsupported version (400, with data.supported), -32601 unknown method (404).
Discovery: /.well-known/mcp/server-card.json. The server card is a draft convention, not a final standard, and may change.
Errors
API errors use one shape: {"error":{"code":"...","message":"..."}}.
| Code | Meaning |
|---|---|
invalid_target | Not a public IP or valid domain (private, reserved, malformed). |
rate_limited | HTTP 429 with Retry-After: 60. Wait and retry. |
captcha_required, captcha_failed | Web UI endpoint /api/check only (Turnstile). Not used by /api/v1. |
upstream_error | DNS resolution failed upstream. |
not_found | Unknown path. |
method_not_allowed | Only GET, HEAD and OPTIONS are accepted. |
Limits
| Limit | Value |
|---|---|
| Checks (cache misses), API, MCP and web | 6 per minute per client IP, plus 120 per minute global per Cloudflare location |
| Read-only endpoints (zones, openapi, catalog) | 60 per minute per client IP |
| Result cache | 15 minutes; hits are free |
| IP addresses per check | max 8 per address family |
| MX hosts per domain | max 5 |
| Concurrent DNS queries | 6 |
| Timeout per DNS query | 4 seconds |
The key-less API has no captcha, so it is bounded by cache and these limits only. Do not poll: one check per target per 15 minutes is enough.
Privacy
No accounts, no cookies, no stored IP addresses or checked targets. Only anonymous aggregate counters are kept (channel, outcome, country, duration). Results are cached for 15 minutes. DNS queries are sent over DNS-over-HTTPS to Cloudflare, and some lists (Spamhaus, SpamRATS) via a relay server. The web form loads Cloudflare Turnstile (a bot check) from challenges.cloudflare.com only when a check needs verification; the API and MCP do not. Requests pass through Cloudflare, which processes IP addresses as our hosting provider. Nothing else is shared with third parties. See the FAQ. Last updated: 2026-10-26.