RDAP Registration Lookup Guide (Domains & IP Addresses)
RDAP (Registration Data Access Protocol) is the modern replacement for the legacy WHOIS protocol. All DataPulse registration tools use RDAP.
Use datapulse_live_rdap for all registration lookups — domains and IP addresses.
datapulse_live_rdap
Supports domain names (including IDN, and emoji or symbol names as registries actually sold them, raw or punycode) and IP addresses (IPv4 and IPv6). A domain is reduced to its registrable name under the full Public Suffix List, private suffixes included, before the lookup: www.Example.COM. is looked up as example.com, www.microsoft.jp.net as microsoft.jp.net, and the response then carries submitted_domain with what you sent. RDAP is the only tool family that removes hostname labels, because registries only know registered names; the DNS tools (datapulse_live_dns, datapulse_dns_dphistory, datapulse_live_domain_health, datapulse_dns_dptechsim, datapulse_dns_neighborhood) canonicalize the spelling and keep the hostname. A single label (localhost, com) is refused, and so is a registrable domain with an underscore (exa_mple.com), which no registry registers; _dmarc.example.com is looked up as example.com. The rules for every tool are in datapulse_help(topic="normalization").
Parameters
| Parameter | Required | Default | Description |
|---|---|---|---|
query | Yes | — | Domain name or IP address to look up (e.g., example.com, xn--n3h.com, 8.8.8.8, 2601:249:8080:5296::35). IDN and punycode supported for domains. Reserved addresses (loopback, RFC 1918, link-local, CGNAT, documentation ranges) are refused with the reason: no RIR can answer for them. |
force | No | false | Bypass every cache and force a fresh live lookup via the Scrape API. |
metadata | No | — | Custom key-value pairs stored with the result. Stored, not echoed back; shared with every caller of this deployment (see datapulse_help(topic="scraping")). |
Lookup Strategy
For domain queries, the tool uses a two-step strategy:
- DataPulse API (fast path): Checks the DataPulse database for cached RDAP summary data. Near-instant.
- Scrape API (fallback): If not found in DataPulse (or if
force: true), performs a live RDAP lookup via the Scrape API.
Both sources return the same compact summary format (see Response Format below).
For IP address queries, the tool goes to the Scrape API, which answers from its own cache when it has a recent result (a lookup can be served from a result several weeks old) and otherwise queries the RIR; force: true refreshes. The response format for IP lookups differs from domain lookups.
Response Format
Domain lookups
Both the DataPulse fast path and Scrape API fallback return the same compact summary. Every response uses the envelope {query, type, datetime, results}, where type is "domain" or "ip":
{
"query": "example.com",
"type": "domain",
"datetime": "2026-03-20T18:16:46Z",
"results": [
{
"name": "example.com",
"researchdate": "2026-02-03T21:07:05Z",
"ianaid": 3827,
"registrationdate": "2026-01-30T22:30:36Z",
"expirationdate": "2027-01-30T22:30:36Z",
"status": ["client delete prohibited", "client transfer prohibited"],
"dns": ["ns-cloud-a1.googledomains.com", "ns-cloud-a2.googledomains.com"],
"abuse_email": "abuse-complaints@squarespace.com",
"abuse_phone": [{"type": "voice", "value": "tel:1-646-693-5324"}]
}
]
}
Field reference:
| Field | Type | Description |
|---|---|---|
name | string | Domain name |
researchdate | string | When this RDAP data was collected |
ianaid | integer | IANA registrar ID |
registrationdate | string | Domain registration date |
expirationdate | string | Domain expiration date. Optional — may be absent. |
last_changed | string | RFC 3339 timestamp of the last RDAP-visible change. Optional — may be absent (many TLDs/registrars never publish a “last changed” event). |
status | array | EPP status codes (see Status Codes below), case-folded, in the order the API sent them |
dns | array | Authoritative nameservers, case-folded with the shared dpdomain fold, in the order the API sent them — the same representation datapulse_dns_rdap_history and datapulse_domain_overview use |
abuse_email | string | Registrar abuse contact email |
abuse_phone | array | Registrar abuse contact phone numbers (optional) |
The envelope also carries submitted_domain when normalisation changed the name you sent (IDN folded to punycode, a subdomain or trailing dot dropped, a fullwidth homograph folded to ASCII); it is absent when only letter case differed. Note the expiry field is expirationdate here and in the overview’s rdap block, but expiration_date in datapulse_dns_rdap_history and in the overview summary; the two tools come from different DataPulse services and the names are kept as each service publishes them.
IP address lookups
IP lookups use the same envelope with type: "ip"; each result object is a compact network summary. Only network_name, start_address, end_address and researchdate are always present; handle, type, cidr, country, organization, registration_date, last_changed, status, abuse_email, abuse_phone and port43 appear when the RIR publishes them, and the RIRs differ:
- ARIN omits
country. Country codes are case-folded to lower case whatever the RIR published (RIPE’s IPv6 objects sayiewhere its IPv4 objects sayNL; both come back as lower case). organizationis whatever the RIR published as the registrant entity, which for some RIPE objects is a maintainer handle (MNT-…) rather than an organisation name.- LACNIC puts the prefix in
handleand omitscidr. - AFRINIC and APNIC sometimes publish no abuse contact, so
abuse_email/abuse_phoneare absent.
Timestamps are returned as the RIR published them (ARIN uses a -05:00 offset where the others use Z, and precision varies), so parse them rather than comparing strings.
Lookup errors
When a lookup fails (domain does not exist, TLD has no RDAP server, timeout), the tool returns an error carrying the API’s HTTP status and its response body verbatim. Common failure causes:
- Domain does not exist (NXDOMAIN)
- TLD has no RDAP server (some ccTLDs — this is an RDAP protocol limitation, not a DataPulse coverage gap; ccTLD domains are fully covered by search, history, and clustering tools)
- IP address not allocated or not found in RIR database
- Registry/RIR rate limiting or timeout
Caching Behavior
- DataPulse database is checked first for domain queries. Data freshness depends on the DataPulse research schedule.
- Use
force: trueto skip the DataPulse cache and force a fresh live lookup via the Scrape API. - A forced live lookup does not add an observation to
datapulse_dns_rdap_history; history is the collector’s own crawl schedule. - The single tool and
datapulse_live_rdap_bulkuse different caches: the single tool answers from the DataPulse database when it can, while bulk consults only the Scrape API’s own 90-day cache (socachedin a bulk receipt is usually nonzero) and queues a job for anything not in it. A domain the single tool answers from the DataPulse database can therefore be researched again by a bulk submission. - When diagnosing why a domain is missing from listings, always use
force: true— clients need current registry status, not a cached snapshot. Seedatapulse_help(topic="why_missing").
Bulk Lookups
For bulk RDAP lookups (up to 1000 domains or IPs per request), use datapulse_live_rdap_bulk. Supports mixed queries — domains and IP addresses can be submitted together. This is async — returns job receipts, not results. Retrieve individual results afterward by calling datapulse_live_rdap(query=...) for each query; completed lookups return the cached result instantly.
Every item is validated before anything is sent. A malformed or blank query, a single label, an underscore domain or a reserved address is reported in rejected_local and the rest of the batch still goes through; a query repeated in the batch is submitted once and listed in duplicates; domains are reduced to the registrable name exactly as the single tool does. The receipt for six inputs:
{
"accepted": 1, "rejected": 0, "cached": 2,
"batch_id": "f47ac10b-...",
"submitted": [
{"index": 0, "query": "example.com", "domain_hash": "a379a6f6...", "job_id": "550e8400-...", "cached": false},
{"index": 2, "query": "8.8.8.8", "domain_hash": "838c4c25...", "cached": true},
{"index": 5, "query": "xn--bcher-kva.com", "domain_hash": "9c1d...", "cached": true}
],
"rejected_items": [],
"rejected_local": [
{"index": 1, "query": "127.0.0.1", "error": "invalid query \"127.0.0.1\": 127.0.0.1 is a loopback address and has no RIR registration"},
{"index": 4, "query": "not a domain!!", "error": "invalid query \"not a domain!!\": ..."}
],
"duplicates": [{"index": 3, "query": "WWW.Example.COM.", "first_index": 0}],
"job_ids": ["550e8400-..."], "domain_hashes": ["a379a6f6...", "838c4c25...", "9c1d..."], "errors": []
}
Every input is accounted for: accepted + cached + rejected + len(rejected_local) + len(duplicates) equals the number of items you passed (1 + 2 + 0 + 2 + 1 = 6).
submitted[].indexis the position in yourdomainsarray;queryis the normalised form that was sent;domain_hashis the hex SHA-256 of that query and the keydatapulse_live_rdapanswers from. The name is historical: for an address it is the hash of the address text (the same valuedatapulse_live_rdapuses), not of any domain.job_idandcachedcome from the API’s per-item report and are absent when it sends none; nothing is inferred from the flatjob_idslist.submittedis what was sent, not what was accepted: an item the API refuses stays listed, without ajob_id, and also appears inrejected_items.accepted,cachedandrejectedare the API’s own counts over the items that were sent.rejected_items(index,query,error) lists what the API refused, with its code.rejected_local(index,query,error) lists what was refused before the request, with the reason. These are not counted inrejected, because the API never saw them. To find every failure, read both lists.domain_hashesandjob_idsare the API’s flat lists in its own order (addresses included, under the same historical name); usesubmittedto map anything back to an input.errorsholds only the API’s own rejection codes. Since every item is validated first, it is[]unless the API refused something that passed validation; do not read an emptyerrors, orrejected: 0, as “nothing was rejected” — checkrejected_local.
Interpreting Registration Data
Domain Status Codes
| Status Code | Meaning | Security Implication |
|---|---|---|
ok | No restrictions | Unlocked - vulnerable to hijacking |
clientTransferProhibited | Transfer locked | Standard protection |
clientDeleteProhibited | Delete locked | Protected |
clientUpdateProhibited | Update locked | Protected |
serverTransferProhibited | Registry lock | Enhanced protection |
serverHold | Suspended by registry | Domain has issues |
clientHold | Suspended by registrar | Domain has issues |
redemptionPeriod | Expired, pending delete | Domain may be dropped |
pendingDelete | Will be released | Domain expiring |
Best practice: All three client*Prohibited statuses should be present.
Lock depth as an ownership signal. The status array is also one of the better available
signals for who runs a domain, because it reflects a configuration the owner chose. Corporate
portfolios typically carry the three client*Prohibited codes plus the three registry-level
server*Prohibited codes, which retail registrars generally do not offer. A lone
client transfer prohibited is the default on nearly every retail registration — it is the
absence of a posture rather than a posture. When you need to judge whether a brand-carrying
domain belongs to that brand, diff its status array against a domain the brand certainly
owns; lock depth is more reliable than the registrar name, which misreads acquisitions,
regional offices, and legacy registrations. See datapulse_help(topic="brand_adjacent").
In the RDAP summary, status codes appear in the status array (e.g., ["client transfer prohibited", "client delete prohibited"]). In WHOIS, they appear as Domain Status: lines.
Dates
| Summary Field | Description |
|---|---|
registrationdate | When the domain was first registered (older = more established) |
expirationdate | When the domain expires (short runway = risk). Optional — may be absent. |
researchdate | When DataPulse last collected this RDAP data |
Registrar
The ianaid field is the IANA-assigned registrar ID. Use datapulse_dns_registrar(iana_id=...) to look up registrar details.
| Registrar Type | Typical Users |
|---|---|
| MarkMonitor, CSC | Large enterprises, brand protection |
| Cloudflare, AWS | Tech companies |
| GoDaddy, Namecheap | SMB, individuals |
| Tucows, eNom | Resellers |
Nameservers
The dns array contains the authoritative nameservers. These should match NS records from DNS. Mismatches indicate:
- Recent migration (propagation delay)
- Misconfiguration
- Potential hijacking
GDPR Impact
Post-2018, most registrars redact contact information. The RDAP summary provides the registrar’s abuse contact (abuse_email, abuse_phone) but individual registrant details are typically not available.
In practice this means RDAP responses contain registrar data, not registrant (owner) data. abuse_email/abuse_phone are the registrar’s abuse desk — not the domain owner’s contact — and must never be presented as the registrant. One case looks like an exception and is not: some registries let an organisation act as its own registrar (Nominet “tags” under .uk, for example, so bbc.co.uk shows nominet.admins@bbc.co.uk). The field is still the sponsoring registrar’s published contact; that the registrar and the registrant are the same organisation is a fact about the registration, not a registrant lookup. There is also no reverse-WHOIS: neither DataPulse nor public RDAP can search registrations by registrant email, name, or organization. For the full explanation and alternative approaches, see datapulse_help(topic="registrant_lookup").
TLD-Specific Notes
.com / .net (Verisign)
- Full RDAP support
- Most complete data for major registrars
.org (PIR)
- Good data quality
.io (Identity Digital)
- Often heavily redacted
- Privacy services common
.co.uk (Nominet)
- Standard RDAP format
- “Data validation” indicates verified registrant
.eu (EURid)
- Very restricted
- Often requires web lookup
TLDs without RDAP
Some ccTLDs have no RDAP server; .de (DENIC) is the best-known example — DENIC publishes only a web WHOIS. datapulse_live_rdap returns an error for these (“No RDAP servers found for …”).
Important: This is a limitation of the RDAP protocol, not of DataPulse data coverage. DataPulse maintains one of the most comprehensive domain databases available (400M+ domains across all TLDs including ccTLDs). Domain search (datapulse_dns_searchlabels), DNS history (datapulse_dns_dphistory), infrastructure similarity (datapulse_dns_dptechsim), and cluster analysis (datapulse_dns_neighborhood) all cover ccTLD domains. Only live RDAP registration lookups are affected by missing RDAP servers.
For how that corpus is built — the PSL+1 unit of analysis, full PSL registry coverage
(ICANN, non-ICANN, and ccTLD registries), wildcard-aware collection, discovery sources, and
the active-and-functioning quality gate that decides what is admitted — see
datapulse_help(topic="methodology").
Generated from the live server (DataPulse MCP 1.0.0) on October 1, 2026. Your AI assistant reads this page by calling datapulse_help(topic="rdap").