SerpAPI Rate Limiting and Budget Drain: Alternatives
SerpAPI monthly credit limits and expiration create waste. Pay-as-you-go alternatives with higher credit-per-dollar ratios.
SerpAPI rate limits at the plan level -- once you exhaust your monthly search credits, you either stop or upgrade. At $75/mo for 5K searches ($0.015/search), a single automated pipeline can burn through the budget in days. Unused credits expire at month end. Alternatives with pay-as-you-go pricing or higher credit-per-dollar ratios solve both the rate limiting and the budget drain.
How SerpAPI rate limiting works
SerpAPI does not have a per-second rate limit like most APIs. Instead, it has a monthly search quota. The $75/mo plan gives 5,000 searches. The $275/mo plan gives 30,000. When you hit the limit, requests return an error until the next billing cycle. There is no burst capacity, no overage billing, no way to add credits mid-cycle without upgrading to the next tier.
The budget drain scenario
# Common mistake: unthrottled pipeline burns SerpAPI budget
import time
def naive_pipeline(keywords: list):
"""This burns 5,000 credits in 2 hours."""
for kw in keywords:
# No delay, no budget tracking
result = serpapi_search(kw) # 1 credit each
process(result)
# 5,000 keywords = 5,000 credits = monthly limit hit
# Better: budget-aware pipeline
def budget_aware_pipeline(keywords: list, daily_limit: int = 200):
"""Spread queries across the month."""
today_count = 0
for kw in keywords:
if today_count >= daily_limit:
print(f"Daily limit reached ({daily_limit}). Resuming tomorrow.")
break
result = serpapi_search(kw)
today_count += 1
time.sleep(1) # pace requestsAlternatives compared
- Serper: $50/yr Dev (50K searches), $50/mo Pro (500K). Google only. No rate limit per minute.
- Scavio: $0.005/credit, $30/mo for 7K credits. Pay-as-you-go available. Credits carry over.
- DataForSEO: $0.002/query live mode, $50 minimum deposit. No monthly expiry.
- Brave: $5/1K queries, $5 free credit/mo. Pay-per-use.
- Tavily: $30/mo Researcher, $100/mo Startup. ~$0.008/query.
Migration from SerpAPI
import os, requests
# Before: SerpAPI
# from serpapi import GoogleSearch
# search = GoogleSearch({"q": query, "api_key": os.environ["SERPAPI_KEY"]})
# results = search.get_dict()
# organic = results.get("organic_results", [])
# After: Scavio (same data shape, different auth)
def search(query: str, num_results: int = 10) -> dict:
resp = requests.post(
"https://api.scavio.dev/api/v1/search",
headers={"x-api-key": os.environ["SCAVIO_API_KEY"]},
json={"query": query, "num_results": num_results,
"include_ai_overview": True},
)
return resp.json()
# Response fields map directly:
# SerpAPI: organic_results[].title, .link, .snippet
# Scavio: organic_results[].title, .link, .snippet
# Bonus: Scavio includes ai_overview, people_also_askBudget tracking wrapper
class BudgetTracker:
def __init__(self, monthly_budget_credits: int):
self.budget = monthly_budget_credits
self.used = 0
def search(self, query: str, **kwargs) -> dict:
if self.used >= self.budget:
raise Exception(f"Budget exhausted: {self.used}/{self.budget}")
resp = requests.post(
"https://api.scavio.dev/api/v1/search",
headers={"x-api-key": os.environ["SCAVIO_API_KEY"]},
json={"query": query, **kwargs},
)
self.used += 1
return resp.json()
@property
def remaining(self):
return self.budget - self.used
# Set budget to match your plan
tracker = BudgetTracker(monthly_budget_credits=7000) # $30 plan
result = tracker.search("best crm 2026")
print(f"Credits remaining: {tracker.remaining}")Cost at common volumes
Monthly cost for 10,000 searches:
- SerpAPI: $275/mo (30K plan, 20K wasted)
- Serper: $50/mo Pro (500K, massive overshoot)
- Scavio: $50/mo (10K credits at $0.005)
- DataForSEO: $20 (10K at $0.002)
- Tavily: $100/mo Startup plan
- Brave: $50 (10K at $5/1K)
Key takeaway
SerpAPI credit expiration and tier-based limits create waste on both ends: you either hit the limit early or pay for searches you never use. Pay-as-you-go models or providers with higher credit-per-dollar ratios eliminate both problems. The migration is a one-function swap in most codebases.