Domain Reports API

The Domain SEO API

Five site-explorer reports over one REST API — keyword footprint, verified top pages, competitors, keyword gap, and domain overview. Every row states how it was produced, and you pay only for the SERPs you actually run.

GET/api/v1/search/web?q=postgres+connection+pooling&num=3
200 OK0.17s1 credit85,000 results
{  "searchTime": 0.17,  "totalResults": 85000,  "page": 1,  "organic": [    {      "position": 1,      "title": "31.10. Connection Pools and Data Sources",      "link": "www.postgresql.org/docs/…",      "domain": "postgresql.org",      "snippet": "For an environment without an application se…"    },    { "position": 2, "domain": "medium.com", … },    { "position": 3, "domain": "stackoverflow.blog", … }  ],  "credits": 1}

What is a domain SEO API and how is it priced?

A domain SEO API returns site-level SEO reports — the keywords a domain is associated with, its top pages, its organic competitors, keyword gaps against named rivals, and an overview — as REST calls instead of a dashboard login. Searlo prices every call by provenance: an unverified report pulls from Google Ads' keyword association for a flat 2 credits; a verified report also runs a live SERP per keyword, at 3 credits per 10 results of depth checked.

Verifying is capped at 10 keywords per call regardless of endpoint — call again to cover more of your list. At the default depth (100, i.e. 10 pages), that is 30 credits per keyword verified; checking only the first page (depth=10) drops that to 3 credits per keyword. /domain/top-pages and /domain/competitors always verify (a page or rival can't be "top" or "competing" on a keyword nobody looked up), so a default call to either costs the same as an unverified keywords call plus 10 verified keywords: 302 credits. None of this is a flat "$X per call" — the cost is the formula, and this page states it in credits everywhere a number appears.

Unverified report (keywords / gaps / overview)
2 credits flat, regardless of rows returned
Verified position, per keyword, at default depth (100)
30 credits (3 credits x 10 pages)
Verified position, per keyword, page-1 only (depth=10)
3 credits
Verify cap
10 keywords per call (verify_limit max) — re-call to cover more
Default /domain/top-pages or /domain/competitors call
302 credits (2 + 10 x 30)
Keyword gap vs 10 competitor domains, unverified
22 credits (2 x 11 domains)
Free to start
3,000 credits, no card our pricing
Ahrefs API access (for contrast)
Requires the Lite plan or higher — $129/mo minimum, 1,000 API credits/user ahrefs.com/pricing

Third-party figures on this page last verified against the sources linked above. Prices change; if you find one of these stale, tell us and we will correct it.

Ahrefs, Semrush and SpyFu answer "what does this domain rank for" out of a proprietary index they build by continuously crawling hundreds of millions of SERPs. Searlo does not operate that index, so it does not pretend to read from one — every row this API returns instead says exactly how it was produced.

Two provenances cover all five reports. `google_ads_site_seed` rows come from Google Ads' own association between a domain's crawled content and a search term — real demand data, no login required, but not a ranking, and `position` stays null. `serp_verified` rows come from a live SERP Searlo actually ran for that keyword — an observation, priced per SERP, and capped at 10 keywords per call so a report can't quietly rack up an unbounded bill.

That design maps directly onto what a per-call API can honestly sell. Keyword footprint and domain overview are cheap because they're one Google Ads operation. Top pages and competitors always cost more because a page can't be "top" and a rival can't be "competing" on a keyword nobody looked up — those two are also the reports with no cheap DIY equivalent, since a single Ads pull is easy to build yourself but a verified-overlap analysis across live SERPs is not.

All five reports take a plain `domain` (or `target` plus up to 10 `competitors` for the gap report), work from any of your existing API keys, and return the same `schema` + `results`/`result` + `credits.used` + `meta` envelope Searlo's rank-tracking, keyword-ideas and backlink endpoints use.

Features

  • Provenance on every row

    `source` is always `google_ads_site_seed` or `serp_verified` — never blended into one unlabeled number.

  • Keyword gap across 10 rivals

    /domain/gaps finds keywords up to ten competitor domains are associated with that your domain is not, ranked by shared coverage.

  • Measured competitors, not a score

    /domain/competitors tallies real co-occurrence across the SERPs verified for your keywords — `overlap` is a share of SERPs sampled, not an opaque index.

  • Verified top pages

    /domain/top-pages groups verified positions by URL, so you see which pages actually rank and for how much volume.

  • One-call domain snapshot

    /domain/overview rolls up footprint, topics and average CPC, adding measured organic visibility once you verify.

  • Pay for what ran

    A flat 2 credits for Ads-based discovery; verified rows cost 3 credits per 10 results of depth, per keyword. No subscription, no per-seat fee — packs start at $0.30/1,000 credits at the Scale pack.

Get started in one request

One domain, five calls: keyword footprint, verified top pages, competitors, keyword gap against named rivals, and an overview — each endpoint's exact request shape, in sequence.

# 1. Keyword footprint — cheap, no positions (2 credits flat)
curl "https://api.searlo.tech/api/v1/domain/keywords?domain=yourdomain.com&limit=50" \
  -H "x-api-key: YOUR_API_KEY"

# 2. Verified top pages — always runs a live SERP per keyword checked
curl "https://api.searlo.tech/api/v1/domain/top-pages?domain=yourdomain.com&limit=20" \
  -H "x-api-key: YOUR_API_KEY"

# 3. Competitors — co-occurrence across SERPs this call verifies independently
curl "https://api.searlo.tech/api/v1/domain/competitors?domain=yourdomain.com&limit=20" \
  -H "x-api-key: YOUR_API_KEY"

# 4. Keyword gap — what up to 10 rivals are associated with that you are not
curl "https://api.searlo.tech/api/v1/domain/gaps?target=yourdomain.com&competitors=competitor1.com,competitor2.com&result_limit=50" \
  -H "x-api-key: YOUR_API_KEY"

# 5. Overview — footprint, topics and (if verified) measured visibility
curl "https://api.searlo.tech/api/v1/domain/overview?domain=yourdomain.com" \
  -H "x-api-key: YOUR_API_KEY"
import requests

BASE = "https://api.searlo.tech/api/v1"
HEADERS = {"x-api-key": "YOUR_API_KEY"}
domain = "yourdomain.com"
rivals = "competitor1.com,competitor2.com"

# 1. Keyword footprint — Google Ads site-seed association, no positions.
# 2 credits flat. Add verify=True to run a live SERP on up to 10 of these
# keywords per call (adds 3 credits x depth-in-pages per keyword verified).
keywords = requests.get(f"{BASE}/domain/keywords",
                         params={"domain": domain, "limit": 50},
                         headers=HEADERS).json()["results"]

# 2. Verified top pages — no `verify` param; every call runs SERPs.
top_pages = requests.get(f"{BASE}/domain/top-pages",
                          params={"domain": domain, "limit": 20},
                          headers=HEADERS).json()["results"]

# 3. Competitors — domains co-occurring on the SERPs this call verified.
competitors = requests.get(f"{BASE}/domain/competitors",
                            params={"domain": domain, "limit": 20},
                            headers=HEADERS).json()["results"]

# 4. Keyword gap — keywords the rivals are associated with that the target
# is not. Cheap by default (Ads association on both sides); verify=True
# measures the target's live position on the gap keywords instead.
gaps = requests.get(f"{BASE}/domain/gaps",
                     params={"target": domain, "competitors": rivals, "result_limit": 50},
                     headers=HEADERS).json()["results"]

# 5. Overview — footprint, topics, and organic_visibility (None unless verified).
overview = requests.get(f"{BASE}/domain/overview",
                         params={"domain": domain},
                         headers=HEADERS).json()["result"]

print(len(keywords), "keywords,", len(top_pages), "top pages,",
      len(competitors), "competitors,", len(gaps), "gap keywords")
print(overview["keyword_footprint"], "total footprint,",
      overview["total_search_volume"], "monthly search volume")
const BASE = "https://api.searlo.tech/api/v1";
const headers = { "x-api-key": "YOUR_API_KEY" };
const domain = "yourdomain.com";
const rivals = "competitor1.com,competitor2.com";

// 1. Keyword footprint — Ads site-seed association, no positions. 2 credits flat.
const { results: keywords } = await (await fetch(
  `${BASE}/domain/keywords?domain=${domain}&limit=50`, { headers },
)).json();

// 2. Verified top pages — every call runs SERPs, no `verify` param to set.
const { results: topPages } = await (await fetch(
  `${BASE}/domain/top-pages?domain=${domain}&limit=20`, { headers },
)).json();

// 3. Competitors — co-occurrence on the SERPs this call verified.
const { results: competitors } = await (await fetch(
  `${BASE}/domain/competitors?domain=${domain}&limit=20`, { headers },
)).json();

// 4. Keyword gap — up to 10 competitor domains, comma-separated.
const gapParams = new URLSearchParams({ target: domain, competitors: rivals, result_limit: "50" });
const { results: gaps } = await (await fetch(
  `${BASE}/domain/gaps?${gapParams}`, { headers },
)).json();

// 5. Overview — organic_visibility is null unless a verified call fed it.
const { result: overview } = await (await fetch(
  `${BASE}/domain/overview?domain=${domain}`, { headers },
)).json();

console.log(keywords.length, "keywords,", topPages.length, "top pages,",
  competitors.length, "competitors,", gaps.length, "gap keywords");
console.log(overview.keyword_footprint, "total footprint,",
  overview.total_search_volume, "monthly search volume");

Keyword gap: what competitors are associated with that you are not

The gap report takes your domain plus up to ten competitor domains and returns the keywords Google Ads associates with the competitors but not with you, ranked by how many rivals share each term and by search volume. Because both sides come from the same Ads site-seed corpus, a gap report costs a handful of discovery operations — 2 credits for your domain plus 2 credits per competitor — rather than hundreds of SERPs.

That default view tells you what to go after; it does not tell you where you'd actually land if you did. Pass `verify=true` and the same call also checks your domain's live position on the gap keywords it just found — capped at 10 keywords per call, at 3 credits per 10 results of depth. That's the version worth acting on, because it separates a keyword you could realistically rank for from one five entrenched competitors already own.

  • GET or POST — POST when you have enough competitor domains to prefer a JSON body over a query string
  • `target` + 1-10 `competitors` required; `gl`/`hl` for locale, `min_volume` to floor demand
  • `limit` (up to 1,000) caps keywords pulled per rival before diffing; `result_limit` (up to 1,000) caps gap rows returned
  • Every row carries `competitor_coverage` — the share of your named rivals associated with that keyword

Competitors: who actually shares your SERPs

This report doesn't model similarity — it counts domains that showed up directly above yours on the SERPs verified for your keyword set, and ranks them by how often that happened. `overlap` is the share of sampled SERPs each rival appeared on: 0.4 means it showed up on 4 of the 10 SERPs this call checked.

It's always a verified call, with no `verify` parameter to set — a domain can't be a measured competitor on a keyword nobody looked up. The sample is whatever `verify_limit` keywords that call checks (10 by default, 10 maximum per call), so the response's own `meta.note` says plainly that a wider sample needs another call.

  • Returns `domain`, `common_keywords`, `overlap`, `common_volume`, `avg_position` per rival, sorted by shared keywords
  • No `verify` param — every /domain/competitors call runs live SERPs
  • Same cost as a verified /domain/keywords call: 2 + (3 x depth-pages x verify_limit) credits

Keyword footprint: what Google Ads thinks you're about

This is the cheap, wide view: every keyword Google Ads associates with your domain's crawled content, with search volume, CPC and competition — no crawled link-graph, no login, and no position, because none was measured. It costs a flat 2 credits no matter how many of the up to 1,000 rows come back, because it's one Ads operation, not one operation per keyword.

The response says what it is in its own fields, not just in this paragraph: `source` reads `google_ads_site_seed` and `position` is `null` on every row until you ask otherwise. Pass `verify=true` to run a live SERP on up to 10 of those keywords per call — 3 credits per 10 results of depth, per keyword checked — and the unverified remainder stays in the same response, clearly marked, so you always see the whole discovered list even when you only paid to measure part of it.

  • `domain`, `gl`, `hl`, `limit` (up to 1,000), `min_volume`
  • `verify` + `verify_limit` (max 10/call) + `device` + `location` + `depth` (10-100) add live positions
  • `source`: `google_ads_site_seed` by default, `serp_verified` on the rows you paid to check

Verified top pages: which URLs actually rank

Ahrefs and Semrush build a top-pages report from their own crawled index; a per-call API's honest equivalent is to run the keyword footprint verified, then group the resulting positions by URL. A page appears here because a keyword check found it ranking — not because a crawler indexed it as "top".

That means coverage is bounded by how many keywords this particular call verified (10 by default, 10 maximum), not by your whole domain's footprint — the response's own `meta.note` field states that plainly rather than implying a complete picture. Run it again against a different slice of your keyword list to build up coverage across multiple calls.

  • Returns `url`, `keywords`, `total_volume`, `best_position`, `avg_position`, `top_keyword` per page
  • Always verified — no `verify` toggle; default cost is 302 credits (2 + 10 keywords x 30 credits at depth=100)
  • `limit` caps pages returned (up to 200)

Overview: the one-call snapshot

Overview rolls the keyword footprint up into one summary: total keyword count, how many carry a search volume, total monthly volume, average CPC, up to ten topics by volume (for the rows the Ads corpus tags with one), and the ten highest-volume keywords. It costs the same as an unverified /domain/keywords call — 2 credits flat — because it's built from the same discovery call, just aggregated.

`organic_visibility` — keywords measured, keywords actually ranking, counts inside the top 3/10/100, and an average position — stays `null` unless you pass `verify=true`, and the response says so in its own `meta.note`. Modelled footprint and measured visibility are separate fields because they're separate operations at separate costs, not one number papering over the other.

  • `domain`, `gl`, `hl`, `limit` (50-1,000)
  • `verify` + `verify_limit` (max 10) + `depth` populate `organic_visibility`
  • Same pricing as /domain/keywords: 2 credits unverified, +3-per-10-depth-per-keyword-verified on top

What teams build on the domain reports

  • Agency site-audit reports without an Ahrefs or Semrush seat per analyst
  • Competitor gap analysis feeding a content or link-building backlog
  • Domain due-diligence checks before an acquisition or partnership
  • SEO tooling that needs footprint and gap data as raw JSON, not a dashboard export
  • Programmatic scoring across a prospect list or a client portfolio

FAQ

Frequently asked questions

What is a domain SEO API?

An API that returns site-level SEO reports — keywords a domain is associated with, its top pages, its organic competitors, keyword gaps against named rivals, and an overview — as REST calls instead of a dashboard login. Searlo's version prices each call by provenance: 2 credits flat for Ads-based discovery, plus 3 credits per 10 results of depth for every keyword you verify with a live SERP.

What is a domain keyword API and what does it cost?

/domain/keywords returns the keywords Google Ads associates with a domain's content — search volume, CPC and competition, no position — for a flat 2 credits regardless of how many of the up to 1,000 rows come back. Add verify=true to run a live SERP on up to 10 of those keywords per call, at 3 credits per 10 results of depth checked, per keyword.

Is this an Ahrefs API alternative?

For four of five reports, yes on a direct basis — organic keywords, top pages, competing domains and overview all have a counterpart Ahrefs itself sells through its own API, per call, with no subscription floor here. The fifth, content gap, doesn't: Ahrefs has never sold it through its API at any tier, only through the Site Explorer dashboard, so /domain/gaps is Searlo's API-accessible equivalent rather than a cheaper version of an Ahrefs API feature. See our dedicated Ahrefs API alternative page for a verified, price-for-price comparison.

How does the keyword gap API work?

Send a target domain and up to 10 competitor domains; the response is the keywords Google Ads associates with the competitors but not the target, ranked by how many rivals share each one and by search volume. It's 2 credits per domain queried (target plus each competitor) unverified; pass verify=true to also measure the target's live position on the returned gap keywords, capped at 10 verified per call.

What does competitor keyword gap analysis cost?

Unverified, it's 2 credits per domain in the comparison — 4 credits for a target plus one rival, 22 credits for a target plus ten rivals. A verified gap report adds 3 credits per 10 results of depth for each of up to 10 gap keywords checked — 300 credits more at the default depth of 100.

Is there a domain overview API?

Yes — /domain/overview returns keyword footprint, keywords with volume, total search volume, average CPC and top topics for 2 credits flat. organic_visibility (keywords ranking, top-3/10/100 counts, average position) is null unless you pass verify=true, since it requires live SERPs rather than modelled Ads data.

What's the difference between a modelled keyword and a verified one?

A modelled (`google_ads_site_seed`) row is Google Ads' own association between your domain's content and a search term — real demand data, but not an observed ranking, and `position` is null. A verified (`serp_verified`) row means Searlo ran an actual SERP for that keyword and recorded where your domain sits. Every row in every one of these five reports carries a `source` field saying which kind it is.

Do these reports use the same crawled index as Ahrefs or Semrush?

No. Searlo doesn't operate a continuously-crawled backlink or rank index. Keyword rows come from Google Ads' own content-to-keyword association; position and competitor data come from live SERPs Searlo actually runs when you ask for them. That's a narrower, differently-sourced signal than a proprietary crawl index, and every response states which one produced each row rather than implying parity.

How many competitor domains can a gap report compare at once?

Up to 10 per call, passed as `competitors` — either a JSON array on the POST route or a comma-separated string on the GET route — alongside a required `target` domain.

Can I get exact ranking positions, not just keyword associations?

Yes, on /domain/keywords, /domain/gaps and /domain/overview, pass verify=true (with an optional verify_limit up to 10 and depth from 10-100). /domain/top-pages and /domain/competitors always run verified, since both reports are built from measured positions by definition.