LLMs now power search experiences across Google AI Mode, Bing Copilot, and Perplexity. Your brand's visibility in these AI-generated responses directly impacts traffic. This scanner checks your brand presence across search results that feed LLM responses, tracking AI citations, featured snippets, and People Also Ask data. Each brand scan costs $0.025 across 5 keywords.
Prerequisites
- Python 3.8+
- requests library
- A Scavio API key from scavio.dev
- Target keywords and brand domain
Walkthrough
Step 1: Scan LLM visibility signals across keywords
Check multiple search features that LLMs use to generate responses.
import os, requests, json
from datetime import datetime
from collections import defaultdict
API_KEY = os.environ['SCAVIO_API_KEY']
SH = {'x-api-key': API_KEY, 'Content-Type': 'application/json'}
BRAND_DOMAIN = 'scavio.dev'
KEYWORDS = [
'best search api for ai agents',
'mcp search tool setup',
'web search api comparison 2026',
'serp api free tier options',
'search api for rag pipeline',
]
def scan_llm_visibility(keyword, domain):
data = requests.post('https://api.scavio.dev/api/v1/search',
headers=SH, json={'query': keyword, 'country_code': 'us'}, timeout=10).json()
domain_l = domain.lower()
# AI Overview / Answer Box (feeds LLM responses)
ai = data.get('ai_overview', data.get('answer_box', {}))
ai_cited = domain_l in json.dumps(ai).lower() if ai else False
# Featured Snippet (high-priority LLM source)
featured = data.get('featured_snippet', {})
in_featured = domain_l in json.dumps(featured).lower() if featured else False
# People Also Ask (LLM follow-up context)
paa = data.get('people_also_ask', [])
in_paa = any(domain_l in json.dumps(q).lower() for q in paa)
# Organic position (base visibility)
organic = data.get('organic_results', [])
org_pos = next((i+1 for i, r in enumerate(organic) if domain_l in r.get('link', '').lower()), None)
# Top 3 domains (who LLMs are citing)
top3 = [r.get('displayed_link', '').split('/')[0] for r in organic[:3]]
return {
'keyword': keyword,
'ai_cited': ai_cited,
'has_ai_overview': bool(ai),
'in_featured': in_featured,
'in_paa': in_paa,
'organic_pos': org_pos,
'top3_domains': top3,
}
scans = []
for kw in KEYWORDS:
scan = scan_llm_visibility(kw, BRAND_DOMAIN)
scans.append(scan)
signals = []
if scan['ai_cited']: signals.append('AI')
if scan['in_featured']: signals.append('FS')
if scan['in_paa']: signals.append('PAA')
pos = f'#{scan["organic_pos"]}' if scan['organic_pos'] else '-'
print(f' {kw[:40]:40} | {pos:5} | {", ".join(signals) or "none"}')
print(f'\nCost: ${len(KEYWORDS) * 0.005:.3f}')Step 2: Calculate LLM visibility score
Aggregate scan data into a composite visibility score.
def calculate_llm_score(scans, domain):
total = len(scans)
# Component scores
ai_cited = sum(1 for s in scans if s['ai_cited'])
has_ai = sum(1 for s in scans if s['has_ai_overview'])
featured = sum(1 for s in scans if s['in_featured'])
paa = sum(1 for s in scans if s['in_paa'])
top3 = sum(1 for s in scans if s['organic_pos'] and s['organic_pos'] <= 3)
top10 = sum(1 for s in scans if s['organic_pos'] and s['organic_pos'] <= 10)
# Weighted score (100 max)
ai_score = (ai_cited / max(has_ai, 1)) * 35 # AI citations worth most
featured_score = (featured / total) * 25 # Featured snippets
paa_score = (paa / total) * 15 # PAA presence
organic_score = (top3 / total) * 15 + (top10 / total) * 10 # Organic ranking
total_score = ai_score + featured_score + paa_score + organic_score
print(f'\n=== LLM Visibility Score: {domain} ===')
print(f' Overall: {total_score:.0f}/100')
print(f'\n Component Breakdown:')
print(f' AI Citations: {ai_score:.0f}/35 ({ai_cited}/{has_ai} keywords with AI)')
print(f' Featured Snippet: {featured_score:.0f}/25 ({featured}/{total} keywords)')
print(f' People Also Ask: {paa_score:.0f}/15 ({paa}/{total} keywords)')
print(f' Organic Top 3: {top3}/{total} keywords')
print(f' Organic Top 10: {top10}/{total} keywords')
return {
'total_score': total_score,
'ai_score': ai_score,
'featured_score': featured_score,
'paa_score': paa_score,
'organic_score': organic_score,
}
visibility = calculate_llm_score(scans, BRAND_DOMAIN)Step 3: Generate actionable recommendations
Identify gaps and provide specific actions to improve LLM visibility.
def generate_recommendations(scans, visibility, domain):
print(f'\n{"=" * 60}')
print(f' LLM VISIBILITY SCANNER REPORT')
print(f' Brand: {domain} | Date: {datetime.now().strftime("%Y-%m-%d")}')
print(f' Score: {visibility["total_score"]:.0f}/100')
print(f'{"=" * 60}')
recs = []
# AI citation gaps
ai_gaps = [s['keyword'] for s in scans if s['has_ai_overview'] and not s['ai_cited']]
if ai_gaps:
recs.append({
'priority': 'HIGH',
'action': 'Optimize for AI citations',
'keywords': ai_gaps,
})
# Featured snippet opportunities
fs_gaps = [s['keyword'] for s in scans if not s['in_featured'] and s['organic_pos'] and s['organic_pos'] <= 5]
if fs_gaps:
recs.append({
'priority': 'MEDIUM',
'action': 'Target featured snippets (already ranking top 5)',
'keywords': fs_gaps,
})
# Not ranking at all
absent = [s['keyword'] for s in scans if not s['organic_pos']]
if absent:
recs.append({
'priority': 'HIGH',
'action': 'Create content (not ranking)',
'keywords': absent,
})
print(f'\n Recommendations ({len(recs)}):')
for r in recs:
print(f'\n [{r["priority"]:6}] {r["action"]}')
for kw in r['keywords'][:3]:
print(f' - {kw}')
# Competitor visibility
print(f'\n Top Competitors (by AI/organic presence):')
all_domains = defaultdict(int)
for s in scans:
for d in s.get('top3_domains', []):
if d and domain not in d:
all_domains[d] += 1
for d, count in sorted(all_domains.items(), key=lambda x: -x[1])[:5]:
print(f' {d:30} | Top 3 in {count}/{len(scans)} keywords')
print(f'\n Scan cost: ${len(scans) * 0.005:.3f}')
print(f' Monthly (daily): ${len(scans) * 0.005 * 30:.2f}')
generate_recommendations(scans, visibility, BRAND_DOMAIN)Python Example
import os, requests, json
SH = {'x-api-key': os.environ['SCAVIO_API_KEY'], 'Content-Type': 'application/json'}
def llm_visibility(keyword, domain):
data = requests.post('https://api.scavio.dev/api/v1/search',
headers=SH, json={'query': keyword, 'country_code': 'us'}, timeout=10).json()
ai = data.get('ai_overview', data.get('answer_box', {}))
cited = domain.lower() in json.dumps(ai).lower() if ai else False
pos = next((i+1 for i, r in enumerate(data.get('organic_results', [])) if domain in r.get('link', '')), None)
print(f'{keyword[:35]:35} | AI: {cited} | Pos: {pos or "-"}')
llm_visibility('best search api', 'scavio.dev')JavaScript Example
const SH = { 'x-api-key': process.env.SCAVIO_API_KEY, 'Content-Type': 'application/json' };
const data = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST', headers: SH,
body: JSON.stringify({ query: 'best search api', country_code: 'us' })
}).then(r => r.json());
const ai = data.ai_overview || data.answer_box || {};
const cited = JSON.stringify(ai).toLowerCase().includes('scavio');
const pos = (data.organic_results || []).findIndex(r => r.link?.includes('scavio.dev'));
console.log(`AI cited: ${cited} | Position: ${pos >= 0 ? pos + 1 : 'absent'}`);Expected Output
best search api for ai agents | #3 | AI
mcp search tool setup | #2 | AI, FS
web search api comparison 2026 | #5 | none
serp api free tier options | #4 | PAA
search api for rag pipeline | #6 | none
Cost: $0.025
=== LLM Visibility Score: scavio.dev ===
Overall: 52/100
Component Breakdown:
AI Citations: 18/35 (2/4 keywords with AI)
Featured Snippet: 5/25 (1/5 keywords)
People Also Ask: 3/15 (1/5 keywords)
Organic Top 3: 2/5 keywords
============================================================
LLM VISIBILITY SCANNER REPORT
Brand: scavio.dev | Date: 2026-05-21
Score: 52/100
============================================================
Recommendations (2):
[HIGH ] Optimize for AI citations
- web search api comparison 2026
- serp api free tier options
Scan cost: $0.025
Monthly (daily): $0.75