Scraping Google Maps directly violates terms and leads to bans. SERP APIs return local pack results as structured JSON through compliant channels. This tutorial extracts local business leads by running location-specific searches through Scavio at $0.005 per search, capturing business names, addresses, phones, ratings, and categories.
Prerequisites
- Python 3.8+
- requests library
- A Scavio API key from scavio.dev
- Target locations and categories
Walkthrough
Step 1: Build search matrix
Combine categories with locations.
import os, requests, csv
API_KEY = os.environ['SCAVIO_API_KEY']
H = {'x-api-key': API_KEY, 'Content-Type': 'application/json'}
CATEGORIES = ['plumber', 'dentist', 'restaurant']
LOCATIONS = ['Austin TX', 'Denver CO']
queries = [{'q': f'{cat} near {loc}', 'cat': cat, 'loc': loc}
for cat in CATEGORIES for loc in LOCATIONS]
print(f'{len(queries)} queries, est. ${len(queries) * 0.005:.3f}')Step 2: Extract local business data
Parse local pack results from SERP.
def extract(query_info):
data = requests.post('https://api.scavio.dev/api/v1/search',
headers=H, json={'query': query_info['q'], 'country_code': 'us'}).json()
businesses = []
for p in data.get('local_results', []):
businesses.append({'name': p.get('title', ''), 'address': p.get('address', ''),
'phone': p.get('phone', ''), 'rating': p.get('rating', ''),
'category': query_info['cat'], 'location': query_info['loc']})
return businessesStep 3: Deduplicate and collect
Process all queries and remove duplicates.
def collect_all(queries):
all_biz = []
for i, q in enumerate(queries):
biz = extract(q)
all_biz.extend(biz)
print(f' [{i+1}/{len(queries)}] "{q["q"]}": {len(biz)} businesses')
seen = set()
unique = []
for b in all_biz:
key = f"{b['name'].lower()}:{b['location'].lower()}"
if key not in seen: seen.add(key); unique.append(b)
print(f'Total: {len(unique)} unique businesses')
return unique
businesses = collect_all(queries)Step 4: Export to CSV
Write leads for CRM import.
def export(businesses, output='leads.csv'):
with open(output, 'w', newline='') as f:
w = csv.DictWriter(f, fieldnames=['name', 'category', 'location', 'address', 'phone', 'rating'])
w.writeheader()
w.writerows(businesses)
print(f'Exported {len(businesses)} leads to {output}')
export(businesses)Python Example
import os, requests
API_KEY = os.environ['SCAVIO_API_KEY']
H = {'x-api-key': API_KEY, 'Content-Type': 'application/json'}
def leads(category, location):
data = requests.post('https://api.scavio.dev/api/v1/search',
headers=H, json={'query': f'{category} near {location}', 'country_code': 'us'}).json()
for p in data.get('local_results', [])[:3]:
print(f' {p.get("title", "")} | {p.get("phone", "N/A")} | {p.get("rating", "")} stars')
leads('plumber', 'Austin TX')JavaScript Example
const API_KEY = process.env.SCAVIO_API_KEY;
const H = { 'x-api-key': API_KEY, 'Content-Type': 'application/json' };
async function leads(cat, loc) {
const data = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST', headers: H,
body: JSON.stringify({ query: `${cat} near ${loc}`, country_code: 'us' })
}).then(r => r.json());
(data.local_results || []).slice(0, 3).forEach(p =>
console.log(` ${p.title} | ${p.phone || 'N/A'} | ${p.rating} stars`));
}
leads('plumber', 'Austin TX').catch(console.error);Expected Output
[1/6] "plumber near Austin TX": 8 businesses
[2/6] "plumber near Denver CO": 6 businesses
...
Total: 38 unique businesses
Exported 38 leads to leads.csv