SEO data that powers your tools.
One API for search and AI visibility data — rankings, keywords, backlinks, and citations. 100TBs of data at your disposal.
No credit card required · Start with 1,500 free credits.
$ curl api.seofetch.com/v1/search -d '{"query": "best running shoes"}'
{
"object": "search",
"credits": { "charged": 1, "balance": 9857 },
"data": {
"query": "best running shoes",
"total_results": 84900000,
"items": [
{
"rank": 1,
"title": "The 12 Best Running Shoes",
"url": "https://example.com/best-running-shoes",
"site_name": "Example Running Co.",
"rating": { "value": 4.6, "votes": 1284, "max": 5 },
"sitelinks": [ { "title": "Best Trail Running Shoes" } ]
}
]
}
}
Three commands to first data.
Get a key
Sign up and generate an API key from your dashboard.
Send a request
Every metered endpoint is one POST. Same envelope, same rules.
Get normalized JSON
The same envelope on every endpoint: object, credits, data. One integration, all data types.
Give your coding agent the whole picture.
A short Markdown brief, built for pasting straight into an agent's context — what the API does, every endpoint and what it costs, a quickstart it can run, and one worked example. The preview below shows the shape; copy the full document into your agent and skip the docs crawl.
# seofetch — SEO data API
seofetch is a REST API for SEO data — search results, keyword volume and difficulty, backlinks, domain overviews, site audits, Lighthouse performance, and more. All 19 endpoints return the same JSON envelope, so learning that shape once gets you every endpoint.
Base URL: `https://api.seofetch.com`. Authenticate every request with `Authorization: Bearer <your key>`. Get a key at `https://seofetch.com/accounts/signup/` — 1,500 free credits, no card required.
## Quick start
```bash
curl https://api.seofetch.com/v1/search \
-H "Authorization: Bearer sof_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"query": "best running shoes"}'
```
show the full document
# seofetch — SEO data API
seofetch is a REST API for SEO data — search results, keyword volume and difficulty, backlinks, domain overviews, site audits, Lighthouse performance, and more. All 19 endpoints return the same JSON envelope, so learning that shape once gets you every endpoint.
Base URL: `https://api.seofetch.com`. Authenticate every request with `Authorization: Bearer <your key>`. Get a key at `https://seofetch.com/accounts/signup/` — 1,500 free credits, no card required.
## Quick start
```bash
curl https://api.seofetch.com/v1/search \
-H "Authorization: Bearer sof_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"query": "best running shoes"}'
```
```json
{
"id": "srch_tnq5objwpmflh2poczbwxnfr",
"request_id": "req_c7leybmgtzholcwoyhozbqsqkq",
"object": "search",
"created_at": "2026-08-08T16:50:38Z",
"elapsed_ms": 142,
"cache": "miss",
"credits": {
"charged": 1,
"balance": 9857
},
"data": {
"query": "best running shoes",
"engine": "google",
"location": 2840,
"language": "en",
"device": "desktop",
"total_results": 84900000,
"serp_url": "https://www.google.com/search?q=best+running+shoes",
"result_types": [
"organic"
],
"results_count": 10,
"items": [
{
"type": "organic",
"rank": 1,
"page": 1,
"domain": "example.com",
"title": "The 12 Best Running Shoes",
"url": "https://example.com/best-running-shoes",
"description": "Our team tested 40 pairs...",
"displayed_link": "example.com › reviews › shoes",
"date": null,
"site_name": "Example Running Co.",
"rating": {
"value": 4.6,
"votes": 1284,
"max": 5
},
"sitelinks": [
{
"type": "sitelink",
"title": "Best Trail Running Shoes",
"description": null,
"url": "https://example.com/best-running-shoes/trail"
},
{
"type": "sitelink",
"title": "Best Budget Running Shoes",
"description": null,
"url": "https://example.com/best-running-shoes/budget"
}
],
"price": null
}
]
}
}
```
## What's possible
- `POST /v1/search` — Run one search query and get the parsed SERP back — ranked items, not raw HTML. — 1 credit at the default depth (10 results), 10 credits at depth=100.
- `POST /v1/keywords/volume` — Historical Google keyword search volume and competition metrics. — 20 credits per call.
- `POST /v1/keywords/difficulty` — Keyword difficulty (0-100) per keyword; unscored keywords return pending and are scored for a later call. — 110 credits per call.
- `POST /v1/backlinks/summary` — Backlink profile summary metrics for a domain or URL. — 20 credits per call.
- `POST /v1/backlinks/list` — Individual backlinks pointing at a domain or URL. — 50 credits per call.
- `POST /v1/backlinks/domains` — Domains that link to a target, with per-domain metrics. — 50 credits per call.
- `POST /v1/backlinks/anchors` — Anchor-text distribution of backlinks to a target. — 50 credits per call.
- `POST /v1/domains/overview` — Return a domain's organic and paid search overview for one market. — 10 credits per call.
- `POST /v1/page/lighthouse` — Lighthouse scores and core web vitals for a single page. — 2 credits per call.
- `POST /v1/page/crawl` — Render a single page and return a slim page-SEO snapshot. — 2 credits per call.
- `POST /v1/page/accessibility` — Axe accessibility scan of a single page — violations, keyboard-navigation checks, honest scan status. — 2 credits per call.
- `POST /v1/site/audit` — Crawl and audit a whole site; billed per delivered page (sum of enabled checks x pages delivered). — 2 credits per check per delivered page.
- `POST /v1/serp/history` — Position history for a (domain, keyword) pair from our SERP archive. — 5 credits per call.
- `POST /v1/domains/card` — Company card — identity, contacts, socials, technology from our crawl. — 10 credits per call.
- `POST /v1/keywords/questions` — People-Also-Ask questions observed for a topic, deduplicated. — 20 credits per call.
- `POST /v1/ai/visibility` — How often AI assistants mention a domain, per provider, over time. — 10 credits per call.
- `GET /v1/locations` — Look up Google Ads geotarget IDs by name — country, state/region, city, or neighborhood. — free, unmetered (`?q=` required).
- `POST /v1/domains/competitors` — Competitor discovery from the SERP archive: domains that rank for the same keywords, ranked by overlap. — 30 credits per call.
- `POST /v1/domains/gap` — Keyword gap between two domains: opportunity, shared, or unique rankings, volume-enriched. — 15 credits per call.
## What people use it for
- **Let an LLM pick what to optimize next** — An agent ranks your pages by winnable upside — positions, volume, difficulty, on-page gaps. (`/v1/search`, `/v1/keywords/volume`, `/v1/keywords/difficulty`, `/v1/page/crawl`)
- **Find backlink donors** — Mine competitors' referring domains into a ranked candidate list for vetting. (`/v1/backlinks/domains`, `/v1/backlinks/anchors`, `/v1/domains/overview`)
- **A rank tracker in a cron job** — Daily positions, diffed and alerted, for 1 credit per keyword per day. (`/v1/search`)
- **Fail the build when the site regresses** — Lighthouse + on-page checks on every deploy. (`/v1/page/lighthouse`, `/v1/page/crawl`, `/v1/site/audit`)
- **Find out who you're actually up against** — Competitors ranked by real keyword overlap from the SERP archive — not who you assume they are. (`/v1/domains/competitors`, `/v1/domains/overview`, `/v1/domains/gap`)
- **Find the content you're missing** — Keywords a competitor ranks for that you don't — volume-enriched, with the questions people actually ask. (`/v1/domains/gap`, `/v1/keywords/questions`, `/v1/keywords/difficulty`)
- **Vet a backlink donor before you pitch** — Spam score, authority, and the link-mix breakdown for any domain — 30 credits to skip a bad neighborhood. (`/v1/backlinks/summary`, `/v1/domains/overview`)
- **Track page performance over time** — Lighthouse scores and lab vitals in a CSV, with rank history sitting next to them. (`/v1/page/lighthouse`, `/v1/serp/history`)
## A worked example — A rank tracker in a cron job
Daily positions, diffed and alerted, for 1 credit per keyword per day.
```bash
#!/usr/bin/env bash
# tracker.sh -- daily rank tracker, cron-ready. keywords.txt: one keyword per line.
# cron: 15 6 * * * cd /path/to/tracker && ./tracker.sh
set -euo pipefail
: "${SEOFETCH_KEY:?export SEOFETCH_KEY first}"
DOMAIN="${TRACK_DOMAIN:-yourdomain.com}"
TODAY=$(date -u +%F)
mkdir -p snapshots
OUT="snapshots/$TODAY.csv"
: > "$OUT"
while IFS= read -r kw; do
[ -z "$kw" ] && continue
# -w tacks the status code onto the last line.
resp=$(curl -sS https://api.seofetch.com/v1/search \
-H "Authorization: Bearer $SEOFETCH_KEY" \
-H "Content-Type: application/json" \
-d "$(jq -cn --arg q "$kw" '{query: $q}')" \
-w $'\n%{http_code}')
code=${resp##*$'\n'}
body=${resp%$'\n'*}
if [ "$code" != "200" ]; then
# a 504 means the job kept running server-side past your connection --
# the charge stands either way. Any non-2xx (401/429/504/500/...) is
# never a "miss" -- skip it rather than parse the error body as data.
echo "warning: $kw returned HTTP $code, skipping" >&2
continue
fi
# "miss" = not in the returned results (top 10 at the default depth) --
# the row survives so the diff below can see you drop out entirely
rank=$(printf '%s' "$body" | jq -r --arg d "$DOMAIN" \
'[.data.items[]? | select(.domain == $d) | .rank][0] // "miss"')
printf '%s,%s\n' "$kw" "$rank" >> "$OUT"
done < keywords.txt
# diff against yesterday, alert on drops (macOS date -v / GNU date -d both handled)
PREV="snapshots/$(date -u -v-1d +%F 2>/dev/null || date -u -d yesterday +%F).csv"
if [ -f "$PREV" ]; then
awk -F, 'NR==FNR { prev[$1]=$2; next }
($1 in prev) && prev[$1] != "miss" && $2 != "miss" && ($2+0) > (prev[$1]+0) \
{ print $1 ": " prev[$1] " -> " $2 }
($1 in prev) && prev[$1] != "miss" && $2 == "miss" \
{ print $1 ": " prev[$1] " -> miss (dropped out)" }' "$PREV" "$OUT" |
sh -c "${ALERT_CMD:-cat}" # e.g. ALERT_CMD="mail -s 'rank drops' you@example.com"
fi
```
## Going deeper
This overview is deliberately short. Every endpoint's exact request parameters (required fields, defaults, enums) and response fields are published as OpenAPI: https://api.seofetch.com/v1/openapi.json. For the whole docs corpus in one fetch — every page, the idempotency/retry contract, and a reference page per endpoint — see https://docs.seofetch.com/llms-full.txt.
All the SEO data your tools need. Predictable credit costs.
Click any endpoint — the response shown is the real envelope, built from the live catalog.
POST /v1/search HTTP/1.1
Authorization: Bearer sof_live_your_key_here
Content-Type: application/json
{
"query": "best running shoes"
}
$ man search — full parameter reference in the docs →
POST /v1/keywords/volume HTTP/1.1
Authorization: Bearer sof_live_your_key_here
Content-Type: application/json
{
"keywords": [
"running shoes",
"trail running shoes"
],
"location": "US",
"language": "en"
}
$ man volume — full parameter reference in the docs →
POST /v1/keywords/difficulty HTTP/1.1
Authorization: Bearer sof_live_your_key_here
Content-Type: application/json
{
"keywords": [
"buy running shoes",
"cold keyword"
],
"location": 2840,
"language": "en"
}
$ man difficulty — full parameter reference in the docs →
POST /v1/backlinks/summary HTTP/1.1
Authorization: Bearer sof_live_your_key_here
Content-Type: application/json
{
"target": "example.com"
}
$ man summary — full parameter reference in the docs →
POST /v1/backlinks/list HTTP/1.1
Authorization: Bearer sof_live_your_key_here
Content-Type: application/json
{
"target": "example.com",
"limit": 100,
"offset": 0
}
$ man list — full parameter reference in the docs →
POST /v1/backlinks/domains HTTP/1.1
Authorization: Bearer sof_live_your_key_here
Content-Type: application/json
{
"target": "example.com",
"limit": 100,
"offset": 0
}
$ man domains — full parameter reference in the docs →
POST /v1/backlinks/anchors HTTP/1.1
Authorization: Bearer sof_live_your_key_here
Content-Type: application/json
{
"target": "example.com",
"limit": 100,
"offset": 0
}
$ man anchors — full parameter reference in the docs →
POST /v1/domains/overview HTTP/1.1
Authorization: Bearer sof_live_your_key_here
Content-Type: application/json
{
"domain": "example.com",
"location": 2840,
"language": "en"
}
$ man overview — full parameter reference in the docs →
POST /v1/page/lighthouse HTTP/1.1
Authorization: Bearer sof_live_your_key_here
Content-Type: application/json
{
"url": "https://example.com/",
"device": "mobile"
}
$ man lighthouse — full parameter reference in the docs →
POST /v1/page/crawl HTTP/1.1
Authorization: Bearer sof_live_your_key_here
Content-Type: application/json
{
"url": "https://example.com/"
}
$ man crawl — full parameter reference in the docs →
POST /v1/page/accessibility HTTP/1.1
Authorization: Bearer sof_live_your_key_here
Content-Type: application/json
{
"url": "https://seojuice.io/"
}
$ man accessibility — full parameter reference in the docs →
POST /v1/site/audit HTTP/1.1
Authorization: Bearer sof_live_your_key_here
Content-Type: application/json
{
"domain": "example.com",
"max_pages": 5,
"checks": [
"crawl",
"lighthouse"
],
"device": "mobile"
}
$ man audit — full parameter reference in the docs →
POST /v1/serp/history HTTP/1.1
Authorization: Bearer sof_live_your_key_here
Content-Type: application/json
{
"domain": "example.com",
"keyword": "best running shoes",
"engine": "google",
"location": 2840,
"language": "en",
"device": "desktop",
"date_from": "2026-05-20",
"date_to": "2026-07-28"
}
$ man history — full parameter reference in the docs →
POST /v1/domains/card HTTP/1.1
Authorization: Bearer sof_live_your_key_here
Content-Type: application/json
{
"domain": "example.com"
}
$ man card — full parameter reference in the docs →
POST /v1/keywords/questions HTTP/1.1
Authorization: Bearer sof_live_your_key_here
Content-Type: application/json
{
"keyword": "running shoes",
"location": 2840,
"language": "en",
"limit": 50
}
$ man questions — full parameter reference in the docs →
POST /v1/ai/visibility HTTP/1.1
Authorization: Bearer sof_live_your_key_here
Content-Type: application/json
{
"domain": "example.com",
"providers": [
"chatgpt",
"perplexity"
],
"date_from": "2026-06-01",
"date_to": "2026-07-28",
"granularity": "week"
}
$ man visibility — full parameter reference in the docs →
GET /v1/locations?q=austin+texas HTTP/1.1 Authorization: Bearer sof_live_your_key_here
$ man locations — full parameter reference in the docs →
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
}
$ man competitors — full parameter reference in the docs →
POST /v1/domains/gap HTTP/1.1
Authorization: Bearer sof_live_your_key_here
Content-Type: application/json
{
"domains": [
"semrush.com",
"ahrefs.com"
],
"mode": "gap",
"engine": "google",
"location": 2840,
"language": "en",
"device": "desktop",
"limit": 100,
"offset": 0
}
$ man gap — full parameter reference in the docs →
What people build with it.
Let an LLM pick what to optimize next
An agent ranks your pages by winnable upside — positions, volume, difficulty, on-page gaps.
/v1/search/v1/keywords/volume/v1/keywords/difficulty/v1/page/crawlFind backlink donors
Mine competitors' referring domains into a ranked candidate list for vetting.
/v1/backlinks/domains/v1/backlinks/anchors/v1/domains/overviewA rank tracker in a cron job
Daily positions, diffed and alerted, for 1 credit per keyword per day.
/v1/searchFail the build when the site regresses
Lighthouse + on-page checks on every deploy.
/v1/page/lighthouse/v1/page/crawl/v1/site/auditFind out who you're actually up against
Competitors ranked by real keyword overlap from the SERP archive — not who you assume they are.
/v1/domains/competitors/v1/domains/overview/v1/domains/gapFind the content you're missing
Keywords a competitor ranks for that you don't — volume-enriched, with the questions people actually ask.
/v1/domains/gap/v1/keywords/questions/v1/keywords/difficultyVet a backlink donor before you pitch
Spam score, authority, and the link-mix breakdown for any domain — 30 credits to skip a bad neighborhood.
/v1/backlinks/summary/v1/domains/overviewTrack page performance over time
Lighthouse scores and lab vitals in a CSV, with rank history sitting next to them.
/v1/page/lighthouse/v1/serp/historyPrepaid credits. No subscription.
Infrastructure-grade, by design.
The playbook that made payments programmable — one consistent API, idempotency everywhere, metered pricing, failures that make themselves right — applied to SEO data.
Metered like a utility
Per-request pricing, timed and logged. Your usage feed is the invoice — no seats, no tiers to outgrow.
"id", "request_id", "object", 🔒
"created_at", "elapsed_ms", "cache", "credits", 🔒
"data": { "query", "items[rank, title, domain]" }
}
One API to learn
The envelope never changes — learn it once and every endpoint behaves identically.
Idempotent by default
Same key, same result, one charge. Crashed cron, flaky network, long job — retries are always free.
Built for bulk
One keyword or five hundred in a single call — same envelope, one flat price.
Dependable enough to build on
Fresh daily, stable ids, replayable results — treat it as an input, not a report.
Primitives, not features
JSON in, JSON out, fixed costs — compose them into trackers, audit gates, agents.
Questions.
What is a credit?
A unit of API usage. Most endpoints cost a flat number of credits per request. /v1/search is depth-tiered (1 or 10), /v1/site/audit is billed per delivered page, /v1/locations is free. Credits don't expire.
What are the rate limits?
100 requests per second per organization.
What happens if I run out of credits?
Requests return 402 Payment Required until you top up.
Do failed requests cost credits?
Upstream failures are refunded automatically. A 504 covers two different situations — check the error's code, not just the status. connection_timeout means the job is still running and the charge stands, nothing to refund yet: reconnect with the same key you sent — or, if you called keyless, with the request_id from that response — to collect the result once it's ready. upstream_timeout means the upstream itself gave up: that's a definite failure, refunded automatically like any other.
Are requests synchronous?
Yes — you get the result on the same connection, up to each endpoint's ceiling (60s for most; /v1/search runs to 180s, /v1/site/audit to 600s — see the per-endpoint ceilings in the docs). If it's still running you get a 504; reconnect with the same key you sent — or, if you called keyless, with the request_id from that response.
Start with 1,500 free credits.
No credit card required.
Get your API key