ScavioScavio
ProductPricingDocs
Sign InGet Started
  1. Home
  2. Tutorials
  3. How to Build an Automated LLM Visibility Scanner
Tutorial

How to Build an Automated LLM Visibility Scanner

Scan how visible your brand is across LLM-powered search results. Track AI citations, organic presence, and AEO signals.

Get Free API KeyAPI Docs

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.

Python
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.

Python
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.

Python
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

Python
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

JavaScript
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

JSON
  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

Related Tutorials

  • How to Build Automated GEO Visibility Reports
  • How to Track Google AI Mode Responses via SERP API
  • How to Build an AI Mode Visibility Dashboard

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.8+. requests library. A Scavio API key from scavio.dev. Target keywords and brand domain. 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

Use Case

Automated LLM Visibility Tracking

Read more
Best Of

Best LLM Visibility Measurement Tools (May 2026)

Read more
Use Case

AI Search Citation Tracking 2026

Read more
Best Of

Best API for LLM Citation Tracking in 2026

Read more
Solution

Automated LLM Visibility Scanning

Read more
Comparison

Manual Prompt Testing vs Automated LLM Visibility Tools

Read more

Start Building

Scan how visible your brand is across LLM-powered search results. Track AI citations, organic presence, and AEO signals.

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