ScavioScavio
ProductPricingDocs
Sign InGet Started
  1. Home
  2. Tutorials
  3. How to Build an SEO Keyword Gap Finder
Tutorial

How to Build an SEO Keyword Gap Finder

Find keywords where competitors rank but you don't by searching target keywords via API, comparing domain positions, and outputting gap opportunities.

Get Free API KeyAPI Docs

An SEO keyword gap finder searches a list of target keywords, finds which ones competitors rank for in the top 10 while your domain does not appear, and outputs the gaps as actionable content opportunities.

Prerequisites

  • Python 3.9+
  • Scavio API key

Walkthrough

Step 1: Define your domain and competitors

Set up the domains you want to compare.

Python
YOUR_DOMAIN = "yoursite.com"
COMPETITOR_DOMAINS = ["competitor1.com", "competitor2.com", "competitor3.com"]

KEYWORDS = [
    "project management software",
    "task tracker for teams",
    "agile board online",
    "kanban tool free",
    "sprint planning tool"
]

Step 2: Search each keyword and extract positions

For each keyword, check if your domain and competitors appear in the top 20 results.

Python
import requests

API_KEY = "your-scavio-api-key"

def get_positions(keyword: str, domains: list) -> dict:
    r = requests.post(
        "https://api.scavio.dev/api/v1/search",
        json={"query": keyword, "num_results": 20},
        headers={"x-api-key": API_KEY},
        timeout=15
    )
    r.raise_for_status()
    results = r.json().get("organic_results", [])
    positions = {}
    for domain in domains:
        pos = next((i + 1 for i, res in enumerate(results) if domain in res.get("link","")), None)
        positions[domain] = pos
    return positions

Step 3: Identify keyword gaps

A gap is a keyword where at least one competitor ranks in the top 10 but your domain does not.

Python
def find_gaps(keywords: list, your_domain: str, competitor_domains: list) -> list:
    all_domains = [your_domain] + competitor_domains
    gaps = []
    for kw in keywords:
        positions = get_positions(kw, all_domains)
        your_pos = positions.get(your_domain)
        competitor_positions = {d: positions.get(d) for d in competitor_domains}
        top10_competitors = [d for d, p in competitor_positions.items() if p and p <= 10]
        if top10_competitors and (not your_pos or your_pos > 10):
            gaps.append({
                "keyword": kw,
                "your_position": your_pos or "not ranking",
                "competitors_ranking": {d: competitor_positions[d] for d in top10_competitors}
            })
    return gaps

gaps = find_gaps(KEYWORDS, YOUR_DOMAIN, COMPETITOR_DOMAINS)
for g in gaps:
    print(f"GAP: {g['keyword']} | You: {g['your_position']} | {g['competitors_ranking']}")

Python Example

Python
import requests
from datetime import date

API_KEY = "your-scavio-api-key"
YOUR_DOMAIN = "yoursite.com"
COMPETITORS = ["asana.com", "monday.com", "clickup.com"]
KEYWORDS = [
    "project management software", "task tracker for teams",
    "agile board online", "kanban tool free",
    "sprint planning tool", "team task management"
]

def get_positions(keyword, domains):
    r = requests.post("https://api.scavio.dev/api/v1/search",
                      json={"query": keyword, "num_results": 20},
                      headers={"x-api-key": API_KEY}, timeout=15)
    r.raise_for_status()
    results = r.json().get("organic_results", [])
    return {d: next((i+1 for i, res in enumerate(results) if d in res.get("link","")), None)
            for d in domains}

def find_gaps(keywords, your_domain, competitors):
    all_domains = [your_domain] + competitors
    gaps, covered = [], []
    for kw in keywords:
        pos = get_positions(kw, all_domains)
        your_pos = pos[your_domain]
        comp_top10 = {d: pos[d] for d in competitors if pos.get(d) and pos[d] <= 10}
        if comp_top10 and (not your_pos or your_pos > 10):
            gaps.append({"keyword": kw, "your_position": your_pos or "NR",
                         "gap_competitors": comp_top10})
        elif your_pos and your_pos <= 10:
            covered.append({"keyword": kw, "position": your_pos})
    return {"gaps": gaps, "covered": covered}

if __name__ == "__main__":
    result = find_gaps(KEYWORDS, YOUR_DOMAIN, COMPETITORS)
    print(f"Keyword Gap Analysis — {YOUR_DOMAIN} — {date.today()}")
    print(f"\nGAPS ({len(result['gaps'])} keywords — content opportunities):")
    for g in result["gaps"]:
        comp_str = ", ".join(f"{d}@{p}" for d, p in g["gap_competitors"].items())
        print(f"  {g['keyword']:<35} | You: {str(g['your_position']):<12} | {comp_str}")
    print(f"\nCOVERED ({len(result['covered'])} keywords — protect these):")
    for c in result["covered"]:
        print(f"  {c['keyword']:<35} | Position {c['position']}")

JavaScript Example

JavaScript
const API_KEY = 'your-scavio-api-key';
const YOUR_DOMAIN = 'yoursite.com';
const COMPETITORS = ['asana.com', 'monday.com'];
const KEYWORDS = ['project management software', 'task tracker for teams', 'kanban tool free'];

async function getPositions(keyword, domains) {
  const res = await fetch('https://api.scavio.dev/api/v1/search', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json', 'x-api-key': API_KEY },
    body: JSON.stringify({ query: keyword, num_results: 20 })
  });
  const data = await res.json();
  const results = data.organic_results ?? [];
  return Object.fromEntries(domains.map(d => [d, (results.findIndex(r => r.link?.includes(d)) + 1) || null]));
}

for (const kw of KEYWORDS) {
  const positions = await getPositions(kw, [YOUR_DOMAIN, ...COMPETITORS]);
  const yourPos = positions[YOUR_DOMAIN];
  const compTop10 = COMPETITORS.filter(d => positions[d] && positions[d] <= 10);
  if (compTop10.length && (!yourPos || yourPos > 10)) {
    console.log(`GAP: ${kw} | You: ${yourPos ?? 'NR'} | Competitors: ${compTop10.join(', ')}`);
  }
}

Expected Output

JSON
Keyword Gap Analysis - yoursite.com - 2026-05-22

GAPS (4 keywords - content opportunities):
  project management software          | You: NR           | asana.com@2, monday.com@5
  agile board online                   | You: NR           | clickup.com@3
  kanban tool free                     | You: 14           | asana.com@1, monday.com@7
  sprint planning tool                 | You: NR           | clickup.com@4, asana.com@8

COVERED (2 keywords - protect these):
  task tracker for teams               | Position 6
  team task management                 | Position 9

Related Tutorials

  • How to Build an SEO Audit Agent in Claude Code
  • How to Monitor Competitor SERP Positions with an API
  • How to Track Products in Google AI Overview Results

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.9+. Scavio API key. 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 SEO Keyword APIs for Agency Work in 2026

Read more
Best Of

Best API for Agency SEO Reporting in 2026

Read more
Glossary

SERP Gap Analysis

Read more
Solution

Automated SERP Gap Analysis

Read more
Use Case

SEO Light User API Workflow

Read more
Use Case

AppSumo SEO Tool to API Migration

Read more

Start Building

Find keywords where competitors rank but you don't by searching target keywords via API, comparing domain positions, and outputting gap opportunities.

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