docs / endpoint
POST /v1/domains/competitors
Competitor discovery from the SERP archive: domains that rank for the same keywords, ranked by overlap.
Credits: 30 credits per call.
Timeout: 60s
Parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
domain |
string | required | — | Domain to find competitors for (bare hostname, lowercased). Required, max 255 chars, no spaces. |
engine |
string | optional | "google" |
Optional, default "google". Same enum as /v1/search. |
location |
integer | optional | 2840 |
Google Ads geotarget ID. Optional, default 2840 (United States). Look one up with /v1/locations. |
language |
string | optional | "en" |
ISO language code. Optional, default "en". |
device |
string | optional | "desktop" |
One of: desktop, mobile. Optional, default "desktop". |
limit |
integer | optional | 25 |
Number of competitors to return. Optional, default 25. 1-100. |
date_from |
string | optional | — | ISO YYYY-MM-DD, inclusive. Optional, default 730 days ago -- sets how far back in the archive the comparison reaches. |
Request
→ requestPOST /v1/domains/competitors
POST /v1/domains/competitors HTTP/1.1
Authorization: Bearer sof_live_your_key_here
Content-Type: application/json
{
"domain": "semrush.com",
"engine": "google",
"location": 2840,
"language": "en",
"device": "desktop",
"limit": 25
}
Response
Wrapped in the standard envelope -- id, object, created_at, elapsed_ms, cache, credits -- documented once on The Contract. The body below is a real envelope with this endpoint's data shape; values vary per request, and a … marks an array cut short for display.
← response200
{
"id": "doma_chtjebfwx3abjucns2jd7fkd",
"request_id": "req_mjgdhw6t3ngmtdlog4eoij3meq",
"object": "domain_competitors",
"created_at": "2026-08-09T07:21:58Z",
"elapsed_ms": 180,
"cache": "miss",
"credits": {
"charged": 30,
"balance": 9857
},
"data": {
"domain": "semrush.com",
"keywords_total": 2834,
"keywords_considered": 200,
"total_competitors": 1743,
"competitors": [
{
"domain": "reddit.com",
"shared_keywords": 106,
"keywords_total": 114768,
"avg_rank": 3.9,
"target_avg_rank": 1,
"overlap": 0.53,
"shared_volume": 370910,
"sample_keywords": [
{
"keyword": "google search console",
"volume": 368000
},
"…"
]
},
"…"
],
"coverage": {
"from": "2026-05-20",
"observations": 200
}
}
}
Response fields
What each field in data (above) means.
| Field | Description |
|---|---|
data.domain |
The domain you requested. |
data.keywords_total |
Total keywords the domain ranks for (unbounded by the archive window). |
data.keywords_considered |
Number of the domain's archived keyword rankings actually considered for this comparison (bounded by the archive window). |
data.total_competitors |
Total number of competing domains found, before limit truncation. |
data.competitors |
Competing domains, ranked by keyword overlap, up to limit. |
data.competitors[].domain |
The competitor's domain. |
data.competitors[].shared_keywords |
Number of keywords both domains rank for. |
data.competitors[].keywords_total |
Total keywords the competitor ranks for. |
data.competitors[].avg_rank |
Competitor's average rank across the shared keywords. |
data.competitors[].target_avg_rank |
Your domain's average rank across the same shared keywords. |
data.competitors[].overlap |
shared_keywords / keywords_considered, rounded to 2dp; null when keywords_considered is 0. |
data.competitors[].shared_volume |
Combined search volume of the shared keywords. |
data.competitors[].sample_keywords |
A few example shared keywords, each with its search volume. |
data.competitors[].sample_keywords[].keyword |
The sample keyword. |
data.competitors[].sample_keywords[].volume |
Search volume for the sample keyword. |
data.coverage |
How much of the rankings archive this comparison drew from. |
data.coverage.from |
Earliest observation date the comparison could have used. |
data.coverage.observations |
Same as keywords_considered. |