DEV Community

Cover image for Why .dev, .app, .page (and 40+ Other TLDs) Don't Respond to WHOIS
Serg Petrov
Serg Petrov

Posted on

Why .dev, .app, .page (and 40+ Other TLDs) Don't Respond to WHOIS

I was building upsonar.io - it monitors uptime, SSL certificates, and domain expiration. When I got to domain expiry alerts, I hit a wall.

Checked .com, .org, .net - worked fine. Then I tried google.dev.

Connection refused.

The Investigation

First thought: maybe Google blocks WHOIS queries for their domains? Let me check the WHOIS server for .dev:

$ whois -h whois.iana.org dev
Enter fullscreen mode Exit fullscreen mode

Output (trimmed):

domain:       DEV
organisation: Charleston Road Registry Inc.
...
whois:

status:       ACTIVE
remarks:      Registration information: https://www.registry.google
Enter fullscreen mode Exit fullscreen mode

See that empty whois: field? There's no WHOIS server for .dev at all.

Turns out, Google owns 40+ TLDs and none of them have a WHOIS server:

.app, .page, .new, .google, .youtube, .android, .chrome, .zip, .mov, .dad, .phd, .prof, .meme, .foo, .nexus, .rsvp, .fly, .ing, .boo, .channel...

You can check 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 started pushing a new protocol called RDAP (Registration Data Access Protocol).

The main problem with WHOIS? No standard format. Every registrar returns different text, different field names, different 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", not "Expiry Date" vs "Registry Expiry Date" vs "paid-till"
  • RESTful API - just a 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 domain expiration lookup tool, RDAP is the way to go. Here's working Go code:

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"`
    }

    json.NewDecoder(resp.Body).Decode(&data)

    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")
}
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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 every 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

  1. New TLDs (especially Google's) have no WHOIS server - RDAP only
  2. ICANN deprecated WHOIS in 2025 - RDAP is the future
  3. RDAP returns JSON - no more parsing 50 different date formats

Don't want to deal with RDAP yourself? upsonar.io/docs/domain-expiry - monitors domain expiration and alerts before they expire. Free tier available.


This is part of the Building a Monitoring Tool in Go series. Follow for more.

What TLDs are you monitoring? Hit any weird edge cases?

Top comments (0)