SEO agencies spend hours monthly screenshotting dashboards for client reports. An API pipeline generates them programmatically: pull rank data, competitor positions, and SERP features, then output formatted reports. At $0.005/query, a 100-keyword report costs $0.50 per client.
Prerequisites
- Python 3.8+
- requests library
- A Scavio API key from scavio.dev
- Client domains and keyword lists
Walkthrough
Step 1: Define client configs
Set up clients with domains, keywords, and competitors.
import os, requests, json
from datetime import date
API_KEY = os.environ['SCAVIO_API_KEY']
H = {'x-api-key': API_KEY, 'Content-Type': 'application/json'}
CLIENTS = [{'name': 'Acme Corp', 'domain': 'acme.com',
'competitors': ['comp1.com', 'comp2.com'],
'keywords': ['widget manufacturing', 'custom widgets', 'widget supplier']}]Step 2: Collect rankings for client and competitors
One SERP call per keyword captures all domain positions.
def collect(client):
report = []
domains = [client['domain']] + client['competitors']
for kw in client['keywords']:
data = requests.post('https://api.scavio.dev/api/v1/search',
headers=H, json={'query': kw, 'country_code': 'us'}).json()
positions = {}
for r in data.get('organic_results', []):
for d in domains:
if d in r.get('link', '') and d not in positions:
positions[d] = r['position']
features = []
if data.get('answer_box'): features.append('AB')
if data.get('related_questions'): features.append('PAA')
report.append({'keyword': kw, 'positions': positions, 'features': features})
return reportStep 3: Generate summary metrics
Calculate average position, top 3/10 counts, and cost.
def summary(client, data):
positions = [r['positions'].get(client['domain']) for r in data if r['positions'].get(client['domain'])]
avg = round(sum(positions) / len(positions), 1) if positions else None
t3 = sum(1 for p in positions if p <= 3)
t10 = sum(1 for p in positions if p <= 10)
print(f"\n{client['name']}: {len(positions)}/{len(data)} ranking, avg={avg}, top3={t3}, top10={t10}")
print(f'Cost: ${len(data) * 0.005:.3f}')Step 4: Run all client reports
Generate and export for every client.
for client in CLIENTS:
data = collect(client)
print(f"{'Keyword':25} {'Client':7} {'Comp1':7} {'Comp2':7} Features")
for r in data:
p = r['positions']
print(f"{r['keyword']:25} {str(p.get(client['domain'], '-')):7} "
f"{str(p.get(client['competitors'][0], '-')):7} "
f"{str(p.get(client['competitors'][1], '-')):7} {', '.join(r['features']) or '-'}")
summary(client, data)
with open(f"report_{client['name'].lower().replace(' ','_')}.json", 'w') as f:
json.dump({'client': client['name'], 'date': date.today().isoformat(), 'data': data}, f, indent=2)Python Example
import os, requests
API_KEY = os.environ['SCAVIO_API_KEY']
H = {'x-api-key': API_KEY, 'Content-Type': 'application/json'}
def report(domain, keywords, comps):
for kw in keywords:
data = requests.post('https://api.scavio.dev/api/v1/search',
headers=H, json={'query': kw, 'country_code': 'us'}).json()
pos = {}
for r in data.get('organic_results', []):
for d in [domain] + comps:
if d in r.get('link', '') and d not in pos: pos[d] = r['position']
print(f'{kw:25} You={pos.get(domain, "-"):4} {" ".join(f"{c}={pos.get(c,"-")}" for c in comps)}')
report('acme.com', ['widgets', 'widget supplier'], ['comp1.com'])JavaScript Example
const API_KEY = process.env.SCAVIO_API_KEY;
const H = { 'x-api-key': API_KEY, 'Content-Type': 'application/json' };
async function report(domain, keywords, comps) {
for (const kw of keywords) {
const data = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST', headers: H, body: JSON.stringify({ query: kw, country_code: 'us' })
}).then(r => r.json());
const pos = {};
for (const r of data.organic_results || []) {
for (const d of [domain, ...comps]) if (r.link.includes(d) && !pos[d]) pos[d] = r.position;
}
console.log(`${kw}: You=${pos[domain]||'-'} ${comps.map(c=>`${c}=${pos[c]||'-'}`).join(' ')}`);
}
}
report('acme.com', ['widgets'], ['comp1.com']).catch(console.error);Expected Output
Keyword Client Comp1 Comp2 Features
widget manufacturing 3 7 - PAA
custom widgets 5 2 8 AB, PAA
widget supplier 1 4 6 -
Acme Corp: 3/3 ranking, avg=3.0, top3=2, top10=3
Cost: $0.015