Sales teams pay a lot for lists like "all dentists in Austin with a phone, website and email". You can build one yourself in a few minutes with two hosted scrapers and the Apify Python client. You pay only for the rows you get back (about $3 per 1,000), and nothing for empty sites.
The pipeline
- Google Maps Scraper returns businesses for a search term and a location: name, phone, website, rating, review count.
- Website Contact Details Extractor visits each website and returns emails (including Cloudflare-obfuscated ones), extra phones, LinkedIn, Instagram, X and the company name.
Both run over plain HTTP, without a headless browser, so a few hundred businesses take seconds.
Code
pip install apify-client
export APIFY_TOKEN=... # free account: console.apify.com → Settings → API & Integrations
import csv, os
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
# 1) Businesses from Google Maps
run = client.actor("torix33/google-maps-scraper").call(run_input={
"searchTerms": ["dentist"],
"locations": ["Austin, TX"],
"maxPlacesPerSearch": 50,
"minRating": 4.0,
})
places = list(client.dataset(run["defaultDatasetId"]).iterate_items())
sites = sorted({p["website"] for p in places if p.get("website")})
# 2) Contacts from each website
run = client.actor("torix33/website-contact-details-extractor").call(run_input={
"websites": sites,
"maxPagesPerSite": 6,
})
contacts = {c["domain"]: c for c in client.dataset(run["defaultDatasetId"]).iterate_items()}
# 3) Merge and save
with open("leads.csv", "w", newline="") as f:
w = csv.writer(f)
w.writerow(["name", "phone", "website", "rating", "reviews", "emails", "linkedin"])
for p in places:
domain = (p.get("website") or "").split("//")[-1].split("/")[0].removeprefix("www.")
c = contacts.get(domain, {})
w.writerow([p["title"], p.get("phone"), p.get("website"), p.get("rating"),
p.get("reviewsCount"), "; ".join(c.get("emails") or []), c.get("linkedin")])
print(len(places), "leads →", "leads.csv")
Prefer a single call? Google Maps Scraper has a scrapeContacts option that runs step 2 for you.
Qualify the list
To keep only businesses on a given stack (for example, WordPress sites without a booking widget), run the same sites list through Website Tech Stack Detector. It returns CMS, analytics, CRM, payments and chat widgets per domain.
Using it from an AI agent
Every actor here is also an MCP tool. Add https://mcp.apify.com/?tools=torix33/google-maps-scraper,torix33/website-contact-details-extractor to Claude Desktop, Cursor or any MCP client and ask: "Find 30 well-rated dentists in Austin and get their emails."
Notes
- Only public business data is collected. Check your local rules (GDPR, CAN-SPAM) before you email anyone.
- Every actor has a
maxResultscost cap, so you can't overspend.
Links: Google Maps Scraper · Website Contact Details Extractor · Tech Stack Detector
Top comments (0)