SearXNG requires Docker, regular updates, and breaks when upstream engines change their HTML. This tutorial migrates your agent from SearXNG to the Scavio search API. You keep the same result format your agent expects but eliminate the maintenance burden. The API costs $0.005/query vs the server costs of running SearXNG.
Prerequisites
- Python 3.8+
- requests library
- A Scavio API key from scavio.dev
- Existing SearXNG integration to replace
Walkthrough
Step 1: Map SearXNG response format to API format
Compare SearXNG's JSON output with the Scavio API response to build a translation layer.
import os, requests, json
API_KEY = os.environ['SCAVIO_API_KEY']
SH = {'x-api-key': API_KEY, 'Content-Type': 'application/json'}
# SearXNG returns this format:
SEARXNG_FORMAT = {
'results': [
{'title': '...', 'url': '...', 'content': '...', 'engine': 'google'},
],
'number_of_results': 10,
}
def scavio_to_searxng_format(query):
"""Call Scavio API and return data in SearXNG format."""
resp = requests.post('https://api.scavio.dev/api/v1/search',
headers=SH, json={'query': query, 'country_code': 'us'}, timeout=10)
resp.raise_for_status()
data = resp.json()
results = []
for r in data.get('organic_results', []):
results.append({
'title': r.get('title', ''),
'url': r.get('link', ''),
'content': r.get('snippet', ''),
'engine': 'scavio',
'score': r.get('position', 0),
})
return {
'results': results,
'number_of_results': len(results),
'query': query,
}
# Test the translation
result = scavio_to_searxng_format('python web framework comparison 2026')
print(f'Query: {result["query"]}')
print(f'Results: {result["number_of_results"]}')
for r in result['results'][:3]:
print(f' [{r["engine"]}] {r["title"][:50]}')
print(f' {r["url"]}')Step 2: Create a drop-in replacement function
Replace the SearXNG call with the API call, keeping the same function signature.
# BEFORE: SearXNG call
# def search(query, num_results=10):
# resp = requests.get('http://localhost:8888/search',
# params={'q': query, 'format': 'json', 'engines': 'google'})
# return resp.json()['results'][:num_results]
# AFTER: Scavio API call (same interface)
def search(query, num_results=10):
"""Drop-in replacement for SearXNG search."""
resp = requests.post('https://api.scavio.dev/api/v1/search',
headers=SH, json={'query': query, 'country_code': 'us'}, timeout=10)
resp.raise_for_status()
data = resp.json()
return [{
'title': r.get('title', ''),
'url': r.get('link', ''),
'content': r.get('snippet', ''),
'engine': 'scavio',
} for r in data.get('organic_results', [])[:num_results]]
# Your existing code works without changes:
results = search('best python web framework 2026', num_results=5)
for r in results:
print(f' {r["title"][:50]} ({r["engine"]})')
print(f' {r["url"]}')
print(f'\nNo Docker. No maintenance. $0.005/query.')Step 3: Add platform-specific search for richer results
Unlike SearXNG, the API supports platform-specific queries for Reddit, YouTube, and more.
def search_platform(query, platform=None, num_results=5):
"""Extended search with platform support (not possible with SearXNG)."""
body = {'query': query, 'country_code': 'us'}
if platform:
body['platform'] = platform
resp = requests.post('https://api.scavio.dev/api/v1/search',
headers=SH, json=body, timeout=10)
resp.raise_for_status()
data = resp.json()
return [{'title': r.get('title', ''), 'url': r.get('link', ''),
'content': r.get('snippet', '')}
for r in data.get('organic_results', [])[:num_results]]
# SearXNG could only do web search. API does platform-specific:
print('=== Google Web ===')
for r in search_platform('FastAPI deployment', num_results=3):
print(f' {r["title"][:50]}')
print('\n=== Reddit ===')
for r in search_platform('FastAPI deployment', platform='reddit', num_results=3):
print(f' {r["title"][:50]}')
print('\n=== YouTube ===')
for r in search_platform('FastAPI deployment', platform='youtube', num_results=3):
print(f' {r["title"][:50]}')
print(f'\nSearXNG: $20-50/mo server + maintenance')
print(f'Scavio API: $0.005/query, zero maintenance')Python Example
import os, requests
SH = {'x-api-key': os.environ['SCAVIO_API_KEY'], 'Content-Type': 'application/json'}
# Drop-in SearXNG replacement
def search(query, num_results=10):
data = requests.post('https://api.scavio.dev/api/v1/search',
headers=SH, json={'query': query, 'country_code': 'us'}, timeout=10).json()
return [{'title': r['title'], 'url': r['link'], 'content': r.get('snippet', '')}
for r in data.get('organic_results', [])[:num_results]]
for r in search('SearXNG alternative api', 5):
print(f'{r["title"][:50]}')JavaScript Example
const SH = { 'x-api-key': process.env.SCAVIO_API_KEY, 'Content-Type': 'application/json' };
// Drop-in SearXNG replacement
async function search(query, numResults = 10) {
const data = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST', headers: SH,
body: JSON.stringify({ query, country_code: 'us' })
}).then(r => r.json());
return (data.organic_results || []).slice(0, numResults)
.map(r => ({ title: r.title, url: r.link, content: r.snippet }));
}
const results = await search('SearXNG alternative', 5);
results.forEach(r => console.log(r.title));Expected Output
Query: python web framework comparison 2026
Results: 10
[scavio] FastAPI vs Django vs Flask: Python Web Framewor
https://...
=== Google Web ===
FastAPI Deployment Guide: Docker, AWS, and GCP
=== Reddit ===
r/Python - Best way to deploy FastAPI in production
=== YouTube ===
FastAPI Deployment Tutorial 2026 - Full Guide
SearXNG: $20-50/mo server + maintenance
Scavio API: $0.005/query, zero maintenance