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 | One of query / domain_hash | — | 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. |
domain_hash | One of query / domain_hash | — | Read the stored row for this hash instead of looking it up: the domain_hash a datapulse_live_rdap_bulk receipt gave for an item (submitted[].domain_hash). Returns the envelope with domain_hash beside it (no sent or type); a hash with no row is a not-found error. force does not apply. |
force | No | false | Bypass every cache and force a fresh live lookup via the Scrape API. |
Lookup Strategy
For domain queries the Scrape API answers from the first of three sources that has the domain, and the envelope’s source names which one did:
cache: the Scrape API’s own stored result, inside its deduplication window.datapulse: the DataPulse crawl database. Near-instant;researchdateis that crawl’s date and can be weeks old.live: a worker queried the registry for this request.
force: true skips cache and datapulse. All three 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
Every source returns the same compact summary. Every response uses the envelope {query, source, datetime, results} from the Scrape API plus this tool’s sent, type ("domain" or "ip") and submitted_domain. query is the Scrape API’s request path with the looked-up name (/rdap/example.com):
{
"query": "/rdap/example.com",
"source": "datapulse",
"sent": "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",
"expiration_date": "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 |
expiration_date | 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. The expiry field is expiration_date here, in the overview’s rdap block and summary, and in datapulse_dns_rdap_history — one name everywhere, with an underscore, beside registrationdate and ianaid without one (the DataPulse API’s own field names). Scrape API builds before 2026-10-07 answered expirationdate for some lookups.
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
A lookup the registry or RIR could not answer is not a tool error: the tool returns the normal envelope, and the observation in results[] carries an error field with the RDAP server’s own text instead of registration data:
{"query": "/rdap/datapulse-nonexistent-7f3a9c.com", "source": "live", "datetime": "2026-10-06T21:01:08Z",
"results": [{"name": "datapulse-nonexistent-7f3a9c.com", "researchdate": "2026-10-06T21:01:08Z",
"error": "# Error: RDAP server returned 404, object does not exist."}],
"sent": "datapulse-nonexistent-7f3a9c.com", "type": "domain"}
example.de comes back the same way with "error": "# Error: No RDAP servers found for 'example.de'". Check results[].error before reading any other field. A tool error (with the API’s HTTP status and body) means the request itself was refused or failed: invalid input (a CIDR, a reserved address, a single label), authentication, or the service being unavailable. Common causes of a results[].error:
- 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. Read each result back with datapulse_live_rdap(domain_hash=...), using the item’s submitted[].domain_hash: that reads the stored row without a new lookup. datapulse_live_rdap(query=...) also finds a finished bulk result in the Scrape API’s cache, but may answer from the DataPulse database instead.
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 |
client transfer prohibited | Transfer locked | Standard protection |
client delete prohibited | Delete locked | Protected |
client update prohibited | Update locked | Protected |
server transfer prohibited | Registry lock | Enhanced protection |
server hold | Suspended by registry | Domain has issues |
client hold | Suspended by registrar | Domain has issues |
redemption period | Expired, pending delete | Domain may be dropped |
pending delete | 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) |
expiration_date | 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 7, 2026. Your AI assistant reads this page by calling datapulse_help(topic="rdap").