REST API · v1 · Synchronous

SERP API (Rank Finder)

Integrate Google rank lookup into your site or app — single request, instant result.

Base URLhttps://www.spindorai.com/api/public-rank-finder
OpenAPI JSON

Share this page or the OpenAPI file with AI assistants to generate integration code automatically.

Integrate in 4 Steps

  1. Create a SERP API key

    Register and log in → https://www.spindorai.com/api-keysSERP API tab. Format: sp_serp_…

  2. POST https://www.spindorai.com/api/public-rank-finder/check

    Content-Type: application/json, X-Spindora-Key: sp_serp_…

  3. Handle JSON response

    Use found, position, page and results[]. No polling — single request is enough.

  4. Show attribution

    Near results: Powered by Spindora → https://www.spindorai.com

Overview

Spindora SERP API finds the ranking position of a domain for a keyword in Google (or DuckDuckGo / Yandex). Results return immediately — no async queue or polling. With an API key, monthly quota is tied to your user account — all SERP keys share the same pool.

API key required

For external calls

Sync response

POST /check → 200

Attribution

Required link

Authentication

A valid SERP API key is required for external integrations. Create keys from your dashboard; the full secret is shown only once.

MethodValue
Header (recommended)X-Spindora-Key: sp_serp_…
BearerAuthorization: Bearer sp_serp_…

Create keys at: https://www.spindorai.com/api-keys (login required)

Quotas & Plans

With API key (external integration)

  • Quota is monthly per user — shared across all SERP keys.
  • Plans: Free 50 · Starter 100 · Pro 200 · Pro+ 400 · Enterprise 800 requests/month.
  • Remaining quota: GET https://www.spindorai.com/api/api-hub/status (with Spindora session token; visible in dashboard).
  • Up to 10 active SERP keys.

Web UI (/sira-bulucu)

  • Without API key, daily IP limit applies (default 30/day).

Buy plans: https://www.spindorai.com/api-key-satin-al

Request Flow

1

POST /check

Send url + keyword

2

Wait (≤60s)

SERP scan on server

3

200 OK

position + results[]

Unlike the SEO Analysis API, there is no task_id or poll loop.

Request Schema

FieldTypeRequiredDescription
urlstringYesTarget site (domain or full URL)
keywordstringYesKeyword to search
engine"google" | "duckduckgo" | "yandex"NoDefault: google
locationstringNoGeo slug: tr, ankara, istanbul, us, uk, de…
locale"tr" | "en"NoError message language
max_pagesinteger 1–10NoMax SERP pages to scan (default 5)

Endpoints

POST/check

Check rank — main integration endpoint.

cURL
curl -X POST "https://www.spindorai.com/api/public-rank-finder/check" \
  -H "Content-Type: application/json" \
  -H "X-Spindora-Key: sp_serp_YOUR_KEY_HERE" \
  -d '{
    "url": "example.com",
    "keyword": "seo aracı",
    "engine": "google",
    "location": "tr",
    "locale": "tr",
    "max_pages": 5
  }'
GET/quota

Daily IP quota for web UI. With API key, use /api-hub/status for monthly quota.

JSON Response Examples

Found (200)

JSON
{
  "success": true,
  "url": "example.com",
  "keyword": "seo aracı",
  "engine": "google",
  "source": "google",
  "location": "tr",
  "found": true,
  "position": 3,
  "page": 1,
  "results": [
    {
      "position": 1,
      "page": 1,
      "title": "En İyi SEO Araçları",
      "url": "https://competitor.com/seo-araclari",
      "description": "…",
      "is_target": false
    },
    {
      "position": 3,
      "page": 1,
      "title": "Example — SEO Aracı",
      "url": "https://example.com/",
      "description": "…",
      "is_target": true
    }
  ],
  "message": "Siteniz 3. sırada (1. sayfa).",
  "attribution": {
    "text": "Powered by Spindora",
    "url": "https://www.spindorai.com",
    "required": true
  }
}

Not found (200)

JSON
{
  "success": true,
  "url": "example.com",
  "keyword": "çok nadir kelime",
  "engine": "google",
  "location": "tr",
  "found": false,
  "position": null,
  "page": null,
  "results": [],
  "message": "İlk 5 sayfada bulunamadı.",
  "attribution": {
    "text": "Powered by Spindora",
    "url": "https://www.spindorai.com",
    "required": true
  }
}

Attribution (Required)

In API mode the response includes an attribution object. It must be visible near results in your integration:

<a href="https://www.spindorai.com" target="_blank" rel="noopener noreferrer">
  Powered by Spindora
</a>

Code Examples

JavaScript (fetch)

const API = 'https://www.spindorai.com/api/public-rank-finder';
const KEY = 'sp_serp_YOUR_KEY_HERE';

async function checkRank(url, keyword) {
  const res = await fetch(`${API}/check`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-Spindora-Key': KEY,
    },
    body: JSON.stringify({
      url,
      keyword,
      engine: 'google',
      location: 'tr',
      locale: 'tr',
      max_pages: 5,
    }),
  });

  if (!res.ok) {
    const err = await res.json().catch(() => ({}));
    throw new Error(err.detail?.message || err.detail || res.statusText);
  }

  const data = await res.json();
  // data.found, data.position, data.page, data.results
  return data;
}

Python (requests)

import requests

API = "https://www.spindorai.com/api/public-rank-finder"
KEY = "sp_serp_YOUR_KEY_HERE"
HEADERS = {"X-Spindora-Key": KEY, "Content-Type": "application/json"}

def check_rank(url: str, keyword: str) -> dict:
    r = requests.post(
        f"{API}/check",
        headers=HEADERS,
        json={
            "url": url,
            "keyword": keyword,
            "engine": "google",
            "location": "tr",
            "locale": "tr",
            "max_pages": 5,
        },
        timeout=60,
    )
    r.raise_for_status()
    return r.json()

# result["found"], result["position"], result["results"]

Node.js

const API = 'https://www.spindorai.com/api/public-rank-finder';
const KEY = 'sp_serp_YOUR_KEY_HERE';

async function checkRank(url, keyword) {
  const res = await fetch(`${API}/check`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-Spindora-Key': KEY,
    },
    body: JSON.stringify({
      url,
      keyword,
      engine: 'google',
      location: 'tr',
      locale: 'tr',
      max_pages: 5,
    }),
  });

  if (!res.ok) {
    const err = await res.json().catch(() => ({}));
    throw new Error(err.detail?.message || err.detail || res.statusText);
  }

  const data = await res.json();
  // data.found, data.position, data.page, data.results
  return data;
}

PHP

<?php
$api = 'https://www.spindorai.com/api/public-rank-finder';
$key = 'sp_serp_YOUR_KEY_HERE';

function checkRank(string $url, string $keyword): array {
    global $api, $key;

    $ch = curl_init("$api/check");
    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => [
            'Content-Type: application/json',
            "X-Spindora-Key: $key",
        ],
        CURLOPT_POSTFIELDS => json_encode([
            'url' => $url,
            'keyword' => $keyword,
            'engine' => 'google',
            'location' => 'tr',
            'locale' => 'tr',
            'max_pages' => 5,
        ]),
        CURLOPT_TIMEOUT => 60,
    ]);
    $body = curl_exec($ch);
    $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    if ($code !== 200) {
        throw new RuntimeException($body ?: "HTTP $code");
    }
    return json_decode($body, true);
}

Response Fields

FieldDescription
foundWhether target domain was found in SERP
positionGlobal rank (1 = first)
pageSERP page number where found
results[]SERP snippets (position, title, url, is_target)
engineRequested search engine
sourceData source used (google, searxng, etc.)
messageHuman-readable summary
attributionRequired display info

Error Codes

HTTPMeaningWhat to do
401Invalid or missing API keyVerify sp_serp_ prefix
403API plan expiredRenew plan at api-key-satin-al
429Monthly quota exceededUpgrade plan or wait next month
400Empty keyword or invalid bodyProvide keyword field
500Temporary SERP / server errorRetry after a short delay

Integration Checklist

  • SERP API key created (sp_serp_…)
  • X-Spindora-Key sent on every POST /check
  • UI shows friendly message when found=false
  • 429 shows upgrade path for monthly quota
  • Powered by Spindora link visible near results
  • Request timeout at least 60s (SERP scan may take time)

Brief for AI / LLMs

Paste this text or the OpenAPI JSON link when asking an AI to write integration code:

Copy — AI prompt
# Spindora SERP API — Integration Brief

Base URL: https://www.spindorai.com/api/public-rank-finder
Documentation: https://www.spindorai.com/developers/serp-api
OpenAPI JSON: https://www.spindorai.com/developers/serp-api.openapi.json
API Key: Register → log in → https://www.spindorai.com/api-keys → create key under SERP API tab (sp_serp_*)

## Authentication
Header: X-Spindora-Key: sp_serp_YOUR_KEY
Alternative: Authorization: Bearer sp_serp_YOUR_KEY

## Flow (synchronous — no polling)
POST /check
Body: {"url":"example.com","keyword":"seo tool","engine":"google","location":"tr","locale":"en","max_pages":5}
→ HTTP 200 returns position, page, results[]

## Quota
Monthly, user-level (shared across all SERP keys):
Free 50 | Starter 100 | Pro 200 | Pro+ 400 | Enterprise 800 / month
Remaining quota: GET https://www.spindorai.com/api/api-hub/status (Spindora session JWT)

## Requirements
- API key required for external integrations
- Show attribution in UI: Powered by Spindora → https://www.spindorai.com

## Error codes
401 invalid key | 403 plan expired | 429 monthly quota exceeded | 400 missing keyword | 500 temporary SERP error

OpenAPI: https://www.spindorai.com/developers/serp-api.openapi.json