How to Build an Autonomous B2B Lead Generation Engine with Playwright, Groq & Resend
The Project
NexusScout AI is an autonomous B2B lead generation engine powered by a three-agent AI pipeline. It scrapes Google Maps for businesses, enriches their data by extracting emails from their websites, and sends personalized outreach emails — all from a single web UI.
The problem it solves: manual lead generation is slow, repetitive, and scales poorly. Sales teams spend hours searching Google Maps, visiting websites one by one, copying emails, and drafting outreach. NexusScout automates the entire pipeline end-to-end.
Architecture
User (React UI)
│
▼
FastAPI Backend
│
├── /api/scout → Agent 1: Scouter (Playwright + Stealth)
├── /api/leads → Agent 2: Enricher (Email extraction)
├── /api/leads/contact → Agent 3: Outreach (Groq + Resend)
│
└── SQLite Database (leads.db)
Three-Agent Pipeline
| Agent | File | Role |
|---|---|---|
| Scouter | backend/agents/scouter.py | Launches a stealth Playwright browser, searches Google Maps, extracts business names and websites |
| Enricher | backend/agents/enricher.py | Visits each website, scrapes contact emails, categorizes leads |
| Outreach | backend/services/ai_service.py + email_service.py | Uses Groq Llama 3.3 70B to write personalized opening lines, sends emails via Resend |
Agent 1: Scouter
The Scouter uses Playwright with stealth plugins to search Google Maps without getting blocked. It takes a query like "Web Design Agencies in London" and extracts:
- Business name
- Website URL
- Address
- Rating
- Category
# Simplified scouter logic
from playwright.sync_api import sync_playwright
from playwright_stealth import stealth_sync
def scout(query: str) -> list[dict]:
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page()
stealth_sync(page)
page.goto(f"https://www.google.com/maps/search/{query}")
page.wait_for_selector('a[href*="/maps/place"]')
results = []
for el in page.query_selector_all('a[href*="/maps/place"]')[:20]:
name = el.get_attribute("aria-label")
href = el.get_attribute("href")
results.append({"name": name, "maps_url": href})
return results
Agent 2: Enricher
Once the Scouter returns businesses with websites, the Enricher visits each site and scrapes contact information. It handles:
- Email extraction from contact pages, about pages, and footers
- Social media profile discovery
- Business categorization based on site content
async def enrich_lead(website: str) -> dict:
emails = await extract_emails(website)
social = await find_social_profiles(website)
category = await categorize_business(website)
return {
"emails": emails,
"social": social,
"category": category,
"enriched": True
}
Agent 3: Outreach
The Outreach agent is where the AI magic happens. It uses Groq's Llama 3.3 70B to generate personalized email opening lines based on the lead's business type and website content.
from groq import Groq
def generate_outreach(business_name: str, website: str, category: str) -> str:
client = Groq(api_key=settings.GROQ_API_KEY)
prompt = f"""Write a short, personalized email opening line
for {business_name} (a {category} business at {website}).
Keep it professional but warm. Max 2 sentences."""
response = client.chat.completions.create(
model="llama-3.3-70b-versatile",
messages=[{"role": "user", "content": prompt}],
temperature=0.7,
)
return response.choices[0].message.content
Then Resend delivers the email:
import resend
resend.Emails.send({
"from": "onboarding@resend.dev",
"to": lead.email,
"subject": f"Quick question for {lead.business_name}",
"html": f"<p>{ai_generated_message}</p>"
})
Tech Stack
| Layer | Technology |
|---|---|
| Frontend | Next.js 16 + Tailwind CSS (dark theme) |
| Backend | FastAPI + SQLAlchemy (async) + SQLite |
| Automation | Playwright + playwright-stealth |
| AI | Groq (Llama 3.3 70B) for email personalization |
| Resend API for delivery |
UI Features
- Stats Bar — Real-time counts (Total / Enriched / Failed)
- Search Bar — Type a query → Scouter scrapes Google Maps
- Lead Cards — Expandable details, email, website, status badges
- Contact Button — Triggers AI personalization + email delivery
- Delete — Remove leads with one click
Quick Start
# Backend
cd backend
uv add .
uv run uvicorn main:app --reload
# Frontend (separate terminal)
cd frontend
npm install
npm run dev
Required API Keys
GROQ_API_KEY=gsk_your_key_here
RESEND_API_KEY=re_your_key_here
What I Learned
-
Three-agent architecture beats monolithic scrapers — Separating search, enrichment, and outreach into independent agents means each can fail and retry without blocking the others. If the Enricher can't find an email, the Scouter's results aren't lost.
-
Playwright stealth is essential — Google Maps blocks headless browsers aggressively. The
playwright-stealthlibrary patches detected automation signals and dramatically improves success rates. -
AI personalization at scale — Writing personalized emails for 100+ leads manually is impractical. Groq's Llama 3.3 generates convincing opening lines that reference each business's specific category and website — far better than generic templates.
-
Async SQLAlchemy makes a difference — When the Enricher is processing 50+ websites concurrently, async database operations prevent write contention and keep the UI responsive.
-
Resend is production-ready for transactional email — Simple API, good deliverability, and generous free tier. Perfect for an MVP lead generation tool.
Frequently Asked Questions
Quick answers to common questions about this project.
Use Playwright with the `playwright-stealth` plugin that patches headless browser detection signals. Add random mouse movements, human-like scrolling, and request delays between 2-5 seconds. Rotating user agents and using residential proxies helps for larger scrapes.
Feed the lead's business name, website content, and category into Groq's Llama 3.3 70B with a prompt that asks for a short, warm opening line referencing their specific business type. The model generates unique copy that sounds human, not templated.
Related Articles
How to Build an Autonomous AI Research Agent with Groq, Tavily & WebSocket Streaming
Tutorial on building an AI research agent with multi-step reasoning — uses Groq LLaMA 3.1 for planning, Tavily for web search, WebSockets for real-time streaming, and Next.js for the dashboard.
How to Build a Real-Time RAG Platform with ChromaDB, FastAPI, Groq & PDF Ingestion
Step-by-step guide to building a Retrieval-Augmented Generation system with auto PDF ingestion, ChromaDB vector search, overlapping chunk windows, and WebSocket streaming for citation-backed answers.