DEV Community

agenthustler
agenthustler

Posted on • Originally published at thedatacollector.substack.com

How to Scrape Google Maps Business Data in 2026

Why Google Maps Data is Gold

Google Maps hosts 250+ million business listings. If you're in lead generation, market research, competitor analysis, or location intelligence, that's your goldmine.

Here's what you can extract:

  • Business names, addresses, phone numbers
  • Opening hours, website links
  • Customer reviews and ratings
  • Photo counts and review dates
  • Category tags and service details
  • Review sentiment and common complaints

For real estate agents, contractors, franchise scouts, and SaaS sales teams, one Google Maps dataset can fund an entire quarter's outreach.

The challenge? Google actively blocks scrapers. They'll:

  • Rate-limit your IP
  • Serve CAPTCHA on repeated requests
  • Ban your user agent if it looks automated
  • Require you to solve reCAPTCHA v3

This article covers three approaches: the free way (limited), the API way (structured), and the reliable way (with proper tooling).


Approach 1: Apify's Google Maps Scraper (Easiest)

The most popular solution in 2026. Apify's Google Maps actor has 297,000 users for a reason: it just works.

Why Use Apify?

  • Zero code required. Point → click → download CSV
  • Built-in proxy rotation. No IP bans
  • Structured data. Reviews, ratings, contact info ready-made
  • Maintained and legal. Apify handles compliance
  • Affordable. ~$10–50 per run depending on scale

How to Use It

  1. Sign up at apify.com
  2. Find the actor → Search "Google Maps Scraper"
  3. Configure your search:
    • Search term: "coffee shops in San Francisco"
    • Max results: 100–500
    • Include reviews: Yes/No (impacts cost)
  4. Run the actor
  5. Export CSV/JSON

Cost example: Scraping 500 Google Maps listings with reviews costs ~$15–25 in Apify credits.

Verdict: Perfect for one-off datasets or non-technical teams. Not ideal if you need real-time scraping at massive scale or custom fields.


Approach 2: Python + Google Maps API (Structured, Limited)

If you want control and your dataset is small (<10K locations), the Google Maps API is the "legal" path.

The Catch

Google's official API has limits:

  • Places API lets you search and fetch details — but at $0.03–0.17 per request
  • 10,000 results per month free tier (then paid)
  • No review text extraction (you get review count and rating only)
  • Geolocation required (need lat/lon or polygon)

Setup

pip install googlemaps
Enter fullscreen mode Exit fullscreen mode

Get your API key:

  1. Go to Google Cloud Console
  2. Enable Places API and Maps JavaScript API
  3. Create an API key (requires credit card)

Code Example: Find Coffee Shops

import googlemaps

# Initialize client
gmaps = googlemaps.Client(key='YOUR_API_KEY_HERE')

# Search for nearby places
places_result = gmaps.places_nearby(
    location=(37.7749, -122.4194),  # San Francisco coords
    radius=5000,  # 5 km radius
    keyword='coffee shop',
    type='cafe'
)

# Extract data
businesses = []
for place in places_result['results']:
    business = {
        'name': place.get('name'),
        'address': place.get('formatted_address'),
        'rating': place.get('rating'),
        'reviews': place.get('user_ratings_total'),
        'lat': place['geometry']['location']['lat'],
        'lon': place['geometry']['location']['lng'],
        'place_id': place['place_id'],
        'open_now': place.get('opening_hours', {}).get('open_now'),
    }
    businesses.append(business)

# Get detailed info for each place
for place_id in [b['place_id'] for b in businesses]:
    place_details = gmaps.place(place_id=place_id)
    place_data = place_details['result']

    # Extract phone and website
    phone = place_data.get('formatted_phone_number')
    website = place_data.get('website')
    hours = place_data.get('opening_hours', {}).get('weekday_text', [])

    print(f"{place_data['name']}")
    print(f"  Phone: {phone}")
    print(f"  Website: {website}")
    print(f"  Hours: {hours}")
Enter fullscreen mode Exit fullscreen mode

Cost Calculation

  • 100 searches: $10–17
  • 1,000 detail calls: $17–30
  • Total: $30–50 per 500 businesses

Verdict: Use this if you need legal compliance and small datasets. Avoid for large-scale scraping (cost explodes fast).


Approach 3: Python + Selenium + Proxy Rotation (DIY Scraping)

For larger datasets and more control, you can automate the browser itself.

The Challenges

  1. Google detects automation (headless Chrome looks fake)
  2. CAPTCHA blocks (reCAPTCHA v3 is triggered on repeat searches)
  3. Rate-limiting (different IP per request)
  4. JavaScript rendering (data loads async)

The Solution: Proxy + Selenium

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.options import Options
import time
import random

# Proxy list (use ScraperAPI, Bright Data, or residential proxies)
PROXIES = [
    'http://proxy1.service.com:8080',
    'http://proxy2.service.com:8080',
    # Add more proxies...
]

def scrape_google_maps_business(search_term, city, max_results=50):
    """
    Scrape Google Maps listing for a search term and location
    """
    businesses = []

    for proxy in PROXIES[:max_results//10]:  # Rotate proxies
        try:
            # Configure Chrome
            options = Options()
            options.add_argument(f'--proxy-server={proxy}')
            # Uncomment for headless (but use undetected-chromedriver for better stealth)
            # options.add_argument('--headless')
            options.add_argument('user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36')
            options.add_argument('--start-maximized')
            options.add_argument('--disable-blink-features=AutomationControlled')

            driver = webdriver.Chrome(options=options)

            # Navigate to Google Maps
            search_url = f'https://www.google.com/maps/search/{search_term}+{city}'
            driver.get(search_url)

            # Wait for results to load
            wait = WebDriverWait(driver, 15)
            wait.until(EC.presence_of_all_elements_located(
                (By.CSS_SELECTOR, 'div[data-item-id]')
            ))

            # Scroll to load more results
            scrollable_div = driver.find_element(
                By.CSS_SELECTOR,
                'div[role="feed"]'
            )

            for _ in range(5):  # Scroll 5 times
                driver.execute_script(
                    'arguments[0].scrollTop = arguments[0].scrollHeight',
                    scrollable_div
                )
                time.sleep(random.uniform(2, 4))  # Random delay

            # Extract listings
            listings = driver.find_elements(By.CSS_SELECTOR, 'div[data-item-id]')

            for listing in listings[:max_results]:
                try:
                    listing.click()
                    time.sleep(random.uniform(1, 2))

                    # Extract from the side panel
                    name_elem = driver.find_element(By.CSS_SELECTOR, 'h1.fontHeadlineSmall')
                    name = name_elem.text

                    # Try to get rating
                    try:
                        rating_elem = driver.find_element(
                            By.XPATH,
                            '//span[@aria-label[contains(., "stars")]]/span'
                        )
                        rating = rating_elem.text
                    except:
                        rating = None

                    # Phone number
                    try:
                        phone_elem = driver.find_element(
                            By.XPATH,
                            '//a[@data-tooltip="Copy phone number"]'
                        )
                        phone = phone_elem.text
                    except:
                        phone = None

                    # Website
                    try:
                        website_elem = driver.find_element(
                            By.XPATH,
                            '//a[@data-tooltip="Open website"]'
                        )
                        website = website_elem.get_attribute('href')
                    except:
                        website = None

                    # Address
                    try:
                        address_elem = driver.find_element(
                            By.XPATH,
                            '//button[@data-tooltip="Copy address"]'
                        )
                        address = address_elem.text
                    except:
                        address = None

                    business = {
                        'name': name,
                        'rating': rating,
                        'phone': phone,
                        'website': website,
                        'address': address,
                        'search_term': search_term,
                        'city': city
                    }

                    businesses.append(business)

                except Exception as e:
                    print(f"Error extracting listing: {e}")
                    continue

            driver.quit()

        except Exception as e:
            print(f"Error with proxy {proxy}: {e}")
            continue

    return businesses

# Usage
results = scrape_google_maps_business(
    search_term='plumber',
    city='Austin TX',
    max_results=50
)

for biz in results:
    print(f"{biz['name']} - {biz['phone']} - {biz['rating']}")
Enter fullscreen mode Exit fullscreen mode

Making It Production-Ready

  1. Use undetected-chromedriver (beats most detection):
   pip install undetected-chromedriver
Enter fullscreen mode Exit fullscreen mode
  1. Use residential proxies (100x better than datacenter proxies):

    • ScraperAPI: $10/month, 1M requests/month
    • Bright Data: $15/month, datacenter + residential
    • Oxylabs: Higher cost but 99.9% reliability
  2. Add retry logic (handle CAPTCHAs gracefully):

   from selenium.common.exceptions import TimeoutException

   def scrape_with_retry(search_term, max_retries=3):
       for attempt in range(max_retries):
           try:
               return scrape_google_maps_business(search_term, max_results=50)
           except TimeoutException:
               if attempt < max_retries - 1:
                   print(f"CAPTCHA hit. Retry {attempt+1}/{max_retries}")
                   time.sleep(60)  # Wait 1 minute before retry
               else:
                   raise
Enter fullscreen mode Exit fullscreen mode

Cost: Residential proxies run $100–500/month for serious volume. DIY makes sense if you're doing 100K+ businesses/month.


Approach 4: Commercial Tools (Guaranteed Reliability)

If you want to skip all the technical headaches:

ScrapingBee

  • Price: $49–249/month
  • No proxy management needed. They handle it
  • JavaScript rendering included
  • 99% success rate
  • API-based (works with Python, cURL, JS)

Example request:

curl "https://api.scrapingbee.com/api/v1?api_key=YOUR_KEY&url=https://www.google.com/maps/search/coffee+shops+san+francisco"
Enter fullscreen mode Exit fullscreen mode

Bright Data

  • Price: $300–2000/month
  • Real residential IPs (their own network)
  • Built-in browser automation
  • Best for large-scale operations

Apify (revisited)

  • Easiest entry point
  • Pre-built Google Maps actor (no code)
  • Pay-as-you-go ($10–500/month depending on volume)

Comparison Table

Method Cost Speed Difficulty Legality Best For
Apify $50–500/mo Fast Easy Legal Beginners, one-offs
Google API $30–200/mo Slow Medium Legal Official, small datasets
Selenium + Proxies $100–1000/mo Slow Hard Gray Large-scale, custom fields
ScrapingBee $49–249/mo Fast Easy Legal Developers, reliability
Bright Data $300–2000/mo Fast Hard Legal Enterprise, volume

Practical Use Cases (2026)

1. Real Estate Lead Generation

Scrape all plumbers, electricians, contractors in target ZIP codes.

  • Revenue: Sell lists at $1–5 per record
  • Addressable market: 10,000+ agents nationwide
  • Monthly potential: $500–2,000

2. Market Research (SaaS)

Identify all logistics companies in your region.

  • Use: Inbound sales targeting
  • Cost: One Apify run = $20
  • ROI: 1 new customer = $5,000+ LTV

3. Franchise Scout

Find all fast-casual restaurants in high-foot-traffic areas.

  • Use: Franchise opportunity mapping
  • Scale: 50 cities × 100 listings = 5,000 data points
  • Revenue: Sell intel to franchisees ($5,000 per city report)

4. Review Sentiment Analysis

Scrape Google Maps reviews for your competitors.

  • Use: Identify pain points, opportunities
  • Tool: Combine with Hugging Face sentiment model
  • Output: Weekly competitive intelligence dashboard

Avoiding Google's Bans (2026 Reality Check)

Google's detection has gotten smarter, but so have scrapers. Here's what actually works:

  1. Residential proxies, not datacenter (most critical)
  2. Random delays (1–5 seconds between requests)
  3. Undetected-chromedriver (not vanilla Selenium)
  4. User-agent rotation (cycle through real browser strings)
  5. Don't be greedy (scrape 50 listings, not 50,000 in one hour)
  6. Handle CAPTCHA (either solve or pause and retry later)

The Truth: At scale (100K+ requests/month), you will hit CAPTCHAs. Plan for this. Either:

  • Integrate a CAPTCHA-solving service (anti-captcha.com, 2captcha.com)
  • Use Apify/ScrapingBee (they handle it)
  • Accept 15–20% of runs hitting CAPTCHA and retry

Getting Started (Right Now)

Option A: Fast & Easy (Today)

  1. Sign up for Apify
  2. Find the Google Maps actor
  3. Run a test search for your target market
  4. Download the CSV
  5. Build your outreach list

Cost: $20 | Time: 30 minutes

Option B: DIY + Learning (This Week)

  1. Set up Python environment
  2. Grab residential proxy trial (ScraperAPI free tier)
  3. Adapt the Selenium code above
  4. Scrape 100 test records
  5. Iterate on parsing

Cost: $10 | Time: 4 hours

Option C: Enterprise (30 Days)

  1. Evaluate Bright Data or Oxylabs
  2. Build custom pipeline
  3. Deploy to cloud (AWS Lambda, Heroku)
  4. Run nightly jobs
  5. Feed data into your CRM

Cost: $500 | Time: 40 hours


The Data Game in 2026

Google Maps data is still the easiest-to-monetize dataset. Why?

  • Businesses actively want to be found
  • Leads convert to sales (not traffic metrics)
  • Phone numbers + addresses = instant revenue (lead gen, B2B outreach)
  • Competition is fragmented (no single dominant player)

You're not competing with Google. You're competing with LinkedIn Sales Navigator ($99/mo) and ZoomInfo ($3,500+/year).

A CSV of 500 plumbers in Austin, with ratings and reviews, is worth money to contractors trying to build referral networks.


Your Next Step

Google Maps scraping is not theoretical. You can:

  • Generate leads and sell them
  • Build B2B prospecting tools
  • Create competitive intelligence dashboards
  • Feed data into your own CRM or SaaS

Ready to scale? We build custom Google Maps extraction pipelines, deploy to the cloud, and integrate with your sales stack.

Need custom scraping solutions? Contact us: hustler@curlship.com

We've extracted data from Google Maps, LinkedIn, Amazon, Reddit, and 20+ other sources. If you need reliable, legal, production-grade data pipelines, let's talk.


Resources & Tools Mentioned

  • Apify: apify.com (Google Maps Actor)
  • Google Maps API: developers.google.com/maps
  • Selenium: selenium-python.readthedocs.io
  • undetected-chromedriver: github.com/ultrafunkamsterdam/undetected-chromedriver
  • ScraperAPI: scraperapy.com
  • Bright Data: brightdata.com
  • ScrapingBee: scrapingbee.com

Next week: How to extract Amazon product pricing data and build automated arbitrage alerts.

Have questions? Hit reply and let me know what you're scraping next.


Disclosure: This post contains affiliate links. I may earn a commission if you sign up through my links, at no extra cost to you.

Compare web scraping APIs:

  • ScraperAPI — 5,000 free credits, 50+ countries, structured data parsing
  • Scrape.do — From $29/mo, strong Cloudflare bypass
  • ScrapeOps — Proxy comparison + monitoring dashboard

Need custom web scraping? Email hustler@curlship.com — fast turnaround, fair pricing.

Top comments (0)