Back to blog
Guides & How-tos2025-08-31·8 min read

Extracting Data from Google Maps with JavaScript: Complete Guide

By Ibrahim DemolCEO IBLeadUpdated March 26, 2026

Google Maps contains 50M+ business listings. Each listing = address, phone, reviews, hours, photos, website. It’s a goldmine for prospecting, market research, competitive analysis.

But how do you extract this data at scale? There are three approaches: the official Google Maps API, custom JavaScript web scraping, or a dedicated tool. This article covers all three — with their real costs, limits, and when to use each.


Why Extract Data from Google Maps?

Before diving into the technique, clarify your need. Use cases are not the same.

Commercial Prospecting

A cleaning agency wants to find 500 restaurants within a 10 km radius. It exports: name, address, phone, email. It does targeted cold calling.

Need: basic data (name, contact), speed, average volume.

Competitive Analysis

A restaurateur analyzes 50 competing restaurants: Google reviews, number of reviews, hours, prices (via the website), photos, technologies used (do they use Uber Eats? Deliveroo? Their own site?).

Need: enriched data (reviews, tech stack), context, low to medium volume.

Market Research

A franchisor analyzes 1,000+ hairdressers in France to identify underserved areas. It extracts: location, Google rating, number of reviews, hours, claimed or unclaimed listing.

Need: structured data, advanced filtering, high volume, monthly updates.

Qualified Lead Detection

An SEO agency looks for restaurants with a rating < 3 stars (potential dissatisfied customers). It exports those with 50+ reviews (significant size) and a website without Google Analytics.

Need: Google reviews (text + rating + date), technology detection, complex filters, medium volume.

Each use case involves a different approach. Let’s look at the options.


Option 1: The Official Google Maps JavaScript API

Google offers a free JavaScript API (with quotas). It works in the browser or in Node.js server-side.

Basic Features

The Google Maps JavaScript API allows for 3 main things:

  1. Geocoding: convert an address → GPS coordinates
  2. Places API: search for places (restaurants, plumbers, etc.) around a location
  3. Place Details: retrieve detailed information about a place (reviews, hours, photos, URL, etc.)

Step 1: Get an API Key

  1. Go to Google Cloud Console
  2. Create a project
  3. Enable these APIs: - Maps JavaScript API - Places API - Geocoding API
  4. Create an API key (type: browser key or server key depending on your usage)
  5. Configure restrictions (allowed domains, quotas)

Important: Google charges beyond the free quotas. By default: 25,000 calls/day free for Places, then €0.017 per call.

Step 2: Implement Geocoding

Convert an address to latitude/longitude.

const geocoder = new google.maps.Geocoder();

geocoder.geocode(
  { address: '75 Rue de Rivoli, Paris' },
  (results, status) => {
    if (status === 'OK') {
      const lat = results[0].geometry.location.lat();
      const lng = results[0].geometry.location.lng();
      console.log(`Coordinates: ${lat}, ${lng}`);
    } else {
      console.error(`Error: ${status}`);
    }
  }
);

Find all restaurants within a 5 km radius around Paris.

const map = new google.maps.Map(document.getElementById('map'), {
  center: { lat: 48.8566, lng: 2.3522 }, // Paris
  zoom: 15
});

const service = new google.maps.places.PlacesService(map);

const request = {
  location: new google.maps.LatLng(48.8566, 2.3522),
  radius: 5000, // 5 km
  type: 'restaurant',
  keyword: 'pizza' // Optional: filter by keyword
};

service.nearbySearch(request, (results, status) => {
  if (status === google.maps.places.PlacesServiceStatus.OK) {
    results.forEach(place => {
      console.log(`${place.name} - ${place.vicinity}`);
    });
  }
});

Important limitation: nearbySearch() returns max 60 results per request, with pagination. To get 500 restaurants, you need to make 9 requests.

Step 4: Retrieve Complete Details (Place Details)

Each place returned by nearbySearch() has a place_id. Use it to get the complete details.

const request = {
  placeId: 'ChIJIQBpAG2ahYAR_6128GltTXQ', // Example: Eiffel Tower
  fields: [
    'name',
    'formatted_address',
    'formatted_phone_number',
    'website',
    'opening_hours',
    'reviews',
    'rating',
    'user_ratings_total',
    'photos'
  ]
};

service.getDetails(request, (place, status) => {
  if (status === google.maps.places.PlacesServiceStatus.OK) {
    console.log(`Name: ${place.name}`);
    console.log(`Address: ${place.formatted_address}`);
    console.log(`Phone: ${place.formatted_phone_number}`);
    console.log(`Website: ${place.website}`);
    console.log(`Rating: ${place.rating} (${place.user_ratings_total} reviews)`);
    console.log(`Hours:`, place.opening_hours.weekday_text);

    // Google Reviews
    place.reviews.forEach(review => {
      console.log(`${review.author_name}: ${review.rating}/5 - "${review.text}"`);
    });
  }
});

Real Costs of the Google Maps API

Operation Free Quota Price Beyond
Geocoding 25,000/day €0.005 per call
Nearby Search 25,000/day €0.032 per call
Place Details 25,000/day €0.017 per call
Text Search 25,000/day €0.032 per call

Real example: extract 1,000 restaurants with complete details.

  • 1,000 Nearby Searches = 17 calls (60 results/call max) = €0.54
  • 1,000 Place Details = €17

Total: ~€17.50 for 1,000 restaurants.

It seems low, but: - You need to do it again every month for updates - You are limited to 60 results per request (hard to paginate) - The returned Google reviews are limited (max 5 per place) - You do not get detected technologies (WordPress, Shopify, etc.)

Limitations of the Google Maps JavaScript API

Limitation Impact
Max 60 results per request Complex manual pagination
Max 5 reviews per place No complete review analysis
No filtering by Google rating You retrieve all results
No filtering by number of reviews No targeting on "mature" listings
No technology detection You don’t know if the site uses WordPress, Shopify, etc.
No SIRET data (France) No legal/financial enrichment
Limited quotas Costs can rise quickly at scale

Option 2: Custom JavaScript Web Scraping with Puppeteer

If you want to bypass the limitations of the official API, you can scrape the Google Maps site directly with Puppeteer (a Node.js library that automates a Chrome browser).

Why Puppeteer?

Puppeteer launches an automated Chrome browser, goes to Google Maps, simulates clicks/scrolls, and extracts the HTML. This way, you can retrieve more than 60 results, complete reviews, photos, etc.

Installation

npm install puppeteer

Example: Scraping Restaurants in Paris

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();

  // Go to Google Maps
  await page.goto('https://www.google.com/maps/search/restaurants+paris', {
    waitUntil: 'networkidle2'
  });

  // Wait for the results to load
  await page.waitForSelector('[role="listitem"]');

  // Scroll to load more results
  const resultsContainer = await page.$('[role="main"]');
  for (let i = 0; i < 5; i++) {
    await resultsContainer.evaluate(el => {
      el.scrollTop = el.scrollHeight;
    });
    await page.waitForTimeout(1000); // Wait for loading
  }

  // Extract the data
  const restaurants = await page.evaluate(() => {
    const items = document.querySelectorAll('[role="listitem"]');
    return Array.from(items).map(item => {
      const nameEl = item.querySelector('[role="heading"]');
      const ratingEl = item.querySelector('[aria-label*="étoile"]');
      const addressEl = item.querySelector('[data-item-id*="address"]');

      return {
        name: nameEl ? nameEl.textContent : 'N/A',
        rating: ratingEl ? ratingEl.getAttribute('aria-label') : 'N/A',
        address: addressEl ? addressEl.textContent : 'N/A'
      };
    });
  });

  console.log(restaurants);

  await browser.close();
})();

Issues with This Approach

  1. Google blocks quickly: After 10-20 requests, Google detects scraping and asks you to confirm you are not a robot (CAPTCHA).

  2. Constant maintenance: Google regularly changes its HTML. Your code breaks every 2-3 months.

  3. Slow: Puppeteer has to launch a full browser for each search. Scraping 10,000 restaurants = 10,000 browsers launched = hours of execution.

  4. Resource-intensive: Each browser consumes 100-200 MB of RAM. Scraping in parallel = powerful server required.

  5. Against terms of service: Google explicitly prohibits scraping Maps.

Verdict: Puppeteer works for one-off tests (50-100 results), not for large-scale extraction.


Option 3: Use a Dedicated No-Code Tool

This is the most pragmatic solution for 95% of use cases. Instead of coding, you use a tool that:

  • Handles extraction at scale
  • Bypasses Google blocks
  • Returns structured data (CSV, JSON, API)
  • Includes complete Google reviews
  • Detects technologies used
  • Updates data monthly

Why a Dedicated Tool?

Criterion Google API Puppeteer Dedicated Tool
Cost for 10,000 results €170+ Free (but slow) €44-99/month
Time for 10,000 results 2-3 days (quotas) 4-6 hours 5 minutes
Complete Google reviews Max 5 per place Yes Yes
Filtering by Google rating No No Yes
Technology detection No No Yes
Maintenance High (API changes) High (HTML changes) Zero
Google blocking Rare Frequent Never

Practical Use Cases with JavaScript

Here are 3 real scenarios and how to implement them.

Case 1: Find 50 Plumbers in Lyon with the Google Maps API

Need: name, address, phone, website, rating. Low volume. Limited budget.

Solution: Official Google Maps API.

async function findPlumbers(city, limit = 50) {
  const geocoder = new google.maps.Geocoder();

  // Geocode the city
  const cityCoords = await new Promise((resolve) => {
    geocoder.geocode({ address: city }, (results) => {
      resolve(results[0].geometry.location);
    });
  });

  const map = new google.maps.Map(document.getElementById('map'), {
    center: cityCoords,
    zoom: 12
  });

  const service = new google.maps.places.PlacesService(map);
  const allResults = [];

  // Make multiple requests (max 60 per request)
  for (let i = 0; i < Math.ceil(limit / 60); i++) {
    const results = await new Promise((resolve) => {
      service.nearbySearch(
        {
          location: cityCoords,
          radius: 15000,
          type: 'plumber',
          pageToken: i === 0 ? null : nextPageToken
        },
        (results, status, pagination) => {
          nextPageToken = pagination.nextPage ? pagination.nextPageToken : null;
          resolve(results || []);
        }
      );
    });

    allResults.push(...results);
    if (allResults.length >= limit) break;
  }

  // Retrieve details for each result
  const details = await Promise.all(
    allResults.slice(0, limit).map(place => {
      return new Promise((resolve) => {
        service.getDetails(
          {
            placeId: place.place_id,
            fields: ['name', 'formatted_address', 'formatted_phone_number', 'website', 'rating']
          },
          (place) => resolve(place)
        );
      });
    })
  );

  return details.map(p => ({
    name: p.name,
    address: p.formatted_address,
    phone: p.formatted_phone_number,
    website: p.website,
    rating: p.rating
  }));
}

// Usage
findPlumbers('Lyon').then(plumbers => {
  console.table(plumbers);
  // Export to CSV
  downloadCSV(plumbers);
});

Cost: ~€0.50 (17 Nearby requests + 50 Place Details)

Time: 30 seconds

Limitation: You don’t know which are claimed, how many reviews they have, or if they use a custom site/Wix/Squarespace.


Case 2: Analyze 200 Competing Restaurants (Reviews, Technologies)

Need: complete reviews, rating, number of reviews, technologies used. Medium volume. Average budget.

Solution: Dedicated tool (the Google Maps API only gives 5 max reviews).

With a tool, you export in 5 minutes:

Name,Address,Rating,Number of Reviews,Review (text),Review (date),Review (author),Website,Detected Technologies
Le Jules Verne,5 Rue Eiffel,4.8,1250,"Excellent value for money",2024-01-15,Pierre M.,lejulesverne.fr,"WordPress, WooCommerce, Google Analytics"
Septime,80 Rue Charonne,4.7,890,"Impeccable service",2024-01-14,Marie D.,septimeparis.com,"Custom, Shopify"

You can then: - Identify well-rated restaurants (4.5+) with 500+ reviews (significant size) - Read negative reviews to identify competitors' weaknesses - See which restaurants use Shopify (they sell online) vs WordPress (custom site)


Case 3: ABM Prospecting — Find 500 Restaurants with Website Without Google Analytics

Need: medium-sized restaurants (50-200 reviews), rating 3.5+, website without Google Analytics (potential lead for SEO/analytics agency).

Solution: Dedicated tool with advanced filters and technology detection.

```javascript // Pseudo-code (the Google Maps API cannot do this) const restaurants = await tool.search({ location: 'France', category: 'restaurant', minRating: 3.5, minReviews: 50, maxReviews: 200, hasWebsite: true, missingTechnology: 'Google Analytics' // EXCLUSIVE });

// Result: 500 qualified restaurants // You contact them with: "We noticed your site doesn’t have

Ready to get started?

Access every Google Maps business, enriched with emails and legal data.

Try IBLead free