An SEO audit tool examines how a site and its competitors perform in search results for a set of target keywords. It checks which SERP features are present (featured snippets, AI overviews, PAA boxes), where competitors rank, and what content gaps exist. Enterprise SEO tools cost thousands per month. This tutorial builds a lightweight audit tool using the Scavio API that produces an actionable keyword-by-keyword report for free, beyond API usage costs.
Prerequisites
- Python 3.10 or higher
- requests library installed
- A Scavio API key
- A target domain and list of keywords to audit
Walkthrough
Step 1: Define audit targets
Set up your target domain, competitor domains, and the keyword list to audit.
TARGET = "mysite.com"
COMPETITORS = ["competitor-a.com", "competitor-b.com"]
KEYWORDS = ["python api tutorial", "rest api guide", "api authentication best practices"]Step 2: Fetch full SERP data for each keyword
Retrieve the complete SERP response including organic results, featured snippet, AI overview, and PAA.
def audit_keyword(keyword: str) -> dict:
r = requests.post(ENDPOINT, headers={"x-api-key": API_KEY},
json={"query": keyword, "country_code": "us"})
r.raise_for_status()
return r.json()Step 3: Analyze SERP features and positions
For each keyword, check which SERP features are present and where the target domain and competitors rank.
def analyze(keyword: str, data: dict) -> dict:
organic = data.get("organic_results", [])
target_pos = next((r["position"] for r in organic if TARGET in r.get("link", "")), None)
competitor_pos = {}
for c in COMPETITORS:
pos = next((r["position"] for r in organic if c in r.get("link", "")), None)
competitor_pos[c] = pos
return {
"keyword": keyword,
"target_position": target_pos,
"competitors": competitor_pos,
"has_featured_snippet": bool(data.get("featured_snippet")),
"has_ai_overview": bool(data.get("ai_overview")),
"paa_count": len(data.get("people_also_ask", [])),
}Step 4: Generate the audit report
Run the audit for all keywords and print a formatted summary report.
def run_audit() -> None:
print(f"SEO Audit for {TARGET}\n" + "=" * 40)
for kw in KEYWORDS:
data = audit_keyword(kw)
result = analyze(kw, data)
pos = result["target_position"]
print(f"\n{kw}")
print(f" Your rank: {'#' + str(pos) if pos else 'not ranked'}")
print(f" AI Overview: {result['has_ai_overview']}, PAA: {result['paa_count']}")Python Example
import os
import requests
API_KEY = os.environ.get("SCAVIO_API_KEY", "your_scavio_api_key")
ENDPOINT = "https://api.scavio.dev/api/v1/search"
TARGET = "mysite.com"
KEYWORDS = ["python api tutorial", "rest api guide"]
def fetch(q):
r = requests.post(ENDPOINT, headers={"x-api-key": API_KEY},
json={"query": q, "country_code": "us"})
r.raise_for_status()
return r.json()
def analyze(kw, data):
organic = data.get("organic_results", [])
pos = next((r["position"] for r in organic if TARGET in r.get("link", "")), None)
return {"keyword": kw, "position": pos, "ai_overview": bool(data.get("ai_overview")), "paa": len(data.get("people_also_ask", []))}
if __name__ == "__main__":
for kw in KEYWORDS:
result = analyze(kw, fetch(kw))
print(f"{kw}: {'#' + str(result['position']) if result['position'] else 'not ranked'} | AI: {result['ai_overview']} | PAA: {result['paa']}")JavaScript Example
const API_KEY = process.env.SCAVIO_API_KEY || "your_scavio_api_key";
const ENDPOINT = "https://api.scavio.dev/api/v1/search";
const TARGET = "mysite.com";
const KEYWORDS = ["python api tutorial", "rest api guide"];
async function fetch_(q) {
const res = await fetch(ENDPOINT, {
method: "POST",
headers: { "x-api-key": API_KEY, "Content-Type": "application/json" },
body: JSON.stringify({ query: q, country_code: "us" })
});
return res.json();
}
function analyze(kw, data) {
const organic = data.organic_results || [];
const match = organic.find(r => r.link.includes(TARGET));
return { keyword: kw, position: match?.position || null, aiOverview: !!data.ai_overview, paa: (data.people_also_ask || []).length };
}
async function main() {
for (const kw of KEYWORDS) {
const data = await fetch_(kw);
const r = analyze(kw, data);
console.log(`${r.keyword}: ${r.position ? "#" + r.position : "not ranked"} | AI: ${r.aiOverview} | PAA: ${r.paa}`);
}
}
main().catch(console.error);Expected Output
SEO Audit for mysite.com
========================================
python api tutorial
Your rank: #6
AI Overview: true, PAA: 4
rest api guide
Your rank: not ranked
AI Overview: false, PAA: 3