How we check availability
Registration and purchasability are genuinely different facts.
Everything below is generated from the live configuration this site runs on, and every claim comes with the command to check it yourself.
A registry can tell you, definitively, whether a domain has a registration record. That is the question RDAP answers, and we ask the registry itself rather than a middleman.
It cannot tell you whether you can buy it. A domain with no registration record can still be priced as a premium name, reserved by the registry, or simply not carried by your registrar. Those are different facts from different systems, and anything that shows you one number for both is guessing about at least one of them.
Step 1 — find the registry.
IANA publishes the map of every top-level domain to its RDAP
server at
data.iana.org/rdap/dns.json.
We cache it and re-read it daily. For
.dev it resolves to:
https://pubapi.registry.google/rdap/
Step 2 — ask it about a domain. The HTTP status
code is the answer: 200 means a registration
record exists, 404 means it does not.
# The domain you picked -- expected: HTTP 404
curl -sI -H 'Accept: application/rdap+json' \
https://pubapi.registry.google/rdap/domain/h1xnzwjttcjz18.dev | head -1
# The control: nic.dev, which we expect to answer HTTP 200
curl -sI -H 'Accept: application/rdap+json' \
https://pubapi.registry.google/rdap/domain/nic.dev | head -1
Both halves matter. A server that answered 200 to
everything would report every domain as taken, and a check that
only ever asks about one domain cannot tell that apart from a
working one. We run the pair.
h1xnzwjttcjz18.dev was generated for
this page load and will be different next time. Fourteen random
characters is about 1020 possibilities against a DNS of
well under a billion names — if it ever comes back
200, something far more interesting than a
documentation bug has happened.
The same request in PHP, Python, Ruby, C# and JavaScript
No API key, no account, no registration. RDAP is an open
standard and these are public endpoints. Every sample below
queries h1xnzwjttcjz18.dev —
change that one string to ask about anything else.
$ch = curl_init('https://pubapi.registry.google/rdap/domain/h1xnzwjttcjz18.dev');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Accept: application/rdap+json'],
]);
curl_exec($ch);
$code = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// 200 = registered, 404 = no registration record
echo $code === 404 ? 'no registration record' : 'registered';
import urllib.request, urllib.error
url = 'https://pubapi.registry.google/rdap/domain/h1xnzwjttcjz18.dev'
req = urllib.request.Request(url, headers={'Accept': 'application/rdap+json'})
# The 404 arrives as an exception, not a return value -- urllib raises on
# any 4xx, so the "available" answer has to be caught rather than read.
try:
with urllib.request.urlopen(req) as r:
print('registered', r.status)
except urllib.error.HTTPError as e:
print('no registration record' if e.code == 404 else f'unexpected {e.code}')
require 'net/http'
require 'uri'
uri = URI('https://pubapi.registry.google/rdap/domain/h1xnzwjttcjz18.dev')
req = Net::HTTP::Get.new(uri, 'Accept' => 'application/rdap+json')
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
# Net::HTTP returns the status as a STRING, not an integer -- '404', not 404.
puts res.code == '404' ? 'no registration record' : 'registered'
using System;
using System.Net;
using System.Net.Http;
using var http = new HttpClient();
http.DefaultRequestHeaders.Add("Accept", "application/rdap+json");
var res = await http.GetAsync("https://pubapi.registry.google/rdap/domain/h1xnzwjttcjz18.dev");
// Do NOT call EnsureSuccessStatusCode() here. HttpClient throws only on
// transport failures, so the 404 arrives as an ordinary response -- and
// that 404 IS the answer you came for.
Console.WriteLine(res.StatusCode == HttpStatusCode.NotFound
? "no registration record"
: "registered");
const res = await fetch(
'https://pubapi.registry.google/rdap/domain/h1xnzwjttcjz18.dev',
{ headers: { Accept: 'application/rdap+json' } }
);
// fetch() does not reject on 4xx, so no try/catch is needed -- but note that
// from a BROWSER this is a cross-origin request and most registry RDAP
// servers do not send CORS headers. Run it server-side (Node, Deno, Bun).
console.log(res.status === 404 ? 'no registration record' : 'registered');
One courtesy if you build on this: registries publish these
endpoints as a compliance obligation, not as a
high-throughput API, and several attach terms asking you not
to hit them with high-volume automated processes. Honour
Retry-After on a 429, keep
concurrency per registry in the low single digits, and cache
what you get.
There are three ways to ask, and we use them in a fixed order.
| Tier | The question it actually answers |
|---|---|
DNS |
Is this name pointed at nameservers? One UDP packet, fast enough to run across hundreds of thousands of candidates — and blind in one specific way, below. |
RDAP |
Does the registry hold a registration record? Structured JSON, defined status codes, no parsing guesswork. Used whenever the extension has one. |
WHOIS |
The same question as RDAP, asked the way we asked it in 1982. Last resort, and confirm-only. |
WHOIS runs only when RDAP structurally cannot answer — that is, when the extension has no RDAP server in the IANA bootstrap file at all. It is not a fallback for RDAP having a bad day. If a registry's RDAP server is slow or throwing errors we back off and retry it; we do not quietly switch to a weaker source and keep the same confidence badge.
It is also confirm-only. WHOIS never produces a verdict here on its own — it confirms or contradicts a DNS “available”, which is why you will not find it in the list of check methods further down. That list is what you can choose; WHOIS is something the checker reaches for on your behalf.
Why it is last: RDAP answers with a status code.
WHOIS answers with free text and no schema — RFC 3912 defines
the transport (open TCP port 43, send a line, read until the server
hangs up) and says nothing whatsoever about what comes back. So
“is this domain free?” degrades into matching phrases
like No match, NOT FOUND or
Status: free, which differ per registry and can change
without notice. That is a fine last resort and a terrible primary
source: a parser that guesses wrong reports a registered domain as
available, which is the one error that costs you money.
Second-level extensions always land here. IANA
bootstraps .uk, not .co.uk, so for
extensions like .co.uk or .com.au RDAP has
nothing to route to and every answer falls through by construction.
.dev — the extension
in the example above — RDAP answers, so WHOIS is never
consulted.
Shown next to every Available result. These descriptions are read from the same code that assigns the grade, so they cannot drift.
| Grade | What it means |
|---|---|
| High | High confidence — the registry itself was asked and reported no registration for this domain. Note this says nothing about PRICE: a domain can be unregistered and still be sold as a premium name for far above the base rate. |
| Medium | Medium confidence — DNS says available and a second opinion was requested, but the registry errored, rate-limited, or answered unclearly. The DNS result stands unverified. |
| Low | Low confidence — this rests on DNS alone, and no registry check was ever attempted. DNS cannot tell an unregistered domain from a registered-but-parked one, so treat this as a lead, not a fact. Re-check with RDAP before acting on it. |
-
Price. A domain with no registration record can
still be a premium name. We have measured one at
$500.20that RDAP correctly reported as unregistered. - Registry reservations. Some names are held back and never released. They have no registration record either, so they look identical to a free domain over RDAP.
- Your registrar's inventory. Registrars choose what to sell. One declining to sell you a name is not evidence that it is registered — we have seen a registrar report "registered already" for a domain the registry itself says has no record.
This is the boundary of what a registration lookup can establish, not a gap in our checking. The definitive answer on price and purchasability is the checkout page of a registrar that carries the extension.
A DNS check is one UDP packet and it is fast enough to run across hundreds of thousands of candidates. It answers a different question: is this name delegated to nameservers?
A domain someone registered this morning and never pointed anywhere is absent from DNS and looks free. That blind spot is the one that costs money — it is the failure where you go to buy a domain and find it taken. Only a registry lookup sees registration itself, which is why DNS-only answers are graded Low and expire quickly.
Live values from this site's configuration.
| Answer for | Re-checked after |
|---|---|
.com |
24 hours |
.io |
12 hours |
.dev |
48 hours |
DNS-only "available" |
1 hours |
Separately, an Available result older than 7 days is downgraded a confidence grade. That is a different question from the cache lifetime above — one asks "is it worth spending a lookup to re-check this?", the other asks "should you trust this enough to go spend money?"
We track 591 extensions. 502 of them can be routed to a registry RDAP server via the IANA bootstrap file; the remaining 89 are answered by DNS alone, backed up by WHOIS where one is reachable, and carry the lower confidence grade that implies.
Check methods you can choose:
dns— DNS Checkrdap— RDAP (recommended)