ScavioScavio
ProductPricingDocs
Sign InGet Started
  1. Home
  2. Tutorials
  3. How to Build a Cost Router for the Cheapest Search Provider
Tutorial

How to Build a Cost Router for the Cheapest Search Provider

Build a smart router that sends each search query to the cheapest provider with available credits. Auto-failover across Scavio, Brave, and Tavily.

Get Free API KeyAPI Docs

When you use multiple search APIs, each has different pricing tiers, free credits, and rate limits. A cost router automatically selects the cheapest available provider for each query, exhausting free tiers first before spending money. This tutorial builds a router across Scavio (250 free/mo, $0.005 after), Brave ($5 free monthly credit), and Tavily (1K free/mo). The router tracks usage, respects rate limits, and falls back gracefully.

Prerequisites

  • Python 3.9+ installed
  • API keys for at least two search providers
  • requests library installed

Walkthrough

Step 1: Define provider configurations

Set up each provider with its pricing, free tier, rate limits, and API call format.

Python
import os

providers = {
    'scavio': {
        'cost_per_query': 0.005,
        'free_monthly': 250,
        'rate_limit_per_sec': 10,
        'api_key': os.environ.get('SCAVIO_API_KEY', ''),
        'priority': 1,  # lower = preferred
    },
    'brave': {
        'cost_per_query': 0.005,
        'free_monthly': 1000,  # $5 free credit = 1K queries
        'rate_limit_per_sec': 5,
        'api_key': os.environ.get('BRAVE_API_KEY', ''),
        'priority': 2,
    },
    'tavily': {
        'cost_per_query': 0.03,
        'free_monthly': 1000,
        'rate_limit_per_sec': 5,
        'api_key': os.environ.get('TAVILY_API_KEY', ''),
        'priority': 3,
    },
}

for name, p in providers.items():
    status = 'configured' if p['api_key'] else 'no key'
    print(f'  {name}: ${p["cost_per_query"]}/query, {p["free_monthly"]} free/mo [{status}]')

Step 2: Build the cost router with usage tracking

The router tracks monthly usage per provider, uses free credits first, then routes to the cheapest paid provider.

Python
import time, requests
from datetime import datetime

class CostRouter:
    def __init__(self, providers: dict):
        self.providers = providers
        self.usage = {name: 0 for name in providers}
        self.month = datetime.now().month
        self.last_call = {name: 0.0 for name in providers}

    def _reset_if_new_month(self):
        current_month = datetime.now().month
        if current_month != self.month:
            self.usage = {name: 0 for name in self.providers}
            self.month = current_month

    def _get_cost(self, name: str) -> float:
        p = self.providers[name]
        if self.usage[name] < p['free_monthly']:
            return 0.0
        return p['cost_per_query']

    def _can_call(self, name: str) -> bool:
        p = self.providers[name]
        if not p['api_key']:
            return False
        elapsed = time.time() - self.last_call[name]
        return elapsed >= (1.0 / p['rate_limit_per_sec'])

    def select_provider(self) -> str:
        self._reset_if_new_month()
        available = [(name, self._get_cost(name), self.providers[name]['priority'])
                     for name in self.providers if self._can_call(name)]
        if not available:
            return list(self.providers.keys())[0]  # fallback to first
        # Sort by cost, then priority
        available.sort(key=lambda x: (x[1], x[2]))
        return available[0][0]

    def search(self, query: str) -> dict:
        provider = self.select_provider()
        cost = self._get_cost(provider)
        results = self._call_provider(provider, query)
        self.usage[provider] += 1
        self.last_call[provider] = time.time()
        return {'results': results, 'provider': provider,
                'cost': cost, 'usage': dict(self.usage)}

Step 3: Implement provider-specific API calls

Add the actual API call logic for each provider. The router dispatches to the correct one automatically.

Python
    def _call_provider(self, name: str, query: str) -> list:
        p = self.providers[name]
        try:
            if name == 'scavio':
                resp = requests.post('https://api.scavio.dev/api/v1/search',
                    headers={'x-api-key': p['api_key'], 'Content-Type': 'application/json'},
                    json={'query': query, 'country_code': 'us', 'num_results': 10},
                    timeout=10)
                return [{'title': r['title'], 'link': r['link'], 'snippet': r.get('snippet', '')}
                        for r in resp.json().get('organic_results', [])]
            elif name == 'brave':
                resp = requests.get('https://api.search.brave.com/res/v1/web/search',
                    headers={'X-Subscription-Token': p['api_key']},
                    params={'q': query, 'count': 10}, timeout=10)
                return [{'title': r['title'], 'link': r['url'], 'snippet': r.get('description', '')}
                        for r in resp.json().get('web', {}).get('results', [])]
            elif name == 'tavily':
                resp = requests.post('https://api.tavily.com/search',
                    json={'api_key': p['api_key'], 'query': query, 'max_results': 10},
                    timeout=10)
                return [{'title': r.get('title', ''), 'link': r['url'], 'snippet': r.get('content', '')}
                        for r in resp.json().get('results', [])]
        except Exception as e:
            print(f'{name} failed: {e}')
            return []
        return []

# Initialize and test
router = CostRouter(providers)
result = router.search('best search API 2026')
print(f'Provider: {result["provider"]}, Cost: ${result["cost"]:.3f}')
print(f'Results: {len(result["results"])}')
print(f'Usage: {result["usage"]}')

Python Example

Python
import requests, os, time

SCAVIO_KEY = os.environ.get('SCAVIO_API_KEY', '')
BRAVE_KEY = os.environ.get('BRAVE_API_KEY', '')
usage = {'scavio': 0, 'brave': 0}

def route_search(query):
    # Use free credits first
    if usage['scavio'] < 250 and SCAVIO_KEY:
        resp = requests.post('https://api.scavio.dev/api/v1/search',
            headers={'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json'},
            json={'query': query, 'country_code': 'us', 'num_results': 10})
        usage['scavio'] += 1
        return {'results': resp.json().get('organic_results', []), 'provider': 'scavio', 'cost': 0}
    if usage['brave'] < 1000 and BRAVE_KEY:
        resp = requests.get('https://api.search.brave.com/res/v1/web/search',
            headers={'X-Subscription-Token': BRAVE_KEY}, params={'q': query, 'count': 10})
        usage['brave'] += 1
        return {'results': resp.json().get('web', {}).get('results', []), 'provider': 'brave', 'cost': 0}
    # Paid fallback
    resp = requests.post('https://api.scavio.dev/api/v1/search',
        headers={'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json'},
        json={'query': query, 'country_code': 'us', 'num_results': 10})
    usage['scavio'] += 1
    return {'results': resp.json().get('organic_results', []), 'provider': 'scavio', 'cost': 0.005}

result = route_search('best search api 2026')
print(f'{result["provider"]}: {len(result["results"])} results, ${result["cost"]}')

JavaScript Example

JavaScript
const SCAVIO_KEY = process.env.SCAVIO_API_KEY;
const BRAVE_KEY = process.env.BRAVE_API_KEY;
const usage = { scavio: 0, brave: 0 };

async function routeSearch(query) {
  if (usage.scavio < 250 && SCAVIO_KEY) {
    const resp = await fetch('https://api.scavio.dev/api/v1/search', {
      method: 'POST',
      headers: { 'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json' },
      body: JSON.stringify({ query, country_code: 'us', num_results: 10 })
    });
    usage.scavio++;
    return { results: (await resp.json()).organic_results || [], provider: 'scavio', cost: 0 };
  }
  if (usage.brave < 1000 && BRAVE_KEY) {
    const resp = await fetch(`https://api.search.brave.com/res/v1/web/search?q=${encodeURIComponent(query)}&count=10`, {
      headers: { 'X-Subscription-Token': BRAVE_KEY }
    });
    usage.brave++;
    return { results: (await resp.json()).web?.results || [], provider: 'brave', cost: 0 };
  }
  const resp = await fetch('https://api.scavio.dev/api/v1/search', {
    method: 'POST',
    headers: { 'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json' },
    body: JSON.stringify({ query, country_code: 'us', num_results: 10 })
  });
  usage.scavio++;
  return { results: (await resp.json()).organic_results || [], provider: 'scavio', cost: 0.005 };
}

routeSearch('best search api').then(r => console.log(`${r.provider}: ${r.results.length} results`));

Expected Output

JSON
  scavio: $0.005/query, 250 free/mo [configured]
  brave: $0.005/query, 1000 free/mo [configured]
  tavily: $0.030/query, 1000 free/mo [no key]

Provider: scavio, Cost: $0.000
Results: 10
Usage: {'scavio': 1, 'brave': 0, 'tavily': 0}

First 250 queries: $0.00 (Scavio free)
Next 1000 queries: $0.00 (Brave free)
Remaining: $0.005/query (cheapest paid)

Related Tutorials

  • How to Calculate the Real Cost Per Agent Search Query
  • How to Benchmark Search API Quality Per Dollar
  • How to Build a Multi-Engine Search Fallback Agent

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.9+ installed. API keys for at least two search providers. requests library installed. 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

Best Of

Best Agent Search APIs with Free Tiers (2026)

Read more
Solution

Rotate Free Tiers Across Search Providers for Zero-Cost Testing

Read more
Glossary

Free Search API Tier Comparison

Read more
Best Of

Best Free Search API Tiers Comparison: May 2026

Read more
Solution

Route Agent Searches to the Cheapest Provider Automatically

Read more
Workflow

Multi-Provider Search Rotation Workflow

Read more

Start Building

Build a smart router that sends each search query to the cheapest provider with available credits. Auto-failover across Scavio, Brave, and Tavily.

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