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