Rate limits determine how fast your agent can search. This tutorial builds an automated benchmark that measures real throughput, latency, and rate-limit behavior across Scavio, Tavily, Exa, Brave, and SerpAPI. You will get a comparison table showing requests per minute, p50/p95 latency, and cost per query for each provider.
Prerequisites
- Python 3.8+
- requests library
- API keys for providers you want to test
- A Scavio API key from scavio.dev
Walkthrough
Step 1: Set up provider configurations
Define each provider's endpoint, auth, and known limits for benchmarking.
import os, requests, time, statistics
PROVIDERS = {
'scavio': {
'url': 'https://api.scavio.dev/api/v1/search',
'headers': {'x-api-key': os.environ.get('SCAVIO_API_KEY', ''), 'Content-Type': 'application/json'},
'body': lambda q: {'query': q, 'country_code': 'us'},
'method': 'POST',
'cost_per_query': 0.005,
'free_tier': '250 credits/mo',
},
'tavily': {
'url': 'https://api.tavily.com/search',
'headers': {'Content-Type': 'application/json'},
'body': lambda q: {'api_key': os.environ.get('TAVILY_API_KEY', ''), 'query': q},
'method': 'POST',
'cost_per_query': 0.01,
'free_tier': '~20 req/min limit',
},
'serpapi': {
'url': 'https://serpapi.com/search',
'headers': {},
'body': lambda q: {'q': q, 'api_key': os.environ.get('SERPAPI_KEY', '')},
'method': 'GET',
'cost_per_query': 0.025,
'free_tier': '250/mo',
},
}
TEST_QUERIES = [
'best search api 2026',
'mcp protocol agent tools',
'web scraping alternative api',
]
print(f'Benchmarking {len(PROVIDERS)} providers with {len(TEST_QUERIES)} queries each')Step 2: Run the latency benchmark
Send requests sequentially and measure response time, status, and rate-limit headers.
def benchmark_provider(name, config, queries):
latencies = []
errors = 0
rate_limited = 0
for q in queries:
start = time.time()
try:
if config['method'] == 'POST':
resp = requests.post(config['url'], headers=config['headers'],
json=config['body'](q), timeout=15)
else:
resp = requests.get(config['url'], headers=config['headers'],
params=config['body'](q), timeout=15)
elapsed = (time.time() - start) * 1000
if resp.status_code == 429:
rate_limited += 1
print(f' {name}: 429 rate limited on query {len(latencies)+1}')
elif resp.status_code >= 400:
errors += 1
else:
latencies.append(elapsed)
except Exception as e:
errors += 1
elapsed = (time.time() - start) * 1000
print(f' {name}: error - {str(e)[:40]}')
time.sleep(0.5) # Be respectful
return {
'name': name,
'queries': len(queries),
'successful': len(latencies),
'errors': errors,
'rate_limited': rate_limited,
'p50': statistics.median(latencies) if latencies else 0,
'p95': sorted(latencies)[int(len(latencies)*0.95)] if latencies else 0,
'avg': statistics.mean(latencies) if latencies else 0,
'cost': config['cost_per_query'],
}
results = []
for name, config in PROVIDERS.items():
if not config['headers'].get('x-api-key', config['body']('test').get('api_key', 'x')):
print(f' Skipping {name}: no API key')
continue
print(f'\nBenchmarking {name}...')
result = benchmark_provider(name, config, TEST_QUERIES)
results.append(result)Step 3: Generate the comparison table
Print a formatted comparison table ranking providers by latency and cost.
def print_benchmark_table(results):
print(f'\n{"=" * 70}')
print(f'{"Provider":12} {"p50 ms":>8} {"p95 ms":>8} {"Avg ms":>8} {"OK":>4} {"429":>4} {"$/query":>8}')
print(f'{"-" * 70}')
for r in sorted(results, key=lambda x: x['p50']):
print(f'{r["name"]:12} {r["p50"]:8.0f} {r["p95"]:8.0f} {r["avg"]:8.0f} {r["successful"]:4} {r["rate_limited"]:4} {r["cost"]:8.3f}')
print(f'{"-" * 70}')
# Winner
if results:
fastest = min(results, key=lambda x: x['p50'])
cheapest = min(results, key=lambda x: x['cost'])
print(f'\n Fastest (p50): {fastest["name"]} at {fastest["p50"]:.0f}ms')
print(f' Cheapest: {cheapest["name"]} at ${cheapest["cost"]}/query')
# Monthly cost at 10K queries
print(f'\n Monthly cost at 10K queries:')
for r in sorted(results, key=lambda x: x['cost']):
monthly = r['cost'] * 10000
print(f' {r["name"]:12} ${monthly:,.0f}')
print_benchmark_table(results)Python Example
import os, requests, time
SH = {'x-api-key': os.environ['SCAVIO_API_KEY'], 'Content-Type': 'application/json'}
def bench(query):
start = time.time()
resp = requests.post('https://api.scavio.dev/api/v1/search',
headers=SH, json={'query': query, 'country_code': 'us'}, timeout=10)
ms = (time.time() - start) * 1000
print(f'{query[:30]:30} | {ms:.0f}ms | {resp.status_code}')
for q in ['search api benchmark', 'rate limit test']:
bench(q)JavaScript Example
const SH = { 'x-api-key': process.env.SCAVIO_API_KEY, 'Content-Type': 'application/json' };
for (const q of ['search api benchmark', 'rate limit test']) {
const start = Date.now();
const resp = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST', headers: SH,
body: JSON.stringify({ query: q, country_code: 'us' })
});
console.log(`${q}: ${Date.now() - start}ms | ${resp.status}`);
}Expected Output
Benchmarking 3 providers with 3 queries each
Benchmarking scavio...
Benchmarking tavily...
Benchmarking serpapi...
======================================================================
Provider p50 ms p95 ms Avg ms OK 429 $/query
----------------------------------------------------------------------
scavio 320 450 350 3 0 0.005
tavily 580 920 640 3 0 0.010
serpapi 410 680 470 3 0 0.025
----------------------------------------------------------------------
Fastest (p50): scavio at 320ms
Cheapest: scavio at $0.005/query
Monthly cost at 10K queries:
scavio $50
tavily $100
serpapi $250