The Problem
Self-hosted SearXNG instances are popular for privacy-focused search, but they suffer from inconsistent result quality. SearXNG aggregates from multiple engines, some of which rate-limit or block the instance IP. Result quality varies by hour and by engine availability. Users experience empty results, slow responses, and missing features like AI Overviews that SearXNG does not support.
The Scavio Solution
Keep SearXNG as the primary search backend for privacy-sensitive queries, but add Scavio as an automatic fallback when SearXNG returns empty or low-quality results. The fallback triggers when SearXNG returns fewer than 3 results or times out. Scavio provides consistent, structured results including AI Overviews. This hybrid approach maintains privacy defaults while ensuring reliable results.
Before
Before the fallback, SearXNG users encountered empty results 10-20% of the time depending on engine availability. They would retry queries or switch to a commercial search engine manually, defeating the purpose of self-hosting SearXNG.
After
After adding Scavio as a fallback, empty-result incidents dropped to under 1%. Users get consistent results without manual retries. SearXNG handles 80-85% of queries, keeping Scavio costs low while ensuring 100% result coverage.
Who It Is For
Self-hosters running SearXNG who need reliable fallback for empty-result scenarios. Privacy-focused teams that want search consistency without fully abandoning self-hosted infrastructure.
Key Benefits
- Empty-result incidents drop from 10-20% to under 1%
- SearXNG handles 80-85% of queries, keeping API costs minimal
- Fallback triggers automatically on empty or low-quality results
- Scavio adds AI Overview data that SearXNG cannot provide
- Privacy-first default with reliable commercial fallback
Python Example
import requests
API_KEY = "your_scavio_api_key"
SEARXNG_URL = "http://localhost:8888/search"
MIN_RESULTS = 3
def hybrid_search(query: str) -> dict:
"""SearXNG primary, Scavio fallback."""
# Try SearXNG first
try:
res = requests.get(SEARXNG_URL, params={"q": query, "format": "json"}, timeout=8)
res.raise_for_status()
searxng_results = res.json().get("results", [])
if len(searxng_results) >= MIN_RESULTS:
return {"source": "searxng", "results": [{"title": r["title"], "link": r["url"], "snippet": r.get("content", "")} for r in searxng_results[:10]]}
except Exception:
pass
# Fallback to Scavio
res = requests.post(
"https://api.scavio.dev/api/v1/search",
headers={"x-api-key": API_KEY},
json={"platform": "google", "query": query, "ai_overview": True},
timeout=15,
)
res.raise_for_status()
data = res.json()
results = [{"title": r.get("title", ""), "link": r.get("link", ""), "snippet": r.get("snippet", "")} for r in data.get("organic", [])[:10]]
return {"source": "scavio", "ai_overview": data.get("ai_overview", {}).get("text", ""), "results": results}
result = hybrid_search("best self-hosted search engine 2026")
print(f"Source: {result['source']}, Results: {len(result['results'])}")JavaScript Example
const API_KEY = "your_scavio_api_key";
async function hybridSearch(query) {
try {
const res = await fetch(`http://localhost:8888/search?q=${encodeURIComponent(query)}&format=json`, { signal: AbortSignal.timeout(8000) });
const data = await res.json();
if ((data.results ?? []).length >= 3) return { source: "searxng", results: data.results.slice(0, 10).map((r) => ({ title: r.title, link: r.url, snippet: r.content ?? "" })) };
} catch {}
const res = await fetch("https://api.scavio.dev/api/v1/search", {
method: "POST",
headers: { "x-api-key": API_KEY, "content-type": "application/json" },
body: JSON.stringify({ platform: "google", query, ai_overview: true }),
});
const data = await res.json();
return { source: "scavio", results: (data.organic ?? []).slice(0, 10).map((r) => ({ title: r.title ?? "", link: r.link ?? "", snippet: r.snippet ?? "" })) };
}
const r = await hybridSearch("best self-hosted search engine 2026");
console.log(`Source: ${r.source}, Results: ${r.results.length}`);Platforms Used
Web search with knowledge graph, PAA, and AI overviews