Introduction
The CatchDoms API gives you programmatic access to expired and auction domains from 16 platforms (Dynadot, GoDaddy, DropCatch, Catched, Gname, SnapNames, UK Backorder, Subreg, WebExpire, Park.io, BloomUp, SEO.Domains, NameShift, Nicsell, Gnews Domains, Backorders Domains) plus 100k+ aged ccTLD domains at registration price (Authority plan only). Catalog refreshed daily.
All responses are JSON. The base URL for all endpoints is:
Data is refreshed daily. Auction bids update several times per day.
Authentication
All API requests require a Bearer token in the Authorization header.
To get your API key:
- Sign up or log in at catchdoms.com
- Go to the API Access page
- Create a new API token
API access requires a Pro subscription (468 EUR/year).
Example request header
Rate Limiting
Rate limit depends on your subscription: Pro: 15 requests per minute, Authority: 60 requests per minute, per token. Pro Lite trial users share the Pro rate limit but pagination is capped at the first 1,000 results per query.
Rate limit information is included in the response headers:
| Header | Description |
|---|---|
X-RateLimit-Limit |
Your rate limit per minute |
X-RateLimit-Remaining |
Requests remaining in current window |
If you exceed the rate limit, you will receive a 429 Too Many Requests response. Wait 60 seconds before retrying.
Use per_page=100 to fetch more results per request and reduce API calls.
Endpoints
/api/domains
List domains
Returns a paginated list of domains. Accepts query parameters for filtering.
/api/domains/{id}
Get single domain
Returns the full domain object by its numeric ID.
/api/user
Get authenticated user
Returns the currently authenticated user's information.
Query Parameters
All parameters are optional. Add them to the query string of GET /api/domains.
| Parameter | Type | Default | Description |
|---|---|---|---|
source |
string | — | Filter by source platform. Use <code>regfree</code> for aged ccTLD domains available at registration price (requires Authority subscription).dynadot, catched, dropcatch, godaddy, gname, snapnames, ukdroplists, subreg, webexpire, parkio, bloomup, seodomains, nameshift, nicsell, gnews-domains, backorders-domains, regfree |
tld |
string | — | Filter by TLD, with or without dot prefix. Comma-separated for multiple..com or .fr,.de,.it |
score_min |
integer | — | Minimum quality score (0-100). 50+ for good domains, 70+ for excellent. |
age_min |
integer | — | Minimum age in years, based on Wayback first snapshot |
type |
string | — | Filter by domain typeauction, closeout, backorder |
has_bids |
boolean | — | Only domains with active auction bids |
has_backlinks |
boolean | — | Only domains with referring domains (SEO value) |
has_gmb |
boolean | — | Only domains with a Google My Business listing |
da_min |
integer | — | Minimum Domain Authority (0-100) |
rd_min |
integer | — | Minimum number of referring domains |
language |
string | — | Filter by detected language codeEN, FR, DE, ES, etc. |
contains |
string | — | Keyword the domain name must contain (max 50 chars) |
has_edu_gov |
boolean | — | Only domains with EDU or GOV referring domains |
tf_min |
integer | — | Minimum Trust Flow score (0-100, from Majestic/SEObserver) |
cf_min |
integer | — | Minimum Citation Flow score (0-100, from Majestic/SEObserver) |
categories |
string | — | Comma-separated TTF topic categories (e.g., "Business,Health") |
price_min |
number | — | Minimum price or current bid amount (USD) |
price_max |
number | — | Maximum price or current bid amount (USD) |
snapshots_min |
integer | — | Minimum number of Wayback Machine snapshots |
per_page |
integer | 50 | Results per page (1-100) |
page |
integer | 1 | Page number for pagination |
Response Fields
Each domain in the data array contains these fields.
| Field | Type | Nullable | Description |
|---|---|---|---|
| Identity | |||
id |
integer | No | Unique domain identifier |
name |
string | No | Full domain name |
tld |
string | No | Top-level domain with dot prefix |
source |
string | No | Source platform (dynadot, catched, dropcatch, godaddy, gname, snapnames, ukdroplists, subreg, webexpire, parkio, bloomup, seodomains, nameshift, nicsell, gnews-domains, backorders-domains, regfree โ regfree requires Authority) |
type |
string | No | Domain type (auction, closeout, backorder) |
auction_type |
string | Yes | Sub-type for DropCatch (Dropped, PreRelease, PrivateSeller) or GoDaddy (Bid, BuyNow) |
| Pricing | |||
price |
float | Yes | Fixed price for closeouts, or starting price for auctions |
max_bid |
float | Yes | Current highest bid for auction domains |
effective_price |
float | Yes | The actual price to pay: max_bid if set, otherwise price. Use this field instead of checking both price and max_bid. |
bids_count |
integer | Yes | Number of bids placed on the domain |
auction_end_date |
string (ISO 8601) | Yes | When the auction ends (ISO 8601) |
| Scoring | |||
estibot_appraisal |
float | Yes | Automated valuation estimate from the registrar |
score |
integer | Yes | CatchDoms quality score (0-100), combining age, authority, backlinks, name quality, and TLD |
is_spammy |
boolean | No | Whether the domain was flagged as spammy |
| History | |||
age |
integer | Yes | Domain age in years (computed from wayback_first_date) |
wayback_snapshots |
integer | Yes | Total number of Wayback Machine snapshots |
wayback_first_date |
string (YYYY-MM-DD) | Yes | Date of earliest Wayback snapshot (YYYY-MM-DD) |
wayback_last_date |
string (YYYY-MM-DD) | Yes | Date of latest Wayback snapshot (YYYY-MM-DD) |
| SEO Metrics | |||
pagerank |
integer | Yes | Open PageRank score (0-10) |
domain_authority |
integer | Yes | Domain Authority from DataForSEO (0-100) |
backlinks_count |
integer | Yes | Total number of backlinks |
referring_domains |
integer | Yes | Number of unique referring domains |
trust_flow |
integer | Yes | Trust Flow from Majestic/SEObserver (0-100) |
citation_flow |
integer | Yes | Citation Flow from Majestic/SEObserver (0-100) |
ttf_topic |
string | Yes | Topical Trust Flow category (e.g., "Business/Marketing") |
ref_domains_edu |
integer | Yes | Number of referring domains from .edu sites |
ref_domains_gov |
integer | Yes | Number of referring domains from .gov sites |
ref_domains_dofollow |
integer | Yes | Number of dofollow referring domains |
| SEO.Domains | |||
seo_domains_category |
string | Yes | Primary category from seo.domains marketplace (seodomains source only, e.g., "Technology", "Finance") |
seo_domains_subcategory |
string | Yes | Secondary/fine-grained category from seo.domains marketplace (seodomains source only) |
indexed_pages |
integer | Yes | Number of pages indexed on Google (regfree: exact count from SERP; seodomains: 1 if indexed, 0 otherwise) |
| Traffic | |||
monthly_visitors |
integer | Yes | Estimated monthly visitors (Dynadot and seodomains) |
| Language | |||
language |
string | Yes | Detected language code (EN, FR, DE, etc.), from Wayback archived content |
| Google My Business | |||
has_gmb |
boolean | No | Whether a GMB listing was found for this domain |
gmb_name |
string | Yes | Business name from the GMB listing |
gmb_category |
string | Yes | Business category from the GMB listing |
gmb_address |
string | Yes | Business address from the GMB listing |
| WHOIS / RDAP | |||
whois_registered_at |
string (ISO 8601) | Yes | Current registration date at the registry (ISO 8601). Reflects the current ownership cycle โ a recent value on an old domain signals it was dropped and re-registered. |
whois_expires_at |
string (ISO 8601) | Yes | Domain expiry date at the registry (ISO 8601) |
whois_last_changed_at |
string (ISO 8601) | Yes | Last time the registry record was modified (ISO 8601). Fresh timestamp = recent owner/DNS/registrar change. |
whois_registrar |
string | Yes | Registrar holding the domain (e.g. "GoDaddy.com, LLC", "NameCheap, Inc.") |
whois_status |
array<string> | Yes | Array of EPP status codes (e.g. ["clientTransferProhibited", "serverHold"]) |
whois_nameservers |
array<string> | Yes | Array of current nameservers (e.g. ["ns1.cloudflare.com", "ns2.cloudflare.com"]) |
whois_ns_category |
string | Yes | Classification derived from the nameservers: for_sale | parked | drop_catcher | active | registrar_default. null when nameservers are unknown or not classified. |
whois_checked_at |
string (ISO 8601) | Yes | Last time WHOIS was fetched for this domain. null = never enriched; set with null fields = TLD has no public RDAP. |
| Links | |||
purchase_url |
string | Yes | Direct link to bid/buy on the source platform |
| Timestamps | |||
created_at |
string (ISO 8601) | No | When the domain was added to CatchDoms (ISO 8601) |
updated_at |
string (ISO 8601) | No | When the domain was last updated (ISO 8601) |
effective_price — The actual price to pay: max_bid if set, otherwise price. Use this field instead of checking both price and max_bid.
Pagination
All list endpoints return paginated results using Laravel's standard pagination format.
The meta object contains:
current_page | Current page number |
last_page | Last page number |
per_page | Items per page |
total | Total matching domains |
from | First item index on this page |
to | Last item index on this page |
The links object contains:
first | URL to the first page |
last | URL to the last page |
prev | URL to the previous page (null on first page) |
next | URL to the next page (null on last page) |
{
"data": [ ... ],
"links": {
"first": "https://catchdoms.com/api/domains?page=1",
"last": "https://catchdoms.com/api/domains?page=68",
"prev": null,
"next": "https://catchdoms.com/api/domains?page=2"
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 68,
"per_page": 50,
"to": 50,
"total": 3400
}
}
Code Examples
Replace YOUR_API_KEY with your actual token.
# List domains with score >= 50 and backlinks
curl "https://catchdoms.com/api/domains?score_min=50&has_backlinks=1&per_page=10" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json"
# Get a single domain by ID
curl "https://catchdoms.com/api/domains/12345" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json"
# Filter by TLD and language
curl "https://catchdoms.com/api/domains?tld=.fr&language=FR&age_min=10" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json"
# Filter by multiple TLDs
curl "https://catchdoms.com/api/domains?tld=.fr,.de,.it&score_min=50" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json"
const API_KEY = 'YOUR_API_KEY';
const BASE_URL = 'https://catchdoms.com/api';
// List domains with filters
const params = new URLSearchParams({
score_min: 50,
has_backlinks: 1,
per_page: 10
});
const response = await fetch(`${BASE_URL}/domains?${params}`, {
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Accept': 'application/json'
}
});
const { data, meta } = await response.json();
console.log(`Found ${meta.total} domains`);
// Get a single domain
const domain = await fetch(`${BASE_URL}/domains/12345`, {
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Accept': 'application/json'
}
}).then(r => r.json());
import requests
API_KEY = 'YOUR_API_KEY'
BASE_URL = 'https://catchdoms.com/api'
headers = {
'Authorization': f'Bearer {API_KEY}',
'Accept': 'application/json'
}
# List domains with filters
response = requests.get(f'{BASE_URL}/domains', headers=headers, params={
'score_min': 50,
'has_backlinks': 1,
'language': 'FR',
'per_page': 25
})
data = response.json()
print(f"Found {data['meta']['total']} domains")
for domain in data['data']:
print(f"{domain['name']} - Score: {domain['score']} - Price: {domain['effective_price']}")
# Get a single domain
domain = requests.get(f'{BASE_URL}/domains/12345', headers=headers).json()
Errors
The API uses standard HTTP status codes. Error responses include a JSON body with a message field.
| Code | Meaning | Description |
|---|---|---|
| 200 | Success | Request completed successfully |
| 401 | Unauthorized | Missing or invalid API token |
| 403 | Forbidden | Valid token but no Pro subscription |
| 404 | Not Found | Domain ID does not exist |
| 422 | Validation Error | Invalid parameter value (e.g. score_min=abc) |
| 429 | Too Many Requests | Rate limit exceeded. Wait 60 seconds. |
Example error response
// 401 Unauthorized
{
"message": "Unauthenticated."
}
// 429 Too Many Requests
{
"message": "Too Many Attempts."
}
MCP Server
CatchDoms includes an MCP (Model Context Protocol) server for AI assistants like Claude Code, Cursor, and Windsurf.
Instead of writing API calls, you can ask natural language questions:
Configuration
Add this to your MCP client config:
Claude Code / Cursor
{
"mcpServers": {
"catchdoms": {
"type": "http",
"url": "https://catchdoms.com/mcp/catchdoms",
"headers": {
"Authorization": "Bearer YOUR_API_KEY"
}
}
}
}
Claude Desktop
{
"mcpServers": {
"catchdoms": {
"command": "npx",
"args": [
"mcp-remote",
"https://catchdoms.com/mcp/catchdoms",
"--header",
"Authorization: Bearer YOUR_API_KEY"
]
}
}
}
Claude Code: ~/.claude.json | Cursor: MCP settings Claude Desktop requires Node.js.
Learn more about MCP integrationTroubleshooting
Getting HTML instead of JSON (Cloudflare captcha)
If your API calls return an HTML page with "Just a moment..." instead of JSON, your IP is being challenged by Cloudflare.
- Disable your VPN or switch to a different VPN node/server
- Try from a different IP address or network
- Make sure you include the
Accept: application/jsonheader
403 Subscription Required
API access requires an active Pro subscription.
- Check your subscription status at catchdoms.com/billing
- If you subscribed after creating your token, create a new token at catchdoms.com/api-access
401 Unauthenticated
Your token is missing or invalid.
- Make sure the header format is exactly:
Authorization: Bearer YOUR_TOKEN(with "Bearer " prefix and a space) - Copy the full token including the number and pipe character (e.g.
42|abc...) - Tokens are shown only once at creation. If lost, revoke and create a new one.
MCP Server disconnected
If Claude Desktop shows "Server disconnected" for the CatchDoms MCP server:
- Check that your token is still valid (create a new one if needed)
- Disable VPN โ Cloudflare may block the connection
- Restart Claude Desktop completely (Cmd+Q on Mac, not just close the window)
- Verify your config file syntax in
claude_desktop_config.json
Still having issues? Contact us at [email protected] with your error message and we'll help you debug.