Why .dev, .app, .page (and 40+ Other TLDs) Don't Respond to WHOIS
Source: Dev.to
The Investigation
First thought: maybe Google blocks WHOIS queries for their domains? Let’s check the WHOIS server for .dev:
whois -h whois.iana.org dev
Output (trimmed):
domain: DEV
organisation: Charleston Road Registry Inc.
...
whois:
status: ACTIVE
remarks: Registration information: https://www.registry.google
Notice the empty whois: field—there’s no WHOIS server for .dev.
Google owns 40+ TLDs and none of them have a WHOIS server, e.g.:
.app, .page, .new, .google, .youtube, .android, .chrome, .zip, .mov, .dad, .phd, .prof, .meme, .foo, .nexus, .rsvp, .fly, .ing, .boo, .channel…
You can verify any TLD on IANA’s root database – look for the “WHOIS Server” field. This isn’t a bug; it’s by design.
Why No WHOIS?
Google launched these TLDs after 2012, when ICANN began promoting a new protocol called RDAP (Registration Data Access Protocol).
The main problem with WHOIS is the lack of a standard format—registrars return different text, field names, and date formats.
RDAP fixes this:
- JSON responses – no more parsing random text formats, just
json.Unmarshal. - Standard field names – expiration date is always
eventAction: "expiration". - RESTful API – a simple GET request works with any HTTP client.
In January 2025, ICANN officially sunset WHOIS for gTLDs. RDAP is now the standard.
How to Check Domain Expiration with RDAP
If you want to monitor domain expiration or build a lookup tool, RDAP is the way to go. Below is a working Go example:
package main
import (
"encoding/json"
"fmt"
"net/http"
"os"
"strings"
"time"
)
func main() {
domain := "google.dev"
if len(os.Args) > 1 {
domain = os.Args[1]
}
expiry, err := getExpiry(domain)
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
days := int(time.Until(expiry).Hours() / 24)
fmt.Printf("%s expires %s (%d days)\n", domain, expiry.Format("2006-01-02"), days)
}
func getExpiry(domain string) (time.Time, error) {
tld := domain[strings.LastIndex(domain, ".")+1:]
// RDAP endpoints (from IANA bootstrap file)
endpoints := map[string]string{
"com": "https://rdap.verisign.com/com/v1/domain/",
"net": "https://rdap.verisign.com/net/v1/domain/",
"org": "https://rdap.publicinterestregistry.org/rdap/domain/",
"dev": "https://pubapi.registry.google/rdap/domain/",
"app": "https://pubapi.registry.google/rdap/domain/",
"io": "https://rdap.nic.io/domain/",
}
endpoint, ok := endpoints[tld]
if !ok {
return time.Time{}, fmt.Errorf("unknown TLD: %s", tld)
}
resp, err := http.Get(endpoint + domain)
if err != nil {
return time.Time{}, err
}
defer resp.Body.Close()
var data struct {
Events []struct {
Action string `json:"eventAction"`
Date string `json:"eventDate"`
} `json:"events"`
}
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
return time.Time{}, err
}
for _, e := range data.Events {
if e.Action == "expiration" {
return time.Parse(time.RFC3339, e.Date)
}
}
return time.Time{}, fmt.Errorf("no expiration date found")
}
Run it:
$ go run main.go google.dev
google.dev expires 2025-09-14 (252 days)
$ go run main.go github.com
github.com expires 2026-10-09 (642 days)
Clean JSON, standard fields, no parsing nightmares.
RDAP Coverage
All gTLDs (.com, .org, .dev, etc.) support RDAP. Most ccTLDs (.uk, .de, .ru, etc.) still rely on WHOIS, but coverage is growing each year.
The full list of RDAP endpoints is in IANA’s bootstrap file; this is where you get the correct endpoint for any TLD.
Key Takeaways
- New TLDs (especially Google’s) have no WHOIS server – RDAP only.
- ICANN deprecated WHOIS in 2025 – RDAP is the future.
- RDAP returns JSON – no more parsing 50 different date formats.
Don’t want to handle RDAP yourself? Check out upsonar.io/docs/domain-expiry – it monitors domain expiration and alerts before they expire. Free tier available.
What TLDs are you monitoring? Hit any weird edge cases?