Gmaps lead generation
Skill Harmeet10000/skills/skills/marketing/gmaps-lead-generation
Collection of my Agent Skills and books.
npx -y skills add Harmeet10000/skills --skill gmaps-lead-generationAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 7 stars7 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
6.2 KB, as published. Nobody here has run it
Google Maps Lead Generation
Generate high-quality B2B leads from Google Maps with deep contact enrichment.
Overview
This pipeline scrapes Google Maps for businesses, then enriches each result by:
- Scraping their website (main page + up to 5 contact pages)
- Searching DuckDuckGo for additional contact info
- Using Claude to extract structured contact data from all sources
Tested at scale: 50+ leads per run, 68 total leads across plumbers, electricians, HVAC, and roofing contractors.
When to Use
- Building outbound sales lists for local service businesses
- Generating leads for B2B services (contractors, medical, legal, etc.)
- Researching businesses in a specific geographic area
- Creating prospecting lists with verified contact info
Inputs
| Parameter | Required | Description |
|---|---|---|
--search | Yes | Search query (e.g., "plumbers in Austin TX") |
--limit | No | Max results to scrape (default: 10) |
--location | No | Additional location filter |
--sheet-url | No | Existing Google Sheet to append to |
--sheet-name | No | Name for new sheet if creating |
--workers | No | Parallel workers for enrichment (default: 3) |
Execution
# Basic usage - creates new sheet
python3 execution/gmaps_lead_pipeline.py --search "plumbers in Austin TX" --limit 10
# Append to existing sheet (recommended for building lead database)
python3 execution/gmaps_lead_pipeline.py --search "dentists in Miami FL" --limit 25 \
--sheet-url "https://docs.google.com/spreadsheets/d/..."
# Higher volume run
python3 execution/gmaps_lead_pipeline.py --search "roofing contractors in Austin TX" \
--limit 50 --workers 5
Output Schema (36 fields)
Business Basics (from Google Maps)
business_name,category,address,city,state,zip_code,countryphone,website,google_maps_url,place_idrating,review_count,price_level
Extracted Contacts (from website + web search + Claude)
emails- All email addresses found (comma-separated)additional_phones- Phone numbers from websitebusiness_hours- Operating hours
Social Media
facebook,twitter,linkedin,instagram,youtube,tiktok
Owner/Key Person Info
owner_name,owner_title,owner_email,owner_phone,owner_linkedin
Team Contacts
team_contacts- JSON array of team members with name, title, email, phone, linkedin
Metadata
lead_id- Unique identifier (MD5 hash of name|address, for deduplication)scraped_at- ISO timestampsearch_query- Original search term usedpages_scraped- Number of pages fetched (1 main + up to 5 contact pages)search_enriched- Whether DuckDuckGo search was used (yes/no)enrichment_status- success/partial/error
Pipeline Steps
- Google Maps Scrape - Apify
compass/crawler-google-placesactor returns business listings with basic info - Website Scraping - Fetches main page + up to 5 prioritized contact pages (/contact, /about, /team, etc.)
- Web Search Enrichment - DuckDuckGo search for
"{business}" owner email contact+ scrapes first relevant result - Claude Extraction - Claude 3.5 Haiku extracts structured contacts from all gathered content
- Google Sheet Sync - Appends new leads, automatically deduplicates by
lead_id
Contact Page Patterns (22 total, priority-ordered)
High priority: /contact, /about, /team, /contact-us, /about-us, /our-team
Medium: /staff, /people, /meet-the-team, /leadership, /management, /founders, /who-we-are
Lower: /company, /meet-us, /our-story, /the-team, /employees, /directory, /locations, /offices
Cost Considerations
| Component | Cost per lead |
|---|---|
| Apify Google Maps | ~$0.01-0.02 |
| Claude Haiku extraction | ~$0.002 |
| DuckDuckGo search | Free |
| HTTP requests (6-7 pages) | Free |
| Google Sheets | Free |
| Total | ~$0.012-0.022 |
For 100 leads: ~$1.50-2.50 total
The pipeline maximizes value per Apify dollar by scraping 6+ pages + web search per business.
Dependencies
apify-client
httpx
html2text
anthropic
gspread
google-auth
google-auth-oauthlib
python-dotenv
Files
execution/gmaps_lead_pipeline.py- Main orchestration scriptexecution/scrape_google_maps.py- Google Maps scraper (standalone)execution/extract_website_contacts.py- Website contact extractor (standalone)
Troubleshooting
"No businesses found"
- Check search query is valid
- Include location in query (e.g., "plumbers in Austin, TX" not just "plumbers")
403 Forbidden errors
- ~10-15% of sites block scrapers with 403/503 errors
- These are handled gracefully and marked as errors in
enrichment_status - The lead is still saved with Google Maps data (phone, address, etc.)
"Could not fetch website"
- Some sites have broken DNS or are offline
- Marked as
errorin enrichment_status - Reduce
--workersif seeing many timeouts
"APIFY_API_TOKEN not found"
- Ensure
.envfile has valid Apify token - Check token hasn't expired at apify.com
Google Sheet auth issues
- Delete
token.jsonand re-authenticate - Ensure
credentials.jsonis valid OAuth client
Duplicate detection
- Pipeline uses
lead_id(MD5 of name|address) to skip existing leads - Running same search twice will show "No new leads to add (all duplicates)"
Learnings
- Google Maps actor returns
websitefield directly - no need to scrape for it - Contact pages commonly use /contact, /about, /team URL patterns
- Claude Haiku is sufficient for extraction and costs 10x less than Sonnet
- ~10-15% of business websites return 403/503 errors - this is normal
- Facebook URLs always fail with 400 errors (blocks scrapers)
- Some sites have broken DNS - handled gracefully as errors
- DuckDuckGo HTML search is free and doesn't block (unlike Google)
stringify_value()helper needed because Claude sometimes returns dicts instead of strings- Deduplication by lead_id prevents re-adding existing businesses across runs
- 50 leads takes ~3-4 minutes with 3 workers
Production Sheet
Active lead database: https://docs.google.com/spreadsheets/d/1ATrOiq3wfph8Or5BE8VCybgvqK5gh7hVPWiSlgb3QiU
Contains: plumbers, electricians, HVAC contractors, roofing contractors (Austin TX)
Gives 0 of the 12 instructions most sales crm skills give
Counted across 361 of the 361 authors here whose files we hold, read 2026-08-06
- Read product marketing context before writing if it existsin 22 of 361, across 14 files
- keep the ask low-frictionin 16 of 361, across 7 files
- Call RUBE_SEARCH_TOOLS firstin 15 of 361, across 5 files
- personalize every outbound messagein 13 of 361, across 4 files
- confirm connection status is activein 13 of 361, across 4 files
- Keep forwardable blurbs under 100 wordsin 13 of 361, across 4 files
- State if personalization context is missingin 13 of 361, across 4 files
- Cut any sentence that does not drive a replyin 13 of 361, across 4 files
- Use proof instead of adjectivesin 12 of 361, across 3 files
- Use a single, low-friction call to actionin 12 of 361, across 4 files
- Calibrate tone to the specific audiencein 12 of 361, across 3 files
- Make each follow-up email add new valuein 12 of 361, across 6 files
Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once.