Lead Scraping & Verification
Goal
Scrape leads using Apify (code_crafter/leads-finder), verify their relevance (industry match > 80%), and save them to a Google Sheet. For large scrapes (1000+ leads), use parallel scraping for 3-5x faster performance.
Inputs
- Industry: The target industry (e.g., "Plumbers", "Software Agencies")
- Location: The target location (e.g., "Texas", "United States", "California"). Scripts auto-format to Apify's required format (US states get ", us" suffix automatically).
- Total Count: The total number of leads desired
Scripts
All scripts are in ./scripts/:
scrape_apify.py - Single scrape, for <1000 leads
scrape_apify_parallel.py - Parallel scraping, for 1000+ leads
classify_leads_llm.py - LLM-based lead classification
enrich_emails.py - Email enrichment via AnyMailFinder
update_sheet.py - Batch sheet updates
read_sheet.py - Read data from Google Sheets
Process
Small Scrapes (<1000 leads)
Test Scrape
python3 ./scripts/scrape_apify.py --query "INDUSTRY" --location "LOCATION" --max_items 25 --no-email-filter --output .tmp/test_leads.json
Verification
- Read
.tmp/test_leads.json
- Check if at least 20/25 (80%) leads match the Industry
- Pass: Proceed to step 3
- Fail: Stop and ask user to refine keywords
Full Scrape
python3 ./scripts/scrape_apify.py --query "INDUSTRY" --location "LOCATION" --max_items TOTAL_COUNT --no-email-filter --output .tmp/leads.json
[Optional] LLM Classification (for complex niches)
python3 ./scripts/classify_leads_llm.py .tmp/leads.json --classification_type product_saas --output .tmp/classified_leads.json
Upload to Google Sheet
python3 ./scripts/update_sheet.py .tmp/leads.json --title "Leads - INDUSTRY"
Enrich Missing Emails
python3 ./scripts/enrich_emails.py SHEET_URL
Large Scrapes (1000+ leads)
Test Scrape (same as above with 25 items)
Parallel Full Scrape
python3 ./scripts/scrape_apify_parallel.py \
--query "INDUSTRY" \
--total_count 4000 \
--location "United States" \
--strategy regions \
--no-email-filter
Geographic partitioning is automatic:
- United States: 4-way (Northeast, Southeast, Midwest, West)
- EU/Europe: 4-way (Western, Southern, Northern, Eastern)
- UK: 4-way (SE England, N England, Scotland/Wales, SW England)
- Canada: 4-way (Ontario, Quebec, West, Atlantic)
- Australia: 4-way (NSW, VIC/TAS, QLD, WA/SA)
Continue with steps 4-6 from small scrapes
Outputs
The ONLY deliverable is the Google Sheet URL. Local JSON files in .tmp/ are temporary intermediates.
Edge Cases
- No leads found: Ask user to broaden search
- API Error: Check credentials in
.env
- Low quality classifications: If >80% "unclear", improve scrape keywords
Environment
Requires in .env:
APIFY_API_TOKEN=your_token
GOOGLE_APPLICATION_CREDENTIALS=path/to/credentials.json
ANTHROPIC_API_KEY=your_key
ANYMAILFINDER_API_KEY=your_key
Schema
Inputs
| Name |
Type |
Required |
Description |
industry |
string |
Yes |
Target industry (e.g., 'Plumbers', 'Software Agencies') |
location |
string |
Yes |
Target location (e.g., 'Texas', 'United States') |
total_count |
integer |
Yes |
Total number of leads desired |
classification_type |
string |
No |
LLM classification type (e.g., 'product_saas') |
Outputs
| Name |
Type |
Description |
sheet_url |
string |
Google Sheet URL with scraped leads |
lead_count |
integer |
Number of leads found |
Credentials
| Name |
Source |
APIFY_API_TOKEN |
.env |
GOOGLE_APPLICATION_CREDENTIALS |
.env |
ANTHROPIC_API_KEY |
.env |
ANYMAILFINDER_API_KEY |
.env |
Composable With
Skills that chain well with this one: classify-leads, casualize-names, instantly-campaigns, onboarding-kickoff
Cost
$0.01-0.02 per lead + $0.30/1K for classification
1---2name: scrape-leads3description: Scrape and verify business leads using Apify, classify with LLM, enrich emails, and save to Google Sheets. Use when user asks to find leads, scrape businesses, generate prospect lists, or build lead databases for any industry or location.4---56# Lead Scraping & Verification78## Goal9Scrape leads using Apify (`code_crafter/leads-finder`), verify their relevance (industry match > 80%), and save them to a Google Sheet. For large scrapes (1000+ leads), use parallel scraping for 3-5x faster performance.1011## Inputs12- **Industry**: The target industry (e.g., "Plumbers", "Software Agencies")13- **Location**: The target location (e.g., "Texas", "United States", "California"). Scripts auto-format to Apify's required format (US states get ", us" suffix automatically).14- **Total Count**: The total number of leads desired1516## Scripts17All scripts are in `./scripts/`:18- `scrape_apify.py` - Single scrape, for <1000 leads19- `scrape_apify_parallel.py` - Parallel scraping, for 1000+ leads20- `classify_leads_llm.py` - LLM-based lead classification21- `enrich_emails.py` - Email enrichment via AnyMailFinder22- `update_sheet.py` - Batch sheet updates23- `read_sheet.py` - Read data from Google Sheets2425## Process2627### Small Scrapes (<1000 leads)28291. **Test Scrape**30 ```bash31 python3 ./scripts/scrape_apify.py --query "INDUSTRY" --location "LOCATION" --max_items 25 --no-email-filter --output .tmp/test_leads.json32 ```33342. **Verification**35 - Read `.tmp/test_leads.json`36 - Check if at least 20/25 (80%) leads match the Industry37 - **Pass**: Proceed to step 338 - **Fail**: Stop and ask user to refine keywords39403. **Full Scrape**41 ```bash42 python3 ./scripts/scrape_apify.py --query "INDUSTRY" --location "LOCATION" --max_items TOTAL_COUNT --no-email-filter --output .tmp/leads.json43 ```44454. **[Optional] LLM Classification** (for complex niches)46 ```bash47 python3 ./scripts/classify_leads_llm.py .tmp/leads.json --classification_type product_saas --output .tmp/classified_leads.json48 ```49505. **Upload to Google Sheet**51 ```bash52 python3 ./scripts/update_sheet.py .tmp/leads.json --title "Leads - INDUSTRY"53 ```54556. **Enrich Missing Emails**56 ```bash57 python3 ./scripts/enrich_emails.py SHEET_URL58 ```5960### Large Scrapes (1000+ leads)61621. **Test Scrape** (same as above with 25 items)63642. **Parallel Full Scrape**65 ```bash66 python3 ./scripts/scrape_apify_parallel.py \67 --query "INDUSTRY" \68 --total_count 4000 \69 --location "United States" \70 --strategy regions \71 --no-email-filter72 ```7374 Geographic partitioning is automatic:75 - **United States**: 4-way (Northeast, Southeast, Midwest, West)76 - **EU/Europe**: 4-way (Western, Southern, Northern, Eastern)77 - **UK**: 4-way (SE England, N England, Scotland/Wales, SW England)78 - **Canada**: 4-way (Ontario, Quebec, West, Atlantic)79 - **Australia**: 4-way (NSW, VIC/TAS, QLD, WA/SA)80813. Continue with steps 4-6 from small scrapes8283## Outputs84**The ONLY deliverable is the Google Sheet URL.** Local JSON files in `.tmp/` are temporary intermediates.8586## Edge Cases87- **No leads found**: Ask user to broaden search88- **API Error**: Check credentials in `.env`89- **Low quality classifications**: If >80% "unclear", improve scrape keywords9091## Environment92Requires in `.env`:93```94APIFY_API_TOKEN=your_token95GOOGLE_APPLICATION_CREDENTIALS=path/to/credentials.json96ANTHROPIC_API_KEY=your_key97ANYMAILFINDER_API_KEY=your_key98```99100---101102## Schema103104### Inputs105| Name | Type | Required | Description |106|------|------|----------|-------------|107| `industry` | string | Yes | Target industry (e.g., 'Plumbers', 'Software Agencies') |108| `location` | string | Yes | Target location (e.g., 'Texas', 'United States') |109| `total_count` | integer | Yes | Total number of leads desired |110| `classification_type` | string | No | LLM classification type (e.g., 'product_saas') |111112### Outputs113| Name | Type | Description |114|------|------|-------------|115| `sheet_url` | string | Google Sheet URL with scraped leads |116| `lead_count` | integer | Number of leads found |117118### Credentials119| Name | Source |120|------|--------|121| `APIFY_API_TOKEN` | .env |122| `GOOGLE_APPLICATION_CREDENTIALS` | .env |123| `ANTHROPIC_API_KEY` | .env |124| `ANYMAILFINDER_API_KEY` | .env |125126### Composable With127Skills that chain well with this one: `classify-leads`, `casualize-names`, `instantly-campaigns`, `onboarding-kickoff`128129### Cost130$0.01-0.02 per lead + $0.30/1K for classification