Back to Recipes

Lead Scraper to CRM

Scrape leads from Google Maps, websites, and directories, enrich with AI, and push directly to your CRM.

Best for: Sales teams, agencies, founders doing outbound

What You Get

  • -Multi-source lead scraping
  • -AI-powered data enrichment
  • -Duplicate detection
  • -CRM integration (HubSpot/Salesforce)
  • -Scheduled scraping jobs

Step by Step

1. Build the scraping engine

Use Playwright to scrape Google Maps search results. For each listing, extract: name, phone, website, address, rating, review count, and category. Handle pagination up to 50 results. Export raw data to a staging table.

2. Implement AI enrichment

For each lead with a website, use Playwright to visit and capture the homepage content. Send to OpenAI to extract: estimated company size, tech stack, target market, and potential pain points. Store enrichment JSON.

3. Build duplicate detection

Query existing CRM contacts by email/domain. Use fuzzy matching on company name for non-email leads. Flag potential duplicates with a confidence score for manual review.

4. Create CRM integration

Implement HubSpot (or Salesforce) API client. Map scraped fields to CRM contact properties. Batch create/update contacts (max 100 per request). Handle rate limits with exponential backoff.

5. Build the review dashboard

Create a Next.js dashboard showing: leads found, enriched, duplicates, and pending review. Allow users to approve/reject leads before CRM push. Show scraping stats and history.

6. Add scheduling

Implement cron-based scheduled scraping jobs. Configurable: daily, weekly, or manual. Each run logs stats and sends a Slack notification with summary.

Stack

Apify or PlaywrightOpenAIHubSpot API / Salesforce APIPostgreSQLNext.js cron jobs

Build This

Copy this prompt and paste it into Claude Code, OpenCode, Codex, or Cursor to build this recipe.

Build a lead scraping to CRM pipeline using Playwright and OpenAI. ROLE: You are a lead generation system that scrapes business listings, enriches them with AI, deduplicates against existing CRM data, and pushes qualified leads to the CRM. CONSTRAINTS: - Rate limit: maximum 100 Google Maps results per query; 500 leads per day total - Enrichment requires a live website; skip leads without a website URL - All leads must go through human review before CRM push (first 50 leads) - Use rotating user agents and delays (2-5 seconds) between page loads - Never scrape personal data (emails, phone numbers) from sources that prohibit it in their ToS TOOL CALLING: - Use function calling for: scrape_google_maps(query, location, limit), scrape_website(url), enrich_lead(lead_data), check_duplicate(email, domain, company_name), push_to_crm(lead_data, crm_config), get_scraping_stats(date_range?) - Each tool returns structured JSON with lead data and metadata STRUCTURED OUTPUT: - Scraped lead must return JSON: { name: string, phone?: string, website?: string, address: string, rating?: number, review_count?: number, category: string, source_url: string } - Enrichment must return JSON: { company_size: string, tech_stack: string[], industry: string, pain_points: string[], funding_stage?: string, confidence: number } - Duplicate check must return JSON: { is_duplicate: boolean, match_type: 'exact' | 'fuzzy' | 'none', existing_contact_id?: string, confidence: number } - CRM push result must return JSON: { contact_id: string, status: 'created' | 'updated' | 'skipped', fields_mapped: string[] } CHAIN OF THOUGHT: - Query construction: analyze the search intent, select optimal Google Maps categories, identify geographic scope - Enrichment reasoning: from website content, infer company size from team page, tech stack from source code/meta tags, pain points from blog/help content - Duplicate resolution: compare exact email match → domain match → fuzzy company name match → address proximity FEW-SHOT EXAMPLES: Query: 'digital marketing agencies in Guadalajara' Scraped: { name: 'Agencia Digital MX', website: 'https://agenciadigital.mx', rating: 4.8, review_count: 127 } Enriched: { company_size: '10-50', tech_stack: ['WordPress', 'Google Analytics', 'HubSpot'], industry: 'Digital Marketing', pain_points: ['scaling ad campaigns', 'client reporting automation'], confidence: 0.85 } Duplicate check: { is_duplicate: false, match_type: 'none', confidence: 0.0 } EVALUATION CRITERIA: - Scraping accuracy: percentage of leads with complete required fields (name, website, category) - Enrichment quality: confidence score average across all enriched leads - Duplicate detection precision: percentage of flagged duplicates that are actual duplicates - CRM data completeness: percentage of pushed leads with all required CRM fields populated The system should: 1) Accept a search query and location, scrape Google Maps results via Playwright, 2) Extract business data from each listing, 3) Visit each lead's website and use OpenAI to enrich with company size, tech stack, and pain points, 4) Check for duplicates against existing CRM contacts using email/domain/fuzzy name matching, 5) Push new leads to HubSpot/Salesforce with mapped fields, 6) Log all scraping stats and provide a review dashboard for human approval before CRM push.

Common Failure Modes

  • !Google Maps blocks scraping after threshold
  • !Email discovery is unreliable
  • !CRM API rate limits
  • !Duplicate matching is imprecise

Implementation Notes

Use rotating proxies for Google Maps. Always allow manual review before CRM push for the first batch. Set reasonable daily scrape limits.

Ship lead scraper to crm in production with 4M Labs

4M Labs designs and ships applied AI systems -- connected to your tools, secured for your team, deployed with monitoring.

  • Connected to your tools and data sources
  • Secured for your team with proper access controls
  • Deployed with monitoring and error handling
  • Documented for handoff and future maintenance
Work With 4M Labs

Frequently Asked Questions

Can I use this recipe in production?
Yes. Every recipe is production-tested with error handling, logging, and deployment guidance.
Which LLM providers are supported?
Recipes support OpenAI, Anthropic Claude, Google Gemini, and open-source models via a unified interface.
How do I customize these recipes?
Each recipe includes a configuration section. Override model selection, API keys, and parameters without changing core logic.