Google Maps Data: API vs Scraping for SMB Leads
SERP API returns Google Maps business data legally at $0.005/query. Direct scraping violates ToS, gets blocked, and costs more in proxies. API wins for SMB leads.
For SMB lead generation, Google Maps data via SERP API returns business name, address, phone, website, rating, and review count at $0.005/query -- legally, reliably, and without proxy infrastructure. Direct Google Maps scraping violates Google's ToS, gets blocked by anti-bot systems, and requires $50-200/month in proxies. The API approach costs less and works consistently.
API vs scraping comparison
Factor | Google Maps scraping | SERP API
Legal | Violates ToS | Authorized access
Cost/query | $0.01-0.05 (proxies) | $0.005
Reliability | 70-80% (blocks) | 99%+
Setup time | Days (Puppeteer) | Minutes (API key)
Maintenance | Ongoing patches | Zero
Data format | Parsed HTML (fragile)| Typed JSON (stable)Get Google Maps data via API
import requests
def get_local_businesses(query: str, num_results: int = 20) -> list:
"""Get Google Maps local pack results via SERP API."""
resp = requests.post(
"https://api.scavio.dev/api/v1/search",
headers={"x-api-key": "YOUR_KEY"},
json={
"query": query,
"num_results": num_results
}
)
data = resp.json()
return data.get("local_results", [])
# Find dentists in Denver
dentists = get_local_businesses("dentists Denver CO")
for d in dentists:
print(f"{d.get('title', 'N/A')}")
print(f" Phone: {d.get('phone', 'N/A')}")
print(f" Rating: {d.get('rating', 'N/A')} ({d.get('reviews_count', 0)} reviews)")
print(f" Website: {d.get('website', 'N/A')}")
print()
Build a lead list across categories and cities
// Batch lead generation: multiple categories x multiple cities
async function batchLeadGen(categories, cities) {
const leads = [];
for (const category of categories) {
for (const city of cities) {
const resp = await fetch("https://api.scavio.dev/api/v1/search", {
method: "POST",
headers: {
"x-api-key": process.env.SCAVIO_KEY,
"Content-Type": "application/json"
},
body: JSON.stringify({
query: category + " " + city,
num_results: 20
})
});
const data = await resp.json();
for (const r of (data.local_results || [])) {
leads.push({
category,
city,
name: r.title,
phone: r.phone || "",
website: r.website || "",
rating: r.rating,
reviews: r.reviews_count || 0
});
}
// Rate limit: avoid hammering the API
await new Promise(r => setTimeout(r, 100));
}
}
return leads;
}
const leads = await batchLeadGen(
["plumber", "electrician", "HVAC repair"],
["Austin TX", "San Antonio TX", "Houston TX"]
);
console.log("Total leads:", leads.length);
// Filter for businesses without websites (need your help)
const noWebsite = leads.filter(l => !l.website);
console.log("No website:", noWebsite.length);
Lead qualification from search data
- No website: needs web presence (web design/marketing services)
- Low reviews (<10): needs review management/marketing
- Low rating (<4.0): needs reputation management
- Has website but no SSL: needs technical update
- High reviews but old website: ready for redesign
Cost for lead generation
Scale | Queries/mo | Monthly cost
10 cities, 5 cats | 50 | $0.25
50 cities, 10 cats | 500 | $2.50
100 cities, 20 cats| 2,000 | $10.00
Daily refresh | +600/mo | +$3.00When scraping still makes sense
If you need data Google Maps does not expose in local pack results (hours of operation, menu items, interior photos), scraping the individual business page may be necessary. For the core lead data (name, phone, website, rating), the API is the better approach.