ScavioScavio
ProductPricingDocs
Sign InGet Started
  1. Home
  2. Tutorials
  3. How to Build a Budget Rank Tracker with the Scavio Search API
Tutorial

How to Build a Budget Rank Tracker with the Scavio Search API

Track 50 keywords daily for $0.035/week using the Scavio Search API. Store rank history in SQLite and get alerts when positions shift by 3+ spots.

Get Free API KeyAPI Docs

Enterprise rank trackers charge $50-200/month to monitor a handful of keywords. With the Scavio Search API at $0.005/credit, you can track 50 keywords daily for $0.035/week -- under $2/year. This tutorial builds a complete rank tracker with SQLite storage, daily cron scheduling, and position change alerts.

Prerequisites

  • Python 3.11+
  • A Scavio API key from https://scavio.dev
  • SQLite3 (included with Python)
  • A cron scheduler or Task Scheduler for daily runs

Walkthrough

Step 1: Set up the SQLite database and keyword list

Create a SQLite database to store daily rank snapshots. Each row records the keyword, the target domain's position, the date, and the URL that ranked.

Python
import sqlite3
from pathlib import Path

DB_PATH = Path("rank_tracker.db")

def init_db():
    conn = sqlite3.connect(DB_PATH)
    conn.execute("""
        CREATE TABLE IF NOT EXISTS rankings (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            keyword TEXT NOT NULL,
            position INTEGER,
            url TEXT,
            checked_at TEXT NOT NULL,
            domain TEXT NOT NULL
        )
    """)
    conn.execute("""
        CREATE INDEX IF NOT EXISTS idx_keyword_date
        ON rankings(keyword, checked_at)
    """)
    conn.commit()
    conn.close()

KEYWORDS = [
    "best API for web scraping 2026",
    "cheap search API for agents",
    "MCP server search tool",
    # ... add up to 50 keywords
]

TARGET_DOMAIN = "scavio.dev"
init_db()

Step 2: Check rankings via the Scavio Search API

For each keyword, search and find your target domain's position in the results. Store the position (or null if not found in top results) in the database.

Python
import httpx
from datetime import date

SCAVIO_API_KEY = "your-api-key"

async def check_ranking(client: httpx.AsyncClient, keyword: str) -> dict:
    resp = await client.post(
        "https://api.scavio.dev/api/v1/search",
        headers={"x-api-key": SCAVIO_API_KEY},
        json={"query": keyword, "num_results": 10}
    )
    resp.raise_for_status()
    results = resp.json().get("results", [])
    for i, r in enumerate(results):
        url = r.get("url", "")
        if TARGET_DOMAIN in url:
            return {"position": i + 1, "url": url}
    return {"position": None, "url": None}

async def check_all_keywords():
    conn = sqlite3.connect(DB_PATH)
    today = date.today().isoformat()
    async with httpx.AsyncClient(timeout=15) as client:
        for keyword in KEYWORDS:
            result = await check_ranking(client, keyword)
            conn.execute(
                "INSERT INTO rankings (keyword, position, url, checked_at, domain) VALUES (?, ?, ?, ?, ?)",
                (keyword, result["position"], result["url"], today, TARGET_DOMAIN)
            )
    conn.commit()
    conn.close()

Step 3: Detect position changes and generate alerts

Compare today's rankings against yesterday's. Flag any keyword that moved 3 or more positions in either direction.

Python
def get_position_changes(threshold: int = 3) -> list[dict]:
    conn = sqlite3.connect(DB_PATH)
    rows = conn.execute("""
        SELECT
            r1.keyword,
            r2.position AS prev_position,
            r1.position AS curr_position,
            r1.url,
            r1.checked_at
        FROM rankings r1
        JOIN rankings r2
            ON r1.keyword = r2.keyword
            AND r1.domain = r2.domain
            AND r2.checked_at = date(r1.checked_at, '-1 day')
        WHERE r1.checked_at = date('now')
            AND r1.position IS NOT NULL
            AND r2.position IS NOT NULL
            AND ABS(r1.position - r2.position) >= ?
        ORDER BY ABS(r1.position - r2.position) DESC
    """, (threshold,)).fetchall()
    conn.close()
    changes = []
    for keyword, prev, curr, url, checked in rows:
        direction = "up" if curr < prev else "down"
        changes.append({
            "keyword": keyword,
            "previous": prev,
            "current": curr,
            "change": prev - curr,
            "direction": direction,
            "url": url
        })
    return changes

Step 4: Generate a daily cost and summary report

Print a summary showing total keywords tracked, credits used, cost, and any significant position changes. Schedule this script with cron for daily automation.

Python
import asyncio

async def daily_report():
    await check_all_keywords()

    credits_used = len(KEYWORDS)  # 1 credit per search
    cost = credits_used * 0.005
    weekly_cost = cost * 7

    changes = get_position_changes(threshold=3)

    print(f"Rank Tracker Report - {date.today().isoformat()}")
    print(f"Keywords tracked: {len(KEYWORDS)}")
    print(f"Credits used: {credits_used}")
    print(f"Daily cost: {cost:.3f}")
    print(f"Weekly cost: {weekly_cost:.3f}")
    print(f"Position changes (3+): {len(changes)}")
    for c in changes:
        arrow = "improved" if c["direction"] == "up" else "dropped"
        print(f"  {c['keyword']}: #{c['previous']} -> #{c['current']} ({arrow} by {abs(c['change'])})")

asyncio.run(daily_report())

# Cron: 0 8 * * * cd /path/to/tracker && python rank_tracker.py

Python Example

Python
import asyncio
import sqlite3
import httpx
from datetime import date
from pathlib import Path

SCAVIO_API_KEY = "your-api-key"
TARGET_DOMAIN = "scavio.dev"
DB_PATH = Path("rank_tracker.db")

KEYWORDS = [
    "best API for web scraping 2026",
    "cheap search API for agents",
    "MCP server search tool",
]

def init_db():
    conn = sqlite3.connect(DB_PATH)
    conn.execute("""
        CREATE TABLE IF NOT EXISTS rankings (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            keyword TEXT, position INTEGER, url TEXT,
            checked_at TEXT, domain TEXT
        )
    """)
    conn.commit()
    conn.close()

async def check_ranking(client, keyword):
    resp = await client.post(
        "https://api.scavio.dev/api/v1/search",
        headers={"x-api-key": SCAVIO_API_KEY},
        json={"query": keyword, "num_results": 10}
    )
    resp.raise_for_status()
    for i, r in enumerate(resp.json().get("results", [])):
        if TARGET_DOMAIN in r.get("url", ""):
            return i + 1, r["url"]
    return None, None

async def main():
    init_db()
    conn = sqlite3.connect(DB_PATH)
    today = date.today().isoformat()
    async with httpx.AsyncClient(timeout=15) as client:
        for kw in KEYWORDS:
            pos, url = await check_ranking(client, kw)
            conn.execute(
                "INSERT INTO rankings VALUES (NULL,?,?,?,?,?)",
                (kw, pos, url, today, TARGET_DOMAIN)
            )
    conn.commit()
    cost = len(KEYWORDS) * 0.005
    print(f"Tracked {len(KEYWORDS)} keywords | Cost: {cost:.3f} | Weekly: {cost * 7:.3f}")
    conn.close()

asyncio.run(main())

JavaScript Example

JavaScript
const SCAVIO_API_KEY = "your-api-key";
const TARGET_DOMAIN = "scavio.dev";
const KEYWORDS = [
  "best API for web scraping 2026",
  "cheap search API for agents",
  "MCP server search tool"
];

async function checkRanking(keyword) {
  const resp = await fetch("https://api.scavio.dev/api/v1/search", {
    method: "POST",
    headers: { "x-api-key": SCAVIO_API_KEY, "Content-Type": "application/json" },
    body: JSON.stringify({ query: keyword, num_results: 10 })
  });
  const data = await resp.json();
  const results = data.results || [];
  for (let i = 0; i < results.length; i++) {
    if ((results[i].url || "").includes(TARGET_DOMAIN)) {
      return { position: i + 1, url: results[i].url };
    }
  }
  return { position: null, url: null };
}

async function main() {
  const rankings = [];
  for (const kw of KEYWORDS) {
    const rank = await checkRanking(kw);
    rankings.push({ keyword: kw, ...rank });
  }
  const cost = KEYWORDS.length * 0.005;
  console.log("Rankings:", JSON.stringify(rankings, null, 2));
  console.log("Daily cost: $" + cost.toFixed(3));
  console.log("Weekly cost: $" + (cost * 7).toFixed(3));
}

main();

Expected Output

JSON
Tracked 3 keywords | Cost: $0.015 | Weekly: $0.105

Related Tutorials

  • How to Build a Marketing Research Agent with the Scavio Search API
  • How to Build an Agent Tool Fallback Chain with Scavio Search API
  • How to Extract YouTube Comments as Structured JSON via the Scavio Search API

Frequently Asked Questions

Most developers complete this tutorial in 15 to 30 minutes. You will need a Scavio API key (free tier works) and a working Python or JavaScript environment.

Python 3.11+. A Scavio API key from https://scavio.dev. SQLite3 (included with Python). A cron scheduler or Task Scheduler for daily runs. A Scavio API key gives you 50 free credits on signup.

Yes. The free tier includes 50 credits on signup, which is more than enough to complete this tutorial and prototype a working solution.

Scavio has a native LangChain package (langchain-scavio), an MCP server, and a plain REST API that works with any HTTP client. This tutorial uses the raw REST API, but you can adapt to your framework of choice.

Related Resources

Best Of

Best API-Based Rank Trackers for SEO in 2026

Read more
Best Of

Best SEO Rank Tracking APIs in 2026

Read more
Solution

Run SEO Rank Checks Overnight in Batch Mode

Read more
Solution

Auto-Alert When Search API Budget Hits Threshold

Read more
Glossary

Exa Semantic Search

Read more
Use Case

n8n Search Enrichment Workflow

Read more

Start Building

Track 50 keywords daily for $0.035/week using the Scavio Search API. Store rank history in SQLite and get alerts when positions shift by 3+ spots.

Get Free API KeyRead the Docs
ScavioScavio

Real-time search API for AI agents. Search every platform, not just Google.

Product

  • Features
  • Pricing
  • Dashboard
  • Affiliates

Developers

  • Documentation
  • API Reference
  • Quickstart
  • MCP Integration
  • Python SDK

Alternatives

  • Tavily Alternative
  • SerpAPI Alternative
  • Firecrawl Alternative
  • Exa Alternative

Tools

  • JSON Formatter
  • cURL to Code
  • Token Counter
  • All Tools

© 2026 Scavio. All rights reserved.

Featured on TAAFT
Terms of ServicePrivacy Policy