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

NameTypeRequiredDefaultDescription
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.

FieldDescription
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.