dot·sweep

GET /check/{domain} — check one domain

No API key, no account, no signup. Responses are JSON, CORS is open, and every endpoint is read-only — nothing here can register, buy or change anything.

Request

curl https://dotsweep.com/check/example.com

The domain goes in the path. Internationalised names are accepted and come back in their ASCII (Punycode) form, which is the canonical spelling and the only one two clients are guaranteed to agree on.

Response

{
  "domain": "example.com",
  "tld": "com",
  "status": "available" | "taken" | "unknown",
  "confidence": "certain" | "estimated",
  "source": "rdap" | "dns" | "whois" | "cache",
  "unused": true,
  "price": {
    "currency": "USD",
    "registration": 11.08,
    "renewal": 11.08,
    "first_payment": 11.08,
    "min_term_years": 2,
    "promo_first_year": true,
    "source": "Porkbun",
    "note": "standard price; premium and reserved names cost more..."
  },
  "prices": [
    { "vendor": "dynadot", "currency": "USD", "registration": 3.48,
      "renewal": 31.20, "first_payment": 3.48, "promo_first_year": true },
    { "vendor": "porkbun", "currency": "USD", "registration": 15.76,
      "renewal": 31.20, "first_payment": 15.76, "quoted": true }
  ],
  "policy": {
    "tld": "eu",
    "eligibility": "Registrant must be an EU/EEA citizen...",
    "technical": "HTTPS only. The whole TLD is HSTS-preloaded...",
    "min_term_years": 2,
    "closed": true,
    "closed_reason": "a .brand TLD reserved for its trademark owner (...)",
    "source": "https://eurid.eu/...",
    "verified": "2026-07-29"
  },
  "buy": [{ "id": "porkbun", "vendor": "Porkbun", "url": "...", "quoted": true }],
  "offer": {
    "kind": "listed" | "parked" | "expiring",
    "venue": "Afternic",
    "url": "https://www.afternic.com/domain/example.com",
    "note": "listed on Afternic — price is on the listing, not in the registry"
  }
}

Read confidence before status

certain means a registry answered. Act on it.

estimated means no registry answered and the verdict came from DNS. A domain can be registered with no nameservers, so an estimated "available" is a hint. note says why the answer stayed estimated.

An unreachable or rate-limited registry is never reported as available. That is the whole reason to call this rather than whois: a raw WHOIS reports a throttled registry as free, and a throttled registry is exactly what you get when you check a lot of names at once.

Fields worth knowing about

FieldWhat it means
unusedRegistered, but with no nameservers. Someone owns it and nothing is served from it, which is the taken domain most likely to be for sale.
priceOne registrar's, not a market rate. Exactly one entry in buy carries quoted: true — that is the vendor this figure belongs to.
min_term_yearsWhere a registry will not sell a single year. .ai is quoted at $82.70 everywhere and cannot be bought for $82.70 by anyone, because the registry deals only in two-year terms.
policy.closedA .brand TLD, or one whose ICANN agreement was terminated. Unregistered and unbuyable at once, so it carries no price and no buy link.
offerOnly filled by GET /whois/{domain}. A taken domain is caught by the DNS prefilter, so no registry record is fetched here and there is nothing to read a for-sale signal out of.
buy[].urlThe link to give a reader. It is an absolute https://dotsweep.com/go/{vendor}/{domain} that forwards to that registrar's search. There is no second URL: the hop is no-store, no-referrer and noindex, so the name searched never reaches the registrar in a referrer.

When to use this instead of the batch

Use it for one domain, and for names somebody else has probably already checked. Each response is cached at the edge per URL, and a cache hit is served without reaching the Worker at all — so it costs nothing and is not rate-limited. Re-checking a popular name is effectively free.

For volume, POST /check carries ten domains per request against the same limit.

Errors

{ "error": { "code": "invalid_domain", "message": "...", "hint": "..." } }

Codes: invalid_domain, bad_body, batch_too_large, rate_limited, unknown_endpoint, method_not_allowed, internal_error. The hint says what to do differently. For anything other than rate_limited and internal_error, repeating the same call fails the same way.

Rate limit

120 requests a minute per client, counted as requests rather than domains. Edge cache hits never reach the Worker and are not counted at all.

That rate is the whole quota. There is no daily or monthly ceiling, no credit balance and no trial that expires, so a job that stays under the rate can run as long as it needs to. Said plainly because an unstated limit gets read as a hidden one, and a caller who plans around a monthly cap is planning around nothing.

The other endpoints

The whole reference on one page → · as plain text →