Data Sources & Methodology
Where our data comes from, how it's verified, and how often it's updated.
Primary sources
- IANA Root Zone Database
- https://www.iana.org/domains/root/db — The authoritative table of all delegated TLDs, their types, and sponsoring organisations. Updated by IANA as delegations change.
- IANA Delegated TLD List
- https://data.iana.org/TLD/tlds-alpha-by-domain.txt — Plain-text list of all currently delegated TLD labels. Includes a version header with date. Updated weekly.
- IANA Per-TLD Delegation Records
https://www.iana.org/domains/root/db/{tld}.html— Individual pages for each TLD with registry information (WHOIS, RDAP, registration services URL), delegation history, and reference documents.
Registrar pricing sources
Price comparison data is kept fully separate from IANA metadata (data/tlds.json vs data/prices.json). Every price figure below is published by the source itself — we never estimate, convert, or invent prices. Sources without a value are shown as "Price unavailable".
First-party reads — labelled Verified
These sources are the registrars' own published price lists, read directly by our daily sync. A price from here is stamped with the moment we read it, and that timestamp is the only thing that can make a price "recently verified".
- Porkbun API — official, no authentication
- Porkbun API v3 — pricing endpoint — registration, renewal and transfer list prices in USD for every TLD Porkbun sells. Documented as a public endpoint by Porkbun; fetched daily.
- Dynadot price list
- dynadot.com/domain/prices — Dynadot's published catalogue, read from the server-rendered page payload. A struck original price is treated as a promotion, exactly as the page presents it.
- Gandi price list
- gandi.net/domain/tld — the official per-extension price table (creation, transfer, renewal). Fetched one letter prefix at a time with a delay between requests; Gandi's robots.txt allows these pages.
- Hover price list
- hover.com/domain-pricing — the published registration, renewal and transfer prices carried in the page's own data payload.
- IONOS price list
- ionos.com/domains/domain-name-prices — first-year welcome price, existing-customer price, standard renewal fee and transfer fee. IONOS's bundle price is never used, because it is not a single-domain price.
Openly licensed datasets — labelled Snapshot
These are third-party datasets. They are downloaded fresh every day, but the dates inside them are the dataset's own observation dates, which can be weeks old. They are never labelled "verified", however recently we downloaded them.
- Best Domain Registrars — licence: CC BY 4.0
- best-domain-registrars.com/data — per-registrar price table plus a verification taxonomy that distinguishes figures the publisher verified, figures confirmed against a pricing model, and placeholder samples. We reuse that taxonomy rather than flattening it: rows marked as samples (currently Squarespace) are dropped, and model-confirmed rows are classified Modelled — but they only win when no better-evidenced copy exists for the same registrar and extension. Cloudflare, for example, is currently covered by a dated snapshot that outranks the model row, so no Modelled rows are published today. Rows the publisher verified stay Snapshot here, because that attestation is theirs — not a read we performed. Attribution:"Price data by Best Domain Registrars".
- Pikkly open data — licence: CC BY 4.0
- pikkly.dev/data — daily-rebuilt JSON covering 6 registrars. Rows sourced from dated community dumps use the dump date as their observation date, not the rebuild time. Attribution:"Price data by Pikkly".
- Open Domain Data — tld_pricing — licence: CC BY 4.0
- opendomaindata.org — monthly snapshot of register/renew/transfer prices normalised to USD across 7 registrars. Citation: Open Domain Data (2026). tld_pricing, opendomaindata.org. Records carry their own check dates, which can be weeks old — anything past 30 days is labelled "stale".
Why some registrars have no first-party price
A registrar appears as Snapshot only when we could not read its own price list. The reasons are concrete, not a lack of effort:
- Cloudflare Registrar sells at cost and publishes no static per-TLD price list. Its prices only appear through an interactive search tool rendered in the browser, and the JSON endpoint that feeds that tool answers a plain server-side request with an HTTP 403 bot challenge. There is therefore no page we may legally read, so its figures can only come from a licensed dataset.
- Namecheap and Spaceship answer a plain server-side request with HTTP 403 (bot protection). Reading them would mean executing JavaScript or evading the challenge, which this project does not do. Their official APIs require an account: Namecheap's additionally needs an API key bound to an allow-listed IP.
- GoDaddy publishes no machine-readable price list either; its figures come from the Best Domain Registrars dataset, which is why they are labelledSnapshot even when they are only days old.
Those rows keep their honest date and are never promoted to Verified. They also never win the "cheapest" slot on a comparison table while a current quote exists — when a stale quote is cheaper, the table lists it underneath the ranked price with a ↓ marker, so an older lower price is disclosed rather than hidden.
Placeholder pricing we refuse to dress up
Squarespace Domains appears in both open datasets, but Best Domain Registrars marks its figures as sample — the publisher's own read of Squarespace's pricing was blocked, so those numbers are placeholders. Open Domain Data repeats the same figures without that warning. We keep the rows so you can see the registrar exists, but they are published as Unverified: no verification date, no freshness band, and they can never be labelled "cheapest". The same rule applies to any registrar added toUNTRUSTED_REGISTRAR_PRICES.
How a price is dated
The old dataset collapsed three different questions into one date, which is why prices looked fresher than they were. Each offer now carries three separate timestamps:
| Field | Question it answers |
|---|---|
source_fetched_at | When did we download this source? Says nothing about how old the numbers are. |
price_observed_at | When does the source say it observed this price? |
price_verified_at | When did we read this figure from the registrar itself? Empty for snapshots. |
The date shown next to a price is always the evidence date — the verification date for a first-party read, otherwise the source's own observation date — never the download date.
Is the data current right now?
A successful workflow is not the same thing as a refreshed price. Each source therefore reports three separate timestamps — when we last attempted it, when it lastsucceeded, and the newest price evidence it actually carries — plus whether this run obtained anything newer than the previous one.
Coverage: incomplete. 1 source downloaded successfully but carries no evidence newer than 30 days (opendomaindata); 1 source did not deliver usable data (namecheap); no current quote exists for cloudflare, namecheap, spaceship, squarespace — their figures are historical snapshots.
| Source | How read | Last successful fetch (UTC) | Newest price evidence | Oldest price evidence | New evidence this run | Published rows | State |
|---|---|---|---|---|---|---|---|
| Porkbun API | First-party | 2026-10-25 | 2026-10-25 (17d) | 2026-10-25 | Yes | 540 | Current |
| Dynadot pricing page | First-party | 2026-10-25 | 2026-10-25 (17d) | 2026-10-25 | Yes | 622 | Current |
| Gandi price list | First-party | 2026-10-25 | 2026-10-25 (17d) | 2026-10-25 | Yes | 759 | Current |
| Hover pricing page | First-party | 2026-10-25 | 2026-10-25 (17d) | 2026-10-25 | Yes | 497 | Current |
| IONOS domain price list | First-party | 2026-10-25 | 2026-10-25 (17d) | 2026-10-25 | Yes | 427 | Current |
| Namecheap API | First-party — kept-previous | — | — | — | No | 0 | No dated data |
| Best Domain Registrars open pricing data | Snapshot | 2026-10-25 | 2026-10-21 (21d) | 2026-09-02 | No | 268 | Current |
| Pikkly open data | Snapshot | 2026-10-25 | 2026-10-24 (18d) | 2026-08-04 | No | 398 | Current |
| Open Domain Data | Snapshot | 2026-10-25 | 2026-08-19 (84d) | 2026-05-12 | No | 38 | Frozen upstream |
Sources that delivered nothing this run. Namecheap API — kept-previous (missing env: NAMECHEAP_API_USER, NAMECHEAP_API_KEY, NAMECHEAP_USERNAME). Any rows they previously contributed are kept as-is and are never re-dated, so a failed or not-yet-configured source cannot make old prices look fresh.
Frozen upstream snapshots. A source can be downloaded perfectly every day and still contain nothing new: its own observation dates do not move. The sources marked Frozen upstream above are exactly that — the fetch succeeds, the file is re-downloaded, and the prices inside it are unchanged because the publisher has not re-read the registrar. Those rows are labelled Stale everywhere on the site and can never take a “cheapest” slot.
No current quote. For cloudflare, namecheap, spaceship, squarespace every published figure is older than the stale threshold, so their prices are shown as historical references and are excluded from cheapest-price ranking.
Verification and freshness are two different things
| Badge | Meaning |
|---|---|
| Verified | Read from the registrar's own published price list during a sync run. |
| Snapshot | From an openly licensed dated dataset, accurate as of that dataset's observation date. |
| Modelled | Derived from a documented pricing policy rather than a published price list. |
| Unverified | No trustworthy observation date, or flagged as placeholder data upstream. |
| Recently verified | Evidence is at most 7 days old. Only first-party reads can earn this label. |
| Verification not recent | Evidence is 8–30 days old. |
| Stale | Evidence is more than 30 days old — a historical reference, not a current quote. |
When two sources disagree about the same registrar and extension, the better-verified copy wins — before age is considered. A snapshot downloaded this morning cannot displace a first-party read from three weeks ago.
Pricing data pipeline
- Daily fetch — GitHub Actions runs
npm run sync:prices. - Validation — rows are rejected for unknown TLDs (anything not in the IANA catalog), invalid or out-of-range prices, missing USD currency, invalid URLs, duplicates, and — critically — a "verified" claim with no verification date behind it.
- Failure guards — a source that errors, returns zero valid rows, or shrinks by more than 50% keeps its previous rows untouched; if every source fails,
data/prices.jsonis left byte-for-byte unchanged and the run fails. - Merge — one offer per registrar+TLD, ranked by verification tier, then evidence age, then source priority.
- Freshness — recomputed from each offer's evidence date on every build, so a rebuild can never re-date an old price.
- Report — every run writes
data/price-sync-report.json(machine-readable) anddata/price-sync-report.md(human-readable), stating how many published prices are first-party reads, how many are snapshots, and the oldest evidence in the dataset. - Commit only on change — if the dataset is unchanged, nothing is committed, so no rebuild is triggered.
Supplemental sources (verified per-TLD)
- Registry websites — Official registration policy pages (linked from IANA's "URL for registration services").
- ICANN Registry Agreements — For gTLDs, the base agreement and any amendments.
- IANA Reports — Delegation/redelegation reports linked from per-TLD pages.
Editorial notes (registration restrictions, practical guidance) are researched from registry policies and cited explicitly. Unverified claims are marked as such.
Data processing pipeline
- Weekly sync — Automated script fetches both IANA sources every Monday (GitHub Actions).
- Validation — Parsers reject malformed data, duplicates, or implausibly small datasets.
- Merge — Delegated list (source of truth for "active" TLDs) joined with Root Zone DB rows (type, manager).
- Detail enrichment — For TLDs without a manager in the DB table, the per-TLD delegation page is fetched for WHOIS/RDAP/URL/dates.
- Normalisation — Types mapped to canonical values; IDN labels decoded to Unicode.
- Change detection — Added/removed TLDs logged; meta.json updated with timestamps and counts.
- Build — Astro SSG generates static HTML for all pages from the JSON dataset.
Data quality levels
| Level | Meaning |
|---|---|
| Verified | Type, manager, and delegation status confirmed against IANA sources. |
| Verified + Editorial | Verified + human-reviewed editorial profile (description, restrictions, citations). |
| Incomplete | Missing manager info (IANA shows "Not assigned") and no verified detail page data. |
Known upstream change: IANA's 2026 page redesign
IANA redesigned both the Root Zone Database index page and the individual delegation records during 2026. Two things changed that affect this site:
- Type taxonomy. The index page previously published six type values (generic, generic-restricted, country-code, sponsored, infrastructure, test). It now publishes three: Generic, Country Code and Special Use. As a result
.gov,.edu,.museum,.aero,.post,.biz,.nameand.pronow appear as Generic, and.arpaas Special Use. We follow what IANA publishes and record the change here instead of inferring the old labels. - Delegation status column. The index page now publishes a status per TLD (Active, Retired, Reserved, Eligible). The sync script cross-checks the count of Active rows against the authoritative delegated list and logs a warning if they diverge, but the delegated list still decides which records exist.
The parsers in src/lib/iana.ts support both the legacy and the current layouts, so a re-sync is stable regardless of which version IANA serves.
Update frequency
- TLD metadata: automated weekly — Every Monday ~06:30 UTC (after IANA's typical update window).
- Pricing: automated daily — GitHub Actions fetches all pricing sources every day; commits only when the dataset actually changed.
- Manual trigger — Available via GitHub Actions workflow dispatch for both pipelines.
- Emergency — If a major delegation change occurs, we can re-run immediately.
What we do NOT do
- We do not bypass authentication, anti-bot controls, or terms-of-use restrictions on any registrar's website. Where we read a registrar's published price list we use a plain HTTP GET with an identifying user agent, at a low rate, and only on paths its
robots.txtallows. - We do not scrape quotes, carts, or availability checks for individual domain names.
- We do not guess prices: if a source doesn't publish a figure, we show "Price unavailable".
- We do not convert currencies or infer a price from another extension's price.
- We do not let affiliate relationships (none exist today) influence which offer is labelled cheapest — rankings use published prices only.
- We do not guess or infer registration rules — only cite verified sources.
- We do not track domain ownership, WHOIS history, or aftermarket data.
Licensing & attribution
IANA data is public domain / freely redistributable per IANA's legal notices. Our compiled dataset, editorial content, and code are proprietary. You may link to our pages freely. For bulk data use, contact us.
Third-party pricing datasets are reused under their own licences, with attribution shown here and on every detail page:
- Best Domain Registrars — CC BY 4.0. "Price data by Best Domain Registrars" — best-domain-registrars.com.
- Pikkly — CC BY 4.0. "Price data by Pikkly" — pikkly.dev.
- Open Domain Data — CC BY 4.0. Open Domain Data (2026). tld_pricing, opendomaindata.org.
- Porkbun, Dynadot, Gandi, Hover, IONOS — their own published price lists, read as public pages and used as factual price references.
Verification & corrections
If you spot an error, please contact us with the TLD, the issue, and a source. We investigate and correct within one sync cycle.