Traditional domain authority tools like Moz and Ahrefs charge $99 to $999 per month and still limit API access. If you need to quickly evaluate 1000 domains for a link-building campaign or domain portfolio analysis, you can estimate domain strength by checking how frequently and highly a domain ranks in Google results for competitive queries. This tutorial uses the Scavio API to run targeted searches and measure how many times each domain appears in top results. At $0.005 per search, checking 1000 domains with one query each costs $5. With smart query batching, you can cover multiple domains per query and get under $5.
Prerequisites
- Python 3.8+ installed
- requests library installed
- A Scavio API key from scavio.dev
- A text file with domains to check (one per line)
Walkthrough
Step 1: Load domains and define probe queries
Load your domain list and create search queries that are likely to surface authoritative domains. Site-specific queries confirm indexing and ranking strength.
import os, requests, csv
API_KEY = os.environ['SCAVIO_API_KEY']
ENDPOINT = 'https://api.scavio.dev/api/v1/search'
HEADERS = {'x-api-key': API_KEY, 'Content-Type': 'application/json'}
def load_domains(path='domains.txt'):
with open(path) as f:
return [line.strip() for line in f if line.strip()]
def make_probe_query(domain):
name = domain.replace('.com', '').replace('.io', '').replace('.org', '').replace('-', ' ')
return f'site:{domain}'Step 2: Run SERP probes and collect signals
For each domain, run a site: query to check how many pages are indexed and whether the domain appears in results. One API call per domain at $0.005 each.
def probe_domain(domain):
query = make_probe_query(domain)
resp = requests.post(ENDPOINT, headers=HEADERS,
json={'query': query, 'country_code': 'us'})
data = resp.json()
results = data.get('organic_results', [])
has_knowledge_graph = 'knowledge_graph' in data
return {
'domain': domain,
'indexed_pages': len(results),
'has_knowledge_graph': has_knowledge_graph,
'top_result_title': results[0].get('title', '') if results else '',
'total_results_hint': data.get('search_information', {}).get('total_results', 0),
}Step 3: Score domains and export results
Assign a simple authority score based on indexed pages, knowledge graph presence, and total results. Export to CSV sorted by score.
def score_domain(probe):
score = 0
score += min(probe['indexed_pages'] * 10, 50)
if probe['has_knowledge_graph']:
score += 30
hint = probe.get('total_results_hint', 0)
if isinstance(hint, (int, float)) and hint > 10000:
score += 20
return score
def bulk_check(domain_file='domains.txt', output='domain_scores.csv'):
domains = load_domains(domain_file)
results = []
for i, domain in enumerate(domains):
probe = probe_domain(domain)
probe['score'] = score_domain(probe)
results.append(probe)
print(f"[{i+1}/{len(domains)}] {domain}: score {probe['score']}")
results.sort(key=lambda x: x['score'], reverse=True)
with open(output, 'w', newline='') as f:
w = csv.DictWriter(f, fieldnames=['domain', 'score', 'indexed_pages',
'has_knowledge_graph', 'total_results_hint'])
w.writeheader()
for r in results:
w.writerow({k: r[k] for k in w.fieldnames})
cost = len(domains) * 0.005
print(f"\nChecked {len(domains)} domains for ${cost:.2f}")
return results
bulk_check()Python Example
import os, requests, csv
API_KEY = os.environ['SCAVIO_API_KEY']
ENDPOINT = 'https://api.scavio.dev/api/v1/search'
H = {'x-api-key': API_KEY, 'Content-Type': 'application/json'}
def probe(domain):
data = requests.post(ENDPOINT, headers=H,
json={'query': f'site:{domain}', 'country_code': 'us'}).json()
results = data.get('organic_results', [])
has_kg = 'knowledge_graph' in data
score = min(len(results) * 10, 50) + (30 if has_kg else 0)
hint = data.get('search_information', {}).get('total_results', 0)
if isinstance(hint, (int, float)) and hint > 10000: score += 20
return {'domain': domain, 'score': score, 'pages': len(results), 'kg': has_kg}
def bulk_check(domains):
results = [probe(d) for d in domains]
results.sort(key=lambda x: x['score'], reverse=True)
with open('scores.csv', 'w', newline='') as f:
w = csv.DictWriter(f, fieldnames=['domain', 'score', 'pages', 'kg'])
w.writeheader()
w.writerows(results)
print(f'Checked {len(domains)} domains for ${len(domains) * 0.005:.2f}')
for r in results[:10]:
print(f" {r['domain']}: {r['score']} pts")
with open('domains.txt') as f:
domains = [l.strip() for l in f if l.strip()]
bulk_check(domains)JavaScript Example
const fs = require('fs');
const API_KEY = process.env.SCAVIO_API_KEY;
const H = { 'x-api-key': API_KEY, 'Content-Type': 'application/json' };
async function probe(domain) {
const data = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST', headers: H,
body: JSON.stringify({ query: `site:${domain}`, country_code: 'us' })
}).then(r => r.json());
const results = data.organic_results || [];
const hasKg = !!data.knowledge_graph;
let score = Math.min(results.length * 10, 50) + (hasKg ? 30 : 0);
const hint = data.search_information?.total_results || 0;
if (hint > 10000) score += 20;
return { domain, score, pages: results.length, kg: hasKg };
}
async function bulkCheck(domains) {
const results = [];
for (const d of domains) {
results.push(await probe(d));
}
results.sort((a, b) => b.score - a.score);
const csv = 'domain,score,pages,kg\n' +
results.map(r => `${r.domain},${r.score},${r.pages},${r.kg}`).join('\n');
fs.writeFileSync('scores.csv', csv);
console.log(`Checked ${domains.length} domains for $${(domains.length * 0.005).toFixed(2)}`);
results.slice(0, 10).forEach(r => console.log(` ${r.domain}: ${r.score} pts`));
}
const domains = fs.readFileSync('domains.txt', 'utf8').split('\n').filter(Boolean);
bulkCheck(domains).catch(console.error);Expected Output
Checked 1000 domains for $5.00
stripe.com: 100 pts
github.com: 100 pts
vercel.com: 80 pts
coolstartup.io: 30 pts
myblog123.com: 10 pts
domain_scores.csv:
domain,score,indexed_pages,has_knowledge_graph,total_results_hint
stripe.com,100,5,True,48500000
github.com,100,5,True,112000000
vercel.com,80,5,True,3200000