Tutorial

How to Build Local Pack Lead Generation

Extract business name, rating, reviews, and phone from Google local pack results. Python lead gen pipeline at $0.005/query.

Google local pack results contain ready-made B2B leads: business name, address, phone number, rating, and review count. Extracting this data through a SERP API at $0.005 per query produces qualified local business leads at a fraction of the cost of manual prospecting or dedicated lead databases. This pipeline generates local leads by category and location.

Prerequisites

  • Python 3.8+
  • requests library
  • A Scavio API key from scavio.dev
  • Target business categories and locations

Walkthrough

Step 1: Search for local businesses by category

Query Google for local pack results in a target category and location.

Python
import os, requests, json, csv

API_KEY = os.environ['SCAVIO_API_KEY']
SH = {'x-api-key': API_KEY, 'Content-Type': 'application/json'}

def search_local(category, location):
    data = requests.post('https://api.scavio.dev/api/v1/search',
        headers=SH, json={'query': f'{category} in {location}', 'country_code': 'us'}).json()
    local = data.get('local_results', [])
    leads = []
    for r in local:
        leads.append({
            'name': r.get('title', r.get('name', '')),
            'address': r.get('address', ''),
            'phone': r.get('phone', ''),
            'rating': r.get('rating', 'N/A'),
            'reviews': r.get('reviews', 0),
            'category': category,
            'location': location
        })
    print(f'{category} in {location}: {len(leads)} local results')
    return leads

leads = search_local('plumbers', 'Austin TX')
for l in leads[:3]:
    print(f'  {l["name"]} | {l["rating"]} ({l["reviews"]} reviews) | {l["phone"]}')

Step 2: Expand to multiple categories and locations

Scale the search across multiple verticals and cities.

Python
CATEGORIES = ['plumbers', 'electricians', 'hvac contractors', 'roofers']
LOCATIONS = ['Austin TX', 'Dallas TX', 'Houston TX']

def batch_local_search(categories, locations):
    all_leads = []
    queries = 0
    for cat in categories:
        for loc in locations:
            leads = search_local(cat, loc)
            all_leads.extend(leads)
            queries += 1
    cost = queries * 0.005
    print(f'\nTotal: {len(all_leads)} leads from {queries} queries. Cost: ${cost:.3f}')
    return all_leads

all_leads = batch_local_search(CATEGORIES, LOCATIONS)

# Deduplicate by name
seen = set()
unique = []
for lead in all_leads:
    key = lead['name'].lower().strip()
    if key not in seen:
        seen.add(key)
        unique.append(lead)
print(f'Unique leads: {len(unique)} (removed {len(all_leads) - len(unique)} duplicates)')

Step 3: Score and qualify leads

Rank leads by quality signals: rating, reviews, and completeness.

Python
def score_lead(lead):
    score = 0
    rating = float(lead.get('rating', 0)) if lead.get('rating') != 'N/A' else 0
    reviews = int(lead.get('reviews', 0))
    if rating >= 4.5: score += 30
    elif rating >= 4.0: score += 20
    elif rating >= 3.5: score += 10
    if reviews >= 100: score += 25
    elif reviews >= 50: score += 20
    elif reviews >= 20: score += 10
    if lead.get('phone'): score += 20
    if lead.get('address'): score += 15
    if lead.get('website'): score += 10
    return score

for lead in unique:
    lead['score'] = score_lead(lead)

unique.sort(key=lambda x: x['score'], reverse=True)
print(f'\nTop qualified leads:')
for l in unique[:10]:
    print(f'  [{l["score"]:3}] {l["name"]:30} | {l["rating"]} ({l["reviews"]} reviews) | {l["category"]}')

Step 4: Export leads to CSV

Save qualified leads to CSV for import into your CRM.

Python
def export_csv(leads, filename='local_leads.csv', min_score=30):
    qualified = [l for l in leads if l.get('score', 0) >= min_score]
    with open(filename, 'w', newline='') as f:
        writer = csv.DictWriter(f, fieldnames=['name', 'category', 'location',
            'rating', 'reviews', 'phone', 'address', 'score'])
        writer.writeheader()
        for l in qualified:
            writer.writerow({k: l.get(k, '') for k in writer.fieldnames})
    total_queries = len(CATEGORIES) * len(LOCATIONS)
    cost = total_queries * 0.005
    print(f'\nExported {len(qualified)} qualified leads to {filename}')
    print(f'  Filtered from {len(leads)} total (min score: {min_score})')
    print(f'  Total cost: ${cost:.3f}')
    print(f'  Cost per lead: ${cost/len(qualified):.4f}' if qualified else '  No qualified leads')

export_csv(unique)

Python Example

Python
import os, requests
SH = {'x-api-key': os.environ['SCAVIO_API_KEY'], 'Content-Type': 'application/json'}

def local_leads(category, location):
    data = requests.post('https://api.scavio.dev/api/v1/search',
        headers=SH, json={'query': f'{category} in {location}', 'country_code': 'us'}).json()
    for r in data.get('local_results', [])[:5]:
        print(f'{r.get("title","")} | {r.get("rating","N/A")} | {r.get("phone","N/A")}')
    print(f'Cost: $0.005')

local_leads('plumbers', 'Austin TX')

JavaScript Example

JavaScript
const SH = { 'x-api-key': process.env.SCAVIO_API_KEY, 'Content-Type': 'application/json' };
async function localLeads(category, location) {
  const data = await fetch('https://api.scavio.dev/api/v1/search', {
    method: 'POST', headers: SH,
    body: JSON.stringify({ query: `${category} in ${location}`, country_code: 'us' })
  }).then(r => r.json());
  (data.local_results || []).slice(0, 5).forEach(r =>
    console.log(`${r.title || r.name} | ${r.rating || 'N/A'} | ${r.phone || 'N/A'}`)
  );
}
localLeads('plumbers', 'Austin TX').catch(console.error);

Expected Output

JSON
plumbers in Austin TX: 8 local results
  ABC Plumbing | 4.8 (234 reviews) | (512) 555-0123
  Radiant Plumbing | 4.9 (1,456 reviews) | (512) 555-0456
  Mr. Rooter | 4.5 (89 reviews) | (512) 555-0789

Total: 48 leads from 12 queries. Cost: $0.060
Unique leads: 42 (removed 6 duplicates)

Top qualified leads:
  [ 90] Radiant Plumbing               | 4.9 (1456 reviews) | plumbers
  [ 75] ABC Plumbing                    | 4.8 (234 reviews) | plumbers

Exported 35 qualified leads to local_leads.csv
  Cost per lead: $0.0017

Related Tutorials

Frequently Asked Questions

Most developers complete this tutorial in 15 to 30 minutes. You will need a Scavio API key (free tier works) and a working Python or JavaScript environment.

Python 3.8+. requests library. A Scavio API key from scavio.dev. Target business categories and locations. A Scavio API key gives you 250 free credits per month.

Yes. The free tier includes 250 credits per month, which is more than enough to complete this tutorial and prototype a working solution.

Scavio has a native LangChain package (langchain-scavio), an MCP server, and a plain REST API that works with any HTTP client. This tutorial uses the raw REST API, but you can adapt to your framework of choice.

Start Building

Extract business name, rating, reviews, and phone from Google local pack results. Python lead gen pipeline at $0.005/query.