The B2B Lead Generation Stack: Maps Leads, Website Contact Finder, and Email Verification
A three-step pipeline that finds local businesses, fills in missing contacts, and verifies every email before a cold outreach campaign goes out.
The actor referenced in this article. Pay only for results delivered.
No single scraper gets you a complete, send-ready B2B lead list on its own. Google Maps has business listings but not every website exposes a crawlable email. A pure email-finder has no way to discover businesses in the first place. And even a good email doesn’t mean much if you haven’t checked whether the mailbox is actually alive. A real lead-generation pipeline chains three narrow tools together, each one covering the gap the last one leaves.
The Three-Stage Pipeline
Stage 1 — Discovery. Google Maps Leads Scraper finds businesses by search query — category and location — and returns name, address, phone, website, rating, and a best-effort verified email pulled from the business’s own site.
Stage 2 — Enrichment. Not every business site exposes an email the way Maps Leads’ crawler expects, and some businesses come back from Stage 1 with a website but no email field populated. Website Contact Scraper takes that list of domains and crawls each site’s homepage plus common contact pages (/contact, /about, /contact-us, /team) to dig out emails, phone numbers, and social links that a lighter first pass missed.
Stage 3 — Verification. Before anything goes into an outreach sequence, Email Verifier & Validator runs a real syntax check, DNS MX lookup, and a non-sending SMTP mailbox probe on every address, flagging disposable, role-based, and catch-all addresses along the way. This is the step that actually protects your sender reputation — Maps Leads’ MX check confirms a domain can receive mail, but it’s not the same as the deeper SMTP-level check this stage performs.
Each stage only costs money for results it actually produces, so running the full chain on a list where Stage 1 already found most of the emails costs very little extra — Stage 2 and 3 just aren’t billed much on rows they don’t need to touch.
Chaining the Three Actors in Python
import os
from apify_client import ApifyClient
apify = ApifyClient(os.environ["APIFY_TOKEN"])
# --- Stage 1: Discover businesses on Google Maps ---
maps_run = apify.actor("themineworks/maps-leads").call(run_input={
"searchQueries": ["marketing agencies in Austin TX", "marketing agencies in Denver CO"],
"maxLeadsPerQuery": 30,
"verifyEmails": True,
"skipClosedBusinesses": True,
"deduplicateAcrossRuns": True,
"proxyConfig": {"useApifyProxy": True, "apifyProxyGroups": ["RESIDENTIAL"]},
})
businesses = [b for b in apify.dataset(maps_run["defaultDatasetId"]).iterate_items()
if "place_id" in b]
# Split: businesses that already have a verified email, and those that don't
have_email = [b for b in businesses if b.get("enrichment_status") == "email_verified"]
need_enrichment = [b for b in businesses if b.get("website") and b.get("enrichment_status") != "email_verified"]
print(f"{len(have_email)} already have a verified email. "
f"{len(need_enrichment)} have a website but no verified email yet.")
# --- Stage 2: Dig deeper on the ones Maps Leads didn't fully resolve ---
domains = [b["website"] for b in need_enrichment]
contact_run = apify.actor("themineworks/website-contact-finder").call(run_input={
"domains": domains,
"maxPagesPerSite": 5,
"proxyConfiguration": {"useApifyProxy": True, "apifyProxyGroups": ["RESIDENTIAL"]},
})
contacts = {c["domain"]: c for c in apify.dataset(contact_run["defaultDatasetId"]).iterate_items()
if c.get("domain")}
# Merge: pull the first discovered email back onto each business record
for b in need_enrichment:
domain = b["website"].replace("https://", "").replace("http://", "").split("/")[0]
found = contacts.get(domain)
if found and found.get("emails"):
b["email"] = found["emails"][0]
all_candidates = have_email + [b for b in need_enrichment if b.get("email")]
# --- Stage 3: Verify every email before it touches an outreach tool ---
emails_to_check = list({b["email"] for b in all_candidates if b.get("email")})
verify_run = apify.actor("themineworks/email-verifier-validator").call(run_input={
"emails": emails_to_check,
"checkMx": True,
"checkSmtp": True,
"detectDisposable": True,
"detectRoleBased": True,
})
verdicts = {v["email"]: v for v in apify.dataset(verify_run["defaultDatasetId"]).iterate_items()
if v.get("email")}
# Final send-ready list: only status == "valid"
send_list = [b for b in all_candidates
if verdicts.get(b.get("email", ""), {}).get("status") == "valid"]
print(f"{len(send_list)} businesses cleared all three stages and are ready for outreach.")
Why Each Stage Is Necessary, Not Redundant
It’s tempting to think Maps Leads’ built-in MX check makes Stage 3 unnecessary. It doesn’t. Maps Leads verifies that a domain can receive mail — a live MX record. Email Verifier goes further: it opens an actual SMTP connection and issues RCPT TO against the specific mailbox (stopping before DATA, so nothing is ever sent), which catches dead mailboxes on domains that are otherwise perfectly capable of receiving mail. It also flags catch-all domains — ones that accept every address regardless of whether a real mailbox exists behind it — which an MX check alone can’t distinguish from a genuinely valid address. A catch-all domain passes MX every time; only the SMTP probe (or a bounce, the hard way) reveals it.
Similarly, Website Contact Finder isn’t a replacement for Maps Leads’ built-in enrichment — it’s a second pass with a different crawl pattern (explicit /contact, /about, /team paths) that catches emails the first pass’s crawler missed, plus social links Maps Leads doesn’t collect at all.
What the Full Pipeline Costs
Maps Leads charges $0.01 per verified lead. Website Contact Scraper charges $0.001 per domain that returns at least one contact. Email Verifier charges $0.001 per email checked. Running the pipeline above on 200 discovered businesses — say 120 already resolved by Maps Leads, 80 needing Stage 2 enrichment, and a final verification pass on all 200 — costs roughly $1.20 (Maps Leads on the verified subset) + $0.08 (Website Contact on 80 domains, assuming most return something) + $0.20 (Email Verifier on 200 addresses), for well under $2 total. None of the three charge for failed lookups or empty results, so a small test run against unpromising data costs next to nothing.
Building on the Individual Actors
This guide assumes familiarity with each actor on its own. For a deeper look at Maps Leads specifically — how it gets past the Google Places API’s 120-result cap and what its verification model looks like — see our Maps Leads guide. For more on Website Contact Scraper’s crawl behavior and output fields, see scraping business contacts from any website. For the full mechanics of the SMTP-level verification step, see bulk email verification in Python.
Frequently Asked Questions
Do I need to run all three stages every time?
No. If Maps Leads already returns a healthy verified-email rate for your search category (common for service businesses with simple websites), you can skip Stage 2 for those rows and go straight to verification. The pipeline above already does this by splitting have_email from need_enrichment.
What if Website Contact Scraper also finds nothing?
Some businesses genuinely don’t expose a crawlable email — a heavily JavaScript-rendered site, or one that only has a contact form with no visible mailto: link. Those rows drop out of the pipeline rather than being force-verified against a guess, which is the correct outcome: better to lose the lead than send to a fabricated address.
How do I avoid re-paying for businesses I’ve already processed?
Maps Leads has built-in cross-run deduplication (deduplicateAcrossRuns) so re-running the same search query later skips businesses you’ve already pulled. For Stages 2 and 3, keep your own record of processed domains and emails and filter them out of future input lists before calling the actors again.
Is this pipeline GDPR/CCPA safe?
All three actors read only publicly available data — public Google Maps listings, public website contact pages, and standard DNS/SMTP protocol checks that don’t retrieve message content. That said, how you use the resulting list (consent basis, opt-out handling, retention) is your responsibility under applicable law, not the tooling’s.
Explore the scraper referenced in this article — see inputs, outputs, and pricing, then run it on Apify.
I Automated My AI Job Hunt: 8 Tools, One Claude Agent, Under $1
Most job hunting is spent on the wrong problem. Here is the exact end-to-end flow — find who is actually hiring, rank by real fit, research the company, find the human, and write an application grounded in facts — run entirely from Claude via MCP.
Ask an AI for a Company's SEC CIK and It Will Lie to You. Here Is the Fix.
An AI that remembers is not an AI that verifies. This is the exact diligence flow — legal identity from GLEIF, filings from EDGAR, funding, engineering activity and hiring — run from Claude via MCP, grounded in real registries, for about fifteen cents a company.
Stop Cold Pitching: Find Local Businesses With a Problem You Can Actually Fix — Under $4
Cold outreach fails because it is generic. Here is the exact flow — build a prospect universe, diagnose the real problem from their own reviews, qualify who can pay, find the human, and pitch with evidence — run entirely from Claude via MCP. No code.