A domain expiry is not a cliff. It is a sequence of timed states, each with a different cost and a different chance of recovery, and the whole sequence is driven by one date published in the registry. Knowing how to read that date — and which of the two dates you are looking at — is the difference between a five-minute renewal and a redemption fee.
How do I look up the expiry date?
For a gTLD like .com, query the registry's WHOIS server directly. The field you want is Registry Expiry Date.
whois -h whois.verisign-grs.com "domain github.com"
# Updated Date: 2024-09-07T09:16:32Z
# Creation Date: 2007-10-09T18:20:50Z
# Registry Expiry Date: 2026-10-09T18:20:50Z
# Registrar: MarkMonitor Inc.
# Domain Status: clientTransferProhibited https://icann.org/epp#clientTransferProhibitedRDAP gives you the same information as JSON, which is far easier to script against. The bootstrap service at rdap.org routes your query to whichever registry runs that TLD, so you do not need to know the endpoint in advance.
curl -sSL https://rdap.org/domain/github.com | jq '.events'
# [
# { "eventAction": "registration", "eventDate": "2007-10-09T18:20:50Z" },
# { "eventAction": "expiration", "eventDate": "2026-10-09T18:20:50Z" },
# { "eventAction": "last changed", "eventDate": "2024-09-07T09:16:32Z" }
# ]
# Just the expiry:
curl -sSL https://rdap.org/domain/github.com \
| jq -r '.events[] | select(.eventAction=="expiration") | .eventDate'Registrar date or registry date — which one is real?
You will often see two expiry values for the same domain, and they will not match exactly. The registry holds the authoritative record; the registrar keeps its own copy for billing. Query github.com at both levels and the difference is plain:
| Source | Field name | Example value | What it governs |
|---|---|---|---|
| Registry (Verisign) | Registry Expiry Date | 2026-10-09T18:20:50Z | The actual lifecycle — grace, redemption, deletion |
| Registrar (MarkMonitor) | Registrar Registration Expiration Date | 2026-10-09T00:00:00Z | When the registrar bills you and stops the service |
The gap is usually hours, occasionally a day, and it exists because registrars normalise to midnight or to their own billing timezone. When they disagree, plan against the earlier of the two. Note also that .com and .net are *thin* registries: the registry record carries dates, status codes, nameservers, and the sponsoring registrar, and nothing about the registrant. Contact details live only at the registrar — which is why a registry lookup will never tell you whose credit card is on file.
What actually happens when a domain expires?
For gTLDs, ICANN policy defines the phases below. Exact durations at the first stage are set by your registrar, so treat those numbers as typical rather than guaranteed; the redemption and pending-delete windows are fixed by policy.
| Phase | Typical duration | Domain status | Recovery |
|---|---|---|---|
| Auto-renew / registrar grace | Registrar-defined, often up to ~45 days | autoRenewPeriod | Renew at normal price |
| Redemption Grace Period | 30 days | redemptionPeriod | Restore, plus a redemption fee that is typically far above renewal price |
| Pending Delete | 5 days | pendingDelete | None — the outcome is fixed |
| Released | Immediate on drop | No record | Anyone may register it, including drop-catch services |
The part that surprises people is that the site usually breaks *before* any of the scary phases. Registrars commonly pull the domain's delegation or repoint the nameservers to a parking page during the grace period, which means DNS stops resolving days before you are technically at risk of losing the name. That looks like a total outage: the web site is gone and mail bounces immediately.
- Check the delegation. If the NS Record Lookup shows registrar parking nameservers instead of yours, the registrar has taken over the delegation.
- Check what resolvers return. A domain removed from the zone answers
NXDOMAIN; a broken delegation typically answersSERVFAIL. SERVFAIL vs NXDOMAIN explains what each one implicates. - Expect mail to fail hard. With no MX records resolvable, sending servers bounce rather than queue in many configurations. Recovery is not instant either — see Mail Bouncing After a DNS Change.
- Expect TLS to fail too. ACME renewals validate over DNS or HTTP against the domain. An expired domain means no renewal, so a certificate problem follows within weeks — check dates with the SSL Certificate Checker.
Read the status codes rather than guessing which phase you are in. They appear as Domain Status lines in WHOIS and in the status array in RDAP, and they are unambiguous.
curl -sSL https://rdap.org/domain/example.com | jq '.status'
# Healthy, locked against unauthorised changes:
# [ "client delete prohibited", "client transfer prohibited", "client update prohibited" ]
# In trouble:
# [ "redemption period" ] → restorable, but expensive
# [ "pending delete" ] → not recoverableHow do I stop this happening again?
Two settings prevent almost every domain loss, and neither takes long to fix.
- Turn on auto-renew and verify the payment method is current. Auto-renew fails silently when a card expires — and cards expire on a schedule that has nothing to do with your domain. Check the stored card as part of the same task.
- Point the registrant email at a mailbox that does not depend on the domain. This is the classic failure: renewal reminders go to
[email protected], the domain expires, DNS stops resolving, mail stops being delivered, and every subsequent warning bounces. Use an address on a different domain. - Keep the registrant contact verifiable. Registrars are required to verify registrant contact details for gTLD registrations, and an unverified or bouncing address can lead to suspension entirely separately from expiry. A dead contact address is a live risk.
- Enable the registrar lock.
clientTransferProhibitedandclientUpdateProhibiteddo not prevent expiry, but they do prevent an unauthorised transfer while you are distracted by one. - Monitor externally. Registrar dashboards are the thing you forget to open. Put the expiry date in a calendar you actually read, and script a check that alerts you independently.
That last one is a few lines of shell. RDAP makes it easy because the date is already ISO-8601:
for d in example.com github.com; do
exp=$(curl -sSL "https://rdap.org/domain/$d" \
| jq -r '.events[] | select(.eventAction=="expiration") | .eventDate')
printf '%-24s %s\n' "$d" "${exp:-unavailable}"
done
# example.com 2027-08-13T04:00:00Z
# github.com 2026-10-09T18:20:50ZWhat about ccTLDs?
None of the ICANN lifecycle policy applies to country-code TLDs. Each ccTLD registry sets its own rules, and they differ substantially — some have no redemption period at all, some quarantine names for months, some do not publish expiry dates in WHOIS at all. Several ccTLDs also have no RDAP endpoint in the IANA bootstrap registry, so rdap.org cannot route your query and you must use the registry's own WHOIS or web lookup. Read the registry's current policy for the specific TLD rather than assuming .com behaviour.
For the mechanics of the two protocols and when each one is the right tool, see RDAP vs WHOIS, or run the domain through our WHOIS Lookup.