Google Maps Leads: API Not Scraper
Google Maps scraping violates ToS. SERP local pack API returns structured business data at $0.005/query. Legal, reliable, and no proxy management.
Google Maps scraping violates Google's Terms of Service and gets your IP addresses blocked. The official Google Places API works but costs $17-40 per 1,000 requests depending on the endpoint. The alternative: a SERP API that returns Google's local pack results as structured JSON at $0.005/query. Legal, reliable, and 3-8x cheaper than the official Places API for lead generation use cases.
Why scraping Google Maps fails at scale
- CAPTCHAs trigger after ~50-100 requests from the same IP range
- Residential proxies add $50-200/mo to costs
- Google actively detects and blocks headless browsers
- HTML structure changes break parsers every few weeks
- ToS violation creates legal risk for your business
SERP local pack results: structured business data
import requests, os
H = {"x-api-key": os.environ["SCAVIO_API_KEY"]}
def find_local_businesses(query: str, location: str = None):
"""Get structured business data from Google local pack."""
payload = {"query": query, "platform": "google"}
if location:
payload["location"] = location
resp = requests.post("https://api.scavio.dev/api/v1/search",
headers=H, json=payload)
data = resp.json()
businesses = []
for r in data.get("local_results", []):
businesses.append({
"name": r.get("title"),
"rating": r.get("rating"),
"reviews": r.get("reviews"),
"address": r.get("address"),
"phone": r.get("phone"),
"website": r.get("website"),
"type": r.get("type"),
})
return businesses
# $0.005 per search
leads = find_local_businesses("plumber", "Austin TX")
for b in leads:
print(f"{b['name']} - {b['rating']} stars ({b['reviews']} reviews)")Building a lead generation pipeline
import csv, time
def generate_leads(business_type: str, cities: list):
"""Generate leads across multiple cities."""
all_leads = []
for city in cities:
query = f"{business_type} in {city}"
businesses = find_local_businesses(query, city)
for b in businesses:
b["city"] = city
b["search_query"] = query
all_leads.append(b)
time.sleep(0.5) # Rate limiting
return all_leads
def export_to_csv(leads: list, filename: str):
"""Export leads to CSV for CRM import."""
if not leads:
return
with open(filename, "w", newline="") as f:
writer = csv.DictWriter(f, fieldnames=leads[0].keys())
writer.writeheader()
writer.writerows(leads)
# 10 cities x $0.005 = $0.05 for lead generation across 10 cities
cities = ["Austin TX", "Dallas TX", "Houston TX", "San Antonio TX"]
leads = generate_leads("HVAC contractor", cities)
export_to_csv(leads, "hvac_leads.csv")
print(f"Generated {len(leads)} leads across {len(cities)} cities")Cost comparison
- Google Places API (Nearby Search): $32 per 1,000 requests
- Google Places API (Text Search): $40 per 1,000 requests
- SERP API local pack: $5 per 1,000 requests (Scavio at $0.005/query)
- Google Maps scraping + proxies: $50-200/mo for proxy, plus maintenance time
Limitations of the local pack approach
Local pack results typically show 3-5 businesses per query. The Google Places API returns up to 20 per request. If you need comprehensive coverage of every business in a category/area, the Places API has better coverage. If you need the top-rated, most-visible businesses (the ones customers actually find on Google), local pack results are exactly that -- the businesses Google surfaces first.