# Free Google Maps Scraper — Places + Contact Details + Photos (`s-r/free-google-maps-scraper`) Actor

- **URL**: https://apify.com/s-r/free-google-maps-scraper.md
- **Developed by:** [SR](https://apify.com/s-r) (community)
- **Categories:** Business, Lead generation
- **Stats:** 50 total users, 12 monthly users, 96.2% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$2.50 / 1,000 place scrapeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Free Google Maps Scraper, Places, Contact Details, Hours, Lat/Lng

A Google Maps scraper that returns every business detail Google's `/maps/search` page renders, name, rating, review count, category, full address, phone number, website, opening hours, latitude / longitude, as clean structured JSON. No browser automation, no Google Places API key, no $17-per-1k Places-API bill at the end of the month. One AJAX call per query returns up to ~300 places, far past Google Maps' 120-per-screen web limit, at $0.0025 each.

### What you get

- Business name, primary category (e.g. `Italian restaurant`), and the full `categories` list
- Rounded star rating (1-5) plus total review count as an integer (`reviews_count: 1248`)
- Stable identifiers: `place_id` (`ChIJ…`), `fid` (`0x…:0x…`), and `kgmid` (`/g/…`)
- Full address **plus parsed parts**, `street`, `city`, `postal_code`, `state`, `country_code`, `neighborhood`
- Phone number in international format when Google has it on file
- Website URL, the outbound link Google Maps points to (typically the merchant's own domain, not a redirector)
- Price range (`price_range: "€30–40"`) when Google has it
- `current_status` ("Open · Closes 12 am", "Closed · Opens 5 pm") **and** the full 7-day `opening_hours` schedule
- `additional_info`, service options, accessibility, amenities, payments, atmosphere, and more, grouped exactly as Google labels them
- Latitude and longitude as decimal floats, accurate to ~1 meter
- Search query echoed on every row so you can join multi-keyword runs into one dataset

### Why scrape Google Maps for places data

Google Places API costs are punishing for any volume use case. The new Places API (New) bills `$17/1000` for **Place Details (Basic)**, `$32/1000` for **Place Details (Advanced)** with phone + website + opening hours, and `$32/1000` for **Text Search (Basic)** before you even fetch a single detail. A lead-gen agency pulling 50,000 dentists across the US pays Google **$1,600 minimum** for that one job, and Places API is rate-limited to a few hundred QPS unless you negotiate a custom quota. Worse, Google deprecated the legacy Places API in March 2025 and is forcing migration to the New API which has stricter field masks and higher per-call billing.

This actor solves that by hitting Google's internal `/search?tbm=map` AJAX endpoint with `curl_cffi` (Chrome TLS impersonation) plus a fresh anonymous Google session cookie from a managed minter pool. One call returns up to ~300 places with the full structured payload, name, rating, address, phone, website, hours, lat/lng, for **$0.0025 per place**, or **$2.50 per 1000**. That's 13× cheaper than Google Places (Basic) and 6× cheaper than competing Google Maps scrapers on the Apify Store such as `compass/crawler-google-places` (which charges per-result on a sliding scale that lands around $4-7 per 1000 places). No browser, no Selenium, no headful Playwright, just one HTTP call per query.

Concrete buyer math: a B2B lead-gen agency building a list of 25,000 plumbers across 100 US cities pays $0.0025 × 25,000 = **$62.50 for the whole job**, finishing in ~30 minutes. The same job through Google Places API (Advanced fields) costs $32 × 25 = **$800**, takes a week to clear quota approval, and still doesn't include the lat/lng on the cheap tier.

### Input

| Field | Default | Description |
|---|---|---|
| `queries` | required | Array of Google Maps search queries (`"restaurants Amsterdam"`, `"plumbers in NYC"`, `"dentists London"`) |
| `max_results_per_query` | `120` | Cap places per query (1-400). A single call returns Google's full inventory for the area, typically up to ~300 places |
| `hl` | `en` | Language code (`en`, `nl`, `de`, `es`, `fr`, `it`, `ja`) |
| `gl` | `us` | Two-letter country code controlling locale + currency |
| `use_cookies` | `true` | Use a fresh anonymous Google session, bypasses the EU consent banner and reduces CAPTCHA at scale |
| `use_proxy` | `false` | Optional. Adds extra IP rotation for very high volume |

### Output

```json
{
  "search_position": 3,
  "name": "De Kas",
  "fid": "0x47c609e91734d71b:0x…",
  "place_id": "ChIJG9c0F-kJxkcR…",
  "kgmid": "/g/1tf…",
  "address": "Kamerlingh Onneslaan 3, 1097 DE Amsterdam",
  "street": "Kamerlingh Onneslaan 3",
  "city": "Amsterdam",
  "postal_code": "1097 DE",
  "state": null,
  "country_code": "NL",
  "neighborhood": "Watergraafsmeer",
  "lat": 52.3471242,
  "lng": 4.9264883,
  "category": "Modern European restaurant",
  "categories": ["Modern European restaurant", "Restaurant"],
  "rating": 4.5,
  "reviews_count": 1842,
  "price_range": "€100+",
  "phone": "+31 20 462 4562",
  "website": "https://restaurantdekas.com/",
  "website_domain": "restaurantdekas.com",
  "current_status": "Open · Closes 4 pm",
  "opening_hours": [
    {"day": "Monday", "hours": "12–2 pm, 6–10 pm"},
    {"day": "Tuesday", "hours": "12–2 pm, 6–10 pm"}
  ],
  "additional_info": {
    "Service options": [{"Outdoor seating": true}, {"Dine-in": true}],
    "Offerings": [{"Alcohol": true}, {"Vegetarian options": true}]
  },
  "search_query": "restaurants Amsterdam"
}
```

Use `place_id` / `fid` to dedupe across multi-keyword runs and as a stable join key into your own systems.

### Use cases

**B2B lead-gen agency building niche prospect lists.** You sell SEO services to dentists. You queue 100 queries (`"dentist <city>"` for the top 100 US metros) and run the actor, each dense metro returns up to ~300 dentists with name, phone, website, and rating, so a 100-metro sweep can pull well over 10,000 leads in one run. Filter for `rating < 4.0` (low-rated practices that need reputation work) and you have an outbound list segmented by exact pain point.

**Local SEO consultant auditing a market.** Your client is a Brooklyn pizzeria. You pull `"pizza Brooklyn"`, `"pizzeria Brooklyn"`, and `"italian restaurant Brooklyn"`, each returning the full local field of competitors in one call. Sort by `reviews_count` descending and you instantly see who the real local competitors are, their ratings, and their websites for backlink prospecting.

**Real-estate analyst mapping commercial supply.** You need every coffee shop in a 5-city catchment to model retail density. Five queries return the full coffee-shop inventory per city, hundreds of places, with `lat`/`lng` ready to load into PostGIS or Mapbox. Compare to Google Places API at $32/1000 with rate limits; you're done in minutes for a few dollars.

**Travel-app developer seeding a points-of-interest database.** Your itinerary app needs 50 POI categories across 50 cities = 2,500 queries, each returning up to ~300 places. At $0.0025/place a 50,000-place database costs ~$125. Through Places API (Text Search + Place Details Advanced): $1,600 + 2-week quota request. Same data, ship two weeks earlier.

### How it compares

| Actor | Price per 1000 places | Phone | Website | Hours | Lat/Lng |
|---|---|---|---|---|---|
| **This actor (s-r/free-google-maps-scraper)** | **$2.50** | yes | yes | yes | yes |
| `compass/crawler-google-places` (#2 on `google maps scraper` SERP) | ~$4-7 sliding scale | yes | yes | yes | yes |
| `gosom/google-maps-scraper` (#3 SERP, open-source CLI) | self-hosted (your infra) | yes | yes | partial | yes |
| Outscraper Google Maps (#1 SERP) | ~$3-5 | yes | yes | yes | yes |
| Google Places API (Advanced) | $32 + quota approval | yes | yes | yes | yes |

The headline competitor on Apify is `compass/crawler-google-places`, which is the top-ranking Maps scraper on Apify Store with thousands of monthly users, but its sliding-scale pricing lands around $4-7 per 1000 results for typical workloads, and its run-times are slower because it uses headless Chrome under the hood. This actor is pure HTTP (`curl_cffi` + cookies) which is why it can sustain 13 places/sec at $2.50/1000.

**Coverage per call:** the Google Maps website caps any single map screen at 120 places, and most scrapers inherit that ceiling per scroll. This actor hits the underlying AJAX endpoint directly and returns Google's full inventory for the area, up to ~300 places, in a single request, so you get past the 120 limit without scroll loops, browser sessions, or extra requests.

### Pricing

This actor uses Apify's pay-per-event monetization at $0.0025 per place returned, that's $2.50 per 1000 places, or roughly 60-90% cheaper than the closest Apify alternatives. All pricing is pay-per-event, you only pay for results you receive. No actor-start fee, no per-compute-unit charges, no charge for empty queries or rate-limit retries.

### Limits and gotchas

- A single `/search?tbm=map` call returns Google's full inventory for the search area, typically up to ~300 places, capped at 400. That already beats Google Maps' own 120-per-screen web limit. For denser coverage (thousands), split into geographically narrower queries (e.g. `"sushi Amsterdam Centrum"`, `"sushi Amsterdam Zuid"`)
- Phone, website, price, and hours are populated only when Google has them on file; expect ~90% website, ~90% phone, ~95% hours coverage in mature markets, lower in emerging ones
- Both `current_status` (live "Open · Closes 10 PM" string) **and** the full 7-day `opening_hours` array are included, no follow-up call needed
- `plus_code` and `hours_status` are legacy fields not populated by this endpoint and may be removed in a future version, use `lat`/`lng` and `opening_hours`/`current_status` instead
- Apify residential proxy is **not** required, the cookie pool plus `curl_cffi`'s Chrome TLS fingerprint is enough for sustained throughput; leaving `use_proxy=false` saves you ~$8/GB
- `gl` controls the result locale, `gl=us` searching `"hairdresser Amsterdam"` will still return Amsterdam results but with US English UI strings; for native locale results set `gl=nl` and `hl=nl`
- Cold-start time is ~2-4 seconds for the first request; subsequent queries in the same run reuse the session pool and complete in ~0.8s each
- Email addresses are **not** included, Google Maps doesn't expose emails on place panels. To get emails, pass the `website` URL to a website-scraper actor and parse `mailto:` links

### FAQ

**How do I scrape Google Maps without the Places API?**
This actor calls Google's internal `/search?tbm=map` AJAX endpoint directly with `curl_cffi` (Chrome TLS impersonation) and a fresh anonymous Google session cookie. No Google Cloud account, no API key, no quota approval. You only pay Apify's per-result rate.

**Is Google Maps scraping legal?**
Scraping publicly visible business listings from Google Maps is generally treated as fair use under hiQ Labs v. LinkedIn (US 9th Circuit) and similar EU case law, the data is public-by-design (Google publishes it for searchers to find). What's not legal is downloading copyrighted Maps tiles or reverse-engineering Google's auth flow. This actor only reads public place panels.

**What's the cost to scrape 10,000 Google Maps places?**
10,000 × $0.0025 = **$25**. For comparison: Google Places API (Advanced) costs $320 for the same 10,000 places, before you factor in quota approval and rate limits.

**Can I get business emails from Google Maps?**
No, Google Maps doesn't expose email addresses on place panels. Most lead-gen workflows use this actor to get the `website` URL, then run a website-scraper actor to crawl the contact page and parse `mailto:` links.

**Will Google rate-limit my scraping?**
At default settings (fresh session cookies, default IP) the actor sustains ~12-15 places/second without throttling. For sustained >50/sec throughput, enable `use_proxy=true` and supply a residential proxy URL via the `PROXY_URL` env var.

### Related Actors

- [Free Google Maps Reviews Scraper](https://apify.com/s-r/free-google-maps-reviews-scraper), every review for any place URL (stars, text, author, owner reply, photos)
- [Free Google Maps Images Scraper](https://apify.com/s-r/free-google-maps-images-scraper), bulk photo URLs for any place URL
- [Free Google Hotels Scraper](https://apify.com/s-r/free-google-hotels-scraper), Google Hotels search with per-room pricing and 18-31 OTA price comparison

# Actor input Schema

## `queries` (type: `array`):

Google Maps search queries (e.g. 'restaurants Amsterdam', 'plumbers in NYC').

## `max_results_per_query` (type: `integer`):

Cap places per query (1-400). A single request returns Google's full inventory for the area — typically up to ~300 places — far beyond Google Maps' 120-per-screen web limit.

## `hl` (type: `string`):

Language code (en, nl, de, es…).

## `gl` (type: `string`):

Two-letter country code (us, gb, nl, de…).

## `use_cookies` (type: `boolean`):

Recommended. Bypasses consent banner and reduces CAPTCHA at scale.

## `use_proxy` (type: `boolean`):

Optional. Adds extra IP rotation for very high volume.

## Actor input object example

```json
{
  "queries": [
    "restaurants Amsterdam",
    "coffee shops Berlin"
  ],
  "max_results_per_query": 120,
  "hl": "en",
  "gl": "us",
  "use_cookies": true,
  "use_proxy": false
}
```

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "queries": [
        "coffee shops amsterdam"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("s-r/free-google-maps-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "queries": ["coffee shops amsterdam"] }

# Run the Actor and wait for it to finish
run = client.actor("s-r/free-google-maps-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "queries": [
    "coffee shops amsterdam"
  ]
}' |
apify call s-r/free-google-maps-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=s-r/free-google-maps-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/BicdJfvb7zWHUt0Ks/builds/Rnmag8ufNEnT0MfjA/openapi.json
