API Docs
Free, unauthenticated API for domain search and intelligence. Search across 6 registrars for live pricing, or look up detailed RDAP/DNS info for any domain. Also available as a paid API via the x402 payment protocol on Starknet — no API keys, just pay-per-request.
2 Free Endpoints + 2 Paid (x402)
Base URL
https://donadomains.xyzDomain Search
/api/search?q={keyword}Search domain availability across 6 registrars with live pricing.
Parameters
qstringSearch keyword. Can be a bare word (e.g. "donadomains") or a full domain (e.g. "donadomains.xyz"). Registrars dynamically discover available TLDs for the keyword.streamoptionalstringSet to "true" for real-time streaming via Server-Sent Events. Omit for a single JSON response.JSON Response
Waits for all registrars to respond, then returns a single JSON object. Takes 5-15 seconds. Best for scripts, bots, and backend integrations.
curl "https://donadomains.xyz/api/search?q=donadomains"const res = await fetch(
"https://donadomains.xyz/api/search?q=donadomains"
);
const data = await res.json();
// Available domains with pricing
const available = data.results.filter(r => r.available);
console.log(`${available.length} domains available`);
// Cheapest option
const cheapest = available
.flatMap(r => r.buyLinks ?? [])
.find(l => l.isCheapest);
console.log(cheapest?.name, cheapest?.price);Example Response
{
"keyword": "example",
"tld": null,
"results": [
{
"domain": "example.xyz",
"available": true,
"tld": ".xyz",
"matchType": "exact",
"buyLinks": [
{
"name": "Dynadot",
"url": "https://dynadot.com/...",
"price": "$13.17/yr",
"priceNum": 13.17,
"source": "scraped"
},
{
"name": "GoDaddy",
"url": "https://godaddy.com/...",
"price": "$0.99/yr",
"priceNum": 0.99,
"isCheapest": true,
"source": "scraped"
}
],
"registerUrl": "https://godaddy.com/..."
},
{
"domain": "example.com",
"available": false,
"tld": ".com",
"matchType": "exact",
"buyLinks": []
}
],
"sources": [
{ "name": "Dynadot", "status": "ok", "count": 45, "durationMs": 6821 },
{ "name": "Name.com", "status": "ok", "count": 27, "durationMs": 8234 },
{ "name": "GoDaddy", "status": "ok", "count": 33, "durationMs": 12450 },
{ "name": "Namecheap", "status": "ok", "count": 6, "durationMs": 9102 },
{ "name": "Hover", "status": "ok", "count": 490, "durationMs": 11873 },
{ "name": "Porkbun", "status": "failed", "count": 0, "durationMs": 20000, "error": "timeout" }
]
}Streaming Response
Results arrive progressively via Server-Sent Events as each registrar completes. Registrar results stream in over 2-15 seconds. Best for building real-time UIs with progress indicators.
curl -N "https://donadomains.xyz/api/search?q=donadomains&stream=true"const res = await fetch(
"https://donadomains.xyz/api/search?q=donadomains&stream=true"
);
const reader = res.body.getReader();
const decoder = new TextDecoder();
let buffer = "";
while (true) {
const { done, value } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
const parts = buffer.split("\n\n");
buffer = parts.pop() ?? "";
for (const part of parts) {
const line = part.split("\n").find(l => l.startsWith("data: "));
if (!line) continue;
const event = JSON.parse(line.slice(6));
if (event.type === "batch") {
console.log(event.registrar, "done:", event.results.length, "results");
} else if (event.type === "complete") {
console.log("Search complete");
}
}
}Event Types
initeventSent first. Contains the list of registrar names being scraped (Dynadot, Name.com, GoDaddy, Namecheap, Hover, Porkbun).batcheventSent each time a registrar completes. Contains the full merged results so far, plus source statuses.completeeventAll sources finished. Stream closes after this.Result Fields
domainstringFully qualified domain name (e.g. example.com)availablebooleanWhether the domain is available for registrationtldstringTLD including dot (e.g. '.com')matchTypeoptionalstring"exact" if TLD matches user query, "similar" otherwisebuyLinksBuyLink[]Purchase links from registrars with pricing (empty array for taken domains)registerUrloptionalstringDirect URL to register at the cheapest registrarBuyLink Fields
namestringRegistrar name (e.g. GoDaddy, Dynadot, Hover)urlstringDirect purchase URL — takes user to checkoutpriceoptionalstringFormatted price (e.g. "$9.99/yr")priceNumoptionalnumberNumeric price for sorting/comparisonisCheapestoptionalbooleanTrue if this is the cheapest option across all registrarspremiumoptionalbooleanTrue if this is a premium/aftermarket listingsourcestringAlways "scraped" — prices are live-scraped from registrar websitesSourceStatus Fields
namestringRegistrar name (e.g. GoDaddy, Dynadot)statusstring"ok" if the registrar returned results, "failed" if it timed out or erroredcountnumberNumber of domain hits returned (0 if failed)durationMsnumberTime in milliseconds the registrar scrape tookerroroptionalstringError message when status is failed (e.g. timeout)Error Responses
400Bad RequestMissing or invalid q parameter500Server ErrorUnexpected internal errorDomain Info
/api/domain/{domain}Returns comprehensive domain intelligence from RDAP, DNS-over-HTTPS, and who.is scraping. Layered approach fills in gaps from multiple sources.
Path Parameters
domainstringFully qualified domain name (e.g. "example.com"). Must match the pattern: lowercase alphanumeric with dots/hyphens, ending in a valid TLD.Examples
curl "https://donadomains.xyz/api/domain/example.com"const res = await fetch(
"https://donadomains.xyz/api/domain/example.com"
);
const intel = await res.json();
console.log(intel.registered); // true
console.log(intel.registrar); // "RESERVED-Internet Assigned Numbers Authority"
console.log(intel.nameservers); // ["a.iana-servers.net", "b.iana-servers.net"]
console.log(intel.sources); // ["rdap", "dns"]Example Response
{
"domain": "example.com",
"registered": true,
"status": [
"client delete prohibited",
"client transfer prohibited",
"client update prohibited"
],
"created": "1995-08-14T04:00:00Z",
"updated": "2024-08-14T07:01:44Z",
"expires": "2025-08-13T04:00:00Z",
"registrar": "RESERVED-Internet Assigned Numbers Authority",
"nameservers": [
"a.iana-servers.net",
"b.iana-servers.net"
],
"sources": ["rdap", "dns"],
"timing": {
"rdap": 342,
"dns": 87
}
}Response Fields
domainstringThe normalized domain that was queriedregisteredbooleanWhether the domain is currently registeredstatusoptionalstring[]ICANN domain status codes (e.g. clientTransferProhibited)createdoptionalstringCreation date (ISO 8601)updatedoptionalstringLast updated date (ISO 8601)expiresoptionalstringExpiration date (ISO 8601)registraroptionalstringName of the registrarregistrarUrloptionalstringRegistrar website URLregistrantoptionalstringName of the registrant (often redacted for privacy)organizationoptionalstringRegistrant organizationcontactEmailoptionalstringRegistrant contact email (only shown when not privacy-protected)contactPhoneoptionalstringContact phone numbercontactAddressoptionalstringRegistrant address (partial, often redacted)nameserversoptionalstring[]Authoritative nameservers for the domaindnssecoptionalstringDNSSEC status (e.g. "signedDelegation")sourcesstring[]Data sources used: "rdap", "dns", "who.is"timingobjectMilliseconds spent per source (e.g. { rdap: 342, dns: 87 })Error Responses
400Bad RequestInvalid domain format504Gateway TimeoutRequest took longer than 10 seconds500Server ErrorUnexpected internal errorData Sources
Domain intelligence is gathered in layers, with each source filling gaps left by previous ones:
- RDAP — Registration Data Access Protocol. Free, HTTP-based. Provides registrar, dates, status, and contact info.
- DNS-over-HTTPS — Cloudflare DoH queries. Fast (~50ms). Resolves nameservers and confirms resolution.
- who.is scrape — Firecrawl-powered fallback. Only triggered when RDAP returns almost no data. Used sparingly.
Paid API (x402)
The same endpoints are available as paid, rate-limit-free versions using the x402 payment protocol on Starknet. No API keys needed — your Starknet wallet signs a payment per request, and gas is sponsored via AVNU paymaster.
How It Works
- Request hits
/api/paid/*→ server returns 402 Payment Required with payment details in thePAYMENT-REQUIREDheader. - Your client signs an OutsideExecution (SNIP-9) containing a USDC transfer, built via AVNU paymaster (gas-free).
- Client retries with the PAYMENT-SIGNATURE header → server verifies and settles on-chain → returns data + tx hash.
Paid Search
/api/paid/search?q={keyword}0.01 USDCSame as /api/search — searches domain availability across 6 registrars with live pricing. JSON response only (no SSE streaming). No rate limits.
Example
import { x402axios } from 'starknet-x402';
import { Account, RpcProvider } from 'starknet';
const provider = new RpcProvider({
nodeUrl: process.env.STARKNET_RPC_URL
});
const account = new Account(provider, address, privateKey);
const result = await x402axios.get(
'https://donadomains.xyz/api/paid/search?q=myproject',
{ account, network: 'starknet-sepolia' }
);
console.log(result.data); // { keyword, tld, results, sources }
console.log(result.settlement?.transaction); // tx hash on StarknetResponse schema is identical to /api/search — see the free API docs for field definitions.
Paid Domain Info
/api/paid/domain/{domain}0.005 USDCSame as /api/domain/{domain} — returns RDAP, DNS, and registrar intelligence for a single domain. No rate limits.
Example
import { x402axios } from 'starknet-x402';
import { Account, RpcProvider } from 'starknet';
const provider = new RpcProvider({
nodeUrl: process.env.STARKNET_RPC_URL
});
const account = new Account(provider, address, privateKey);
const result = await x402axios.get(
'https://donadomains.xyz/api/paid/domain/github.com',
{ account, network: 'starknet-sepolia' }
);
console.log(result.data); // domain intel
console.log(result.settlement?.transaction); // tx hashResponse schema is identical to /api/domain/{domain} — see the free API docs for field definitions.
Setup
npm install starknet-x402The SDK handles the full 402 flow automatically — no manual header construction needed. USDC on Starknet Sepolia for testing, mainnet for production. Gas is sponsored by AVNU paymaster.
Rate Limits
The free API is rate-limited per IP address to keep things fair:
/api/search20 req/hrEach search scrapes 6 registrars — expensive upstream/api/domain/{domain}60 req/hrLightweight RDAP + DNS lookups- Rate limits reset every hour from your first request
- Exceeding the limit returns 429 Too Many Requests
- The search endpoint may take 5-15 seconds (registrar scraping)
- The domain info endpoint has a 10 second timeout
No rate limits. Pay per request with USDC on Starknet. See the Paid API section for details.