# Google Maps Menu Scraper (`crawlerbros/google-maps-menu`) Actor

Extract restaurant menu items, popular dishes, photos, categories, and external menu links from any Google Maps place page.

- **URL**: https://apify.com/crawlerbros/google-maps-menu.md
- **Developed by:** [Crawler Bros](https://apify.com/crawlerbros) (community)
- **Categories:** AI, Automation, E-commerce
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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

## Google Maps Menu Scraper

Extract restaurant menu items, popular-dish indicators, dish photos, menu categories, and external menu links from any Google Maps place page.

### What It Does

Give this actor a Google Maps URL for a restaurant or food business and it returns:

- **Menu items** with names and photos (one record per item)
- **`isPopular` indicator** — `true` when Google highlights a dish as popular
- **Menu categories** — the section names (e.g. `Appetizers`, `Ramen`, `Desserts`) that Google exposes for that restaurant
- **External menu URL** when the restaurant links to its own menu site, PDF, or ordering portal
- **Place ID** for cross-referencing with the Google Maps ecosystem
- **Graceful single fallback record** with `menuFound: false` when no menu data is available — so your dataset stays consistent

### Use Cases

- Power menu intelligence for delivery, restaurant tech, or food blog platforms
- Discover signature / popular dishes per restaurant
- Aggregate menu category coverage by cuisine, location, or chain
- Enrich CRM / lead-gen datasets with menu signals
- Build product catalogues that link back to the operator's own menu page

### Input

| Field | Type | Required | Description |
|---|---|---|---|
| `placeUrl` | String | Yes | Google Maps URL of a single restaurant |
| `maxItems` | Integer | No | Maximum menu items per run (1-500). Default `100` |
| `language` | Enum | No | UI language (`en`, `es`, `fr`, `de`, `it`, `pt`, `ja`, `ko`, `zh`, `ar`, `ru`). Default `en` |
| `proxyConfiguration` | Object | No | Apify proxy settings (optional — runs reliably without proxy by default) |

**Example input:**

```json
{
  "placeUrl": "https://www.google.com/maps/place/The+Halal+Guys/@40.7615453,-73.9794252,17z/",
  "maxItems": 50,
  "language": "en"
}
````

> **Tip:** Copy the URL straight from the address bar after opening a restaurant on Google Maps.

### Output

One record per menu item:

```json
{
  "businessName": "The Halal Guys",
  "placeId": "0x89c258ff097dbc2d:0x86df3a18a06daf7c",
  "placeUrl": "https://www.google.com/maps/place/...",
  "menuUrl": "https://example.com/menu",
  "menuCategories": ["Platters", "Sandwiches", "Sides", "Beverages", "Desserts"],
  "menuFound": true,
  "itemName": "Chicken and Beef Gyro Platter",
  "isPopular": true,
  "itemImage": "https://lh3.googleusercontent.com/...=s0",
  "rank": 1,
  "scrapedAt": "2026-06-16T12:00:00Z"
}
```

If a restaurant has no inline menu items on Google Maps, the actor pushes a single fallback record (and still surfaces the external `menuUrl` when present):

```json
{
  "businessName": "Some Restaurant",
  "placeUrl": "https://www.google.com/maps/place/...",
  "menuUrl": "https://restaurant.example.com/menu",
  "menuCategories": ["Appetizers", "Mains"],
  "menuFound": false,
  "scrapedAt": "2026-06-16T12:00:00Z"
}
```

Empty / null fields are stripped from output to keep records compact, while every record carries the same set of keys for stable column schemas.

### Field Reference

| Field | Type | Notes |
|---|---|---|
| `businessName` | String | Restaurant name from the place page heading |
| `placeId` | String | Google place feature ID (`0x...:0x...` form) |
| `placeUrl` | String | The original Google Maps URL |
| `menuUrl` | String | External menu link (restaurant site, PDF, ordering portal) when present |
| `menuCategories` | Array\<String> | Menu section names exposed by Google for this restaurant |
| `menuFound` | Boolean | `true` when at least one inline menu item was extracted, `false` otherwise |
| `itemName` | String | Menu item name |
| `isPopular` | Boolean | `true` when Google flags the item as Popular |
| `itemImage` | String | Max-resolution photo URL of the dish (when available) |
| `rank` | Integer | Position of the item within the menu (1-based) |
| `scrapedAt` | String | ISO 8601 UTC timestamp |

### Frequently Asked Questions

**Does every restaurant on Google Maps have a menu?**
No — only restaurants where Google has indexed menu cards expose inline menu items. When inline items aren't available the actor still emits the external `menuUrl` (when the operator has linked one) so you can follow up directly.

**Why no prices on inline items?**
Google Maps does not currently render per-item prices on the place page Menu tab — it shows the dish name, image, and a "Popular" badge but the price (when published) lives behind the external menu link. The actor surfaces every signal Google exposes; if you need item-level prices, follow the `menuUrl` to the restaurant's own menu site.

**Do I need a proxy or cookies?**
No. The actor works reliably from Apify's default datacenter IPs. You can supply Apify Proxy in `proxyConfiguration` as an automatic fallback if a run yields no menu signal.

**Which languages are supported?**
Eleven languages are exposed via the `language` input: English, Spanish, French, German, Italian, Portuguese, Japanese, Korean, Chinese, Arabic, Russian. This controls the Google Maps UI language only — menu item text is returned exactly as published.

**How many items per run?**
The default cap is 100. You can request up to 500 items per run with `maxItems`. Most restaurants surface between 5 and 30 dish cards on Google Maps.

**Can I batch multiple restaurants?**
This actor accepts one `placeUrl` per run. To process many restaurants, schedule the actor with different inputs or chain it inside a workflow that iterates over URLs.

**Why are some fields missing from my records?**
Empty / null fields are stripped to keep your dataset compact. If `itemImage` or `menuUrl` is absent it simply means Google did not publish that detail for that restaurant. Every record always carries `businessName`, `placeUrl`, `menuFound`, and `scrapedAt`.

### Notes & Limitations

- **Google's inline Menu data is shallow.** Google Maps shows dish name + image + a "Popular" badge on the place page, but does not render per-item prices or descriptions inline. Where the operator publishes the full menu (prices, sizes, modifiers, etc.) it lives behind the external `menuUrl` we surface.
- **Coverage varies.** Chains and well-curated places typically expose 5-20 dish cards; many smaller venues expose only the external `menuUrl`. The actor degrades gracefully and always pushes at least one record so you can detect the no-menu case in your pipeline.
- **Place resolution is search-first.** The actor resolves the input URL via Google Maps search; very ambiguous names without coordinates may resolve to a different branch — include `@lat,lng` in the URL when targeting a specific location.

### Complete Google Maps Scraper Suite

This actor is part of a comprehensive Google Maps data extraction toolkit by **crawlerbros**. All actors run on the free Apify plan, use no proxy by default, and return clean, structured data.

| Actor | What it does |
|---|---|
| Google Maps Business Scraper | Extract business data — name, address, phone, website, rating, reviews, hours, amenities |
| Google Maps Reviews Scraper | Scrape reviews with reviewer Local Guide level, photos, mentioned items, owner replies |
| Google Maps Photos Scraper | Extract all photos from any place — max-resolution URLs, contributor info, categories |
| Google Maps Business Hours Scraper | Full 7-day hours, timezone, current local time, next open/close, holiday hours |
| Google Maps Popular Times Scraper | Busy hours histogram for all 7 days + current busyness + typical visit time |
| Google Maps Email Extractor | Find business emails + social media links by crawling websites |
| Google Maps Area Scanner | Geographic grid scanning — bypass the 120-place limit with bounding box / circle / polygon |
| Google Maps Leads Scraper | B2B lead generation with email + phone enrichment, US states + global countries |
| Google Maps Directions Scraper | A→B routing — distance, duration, traffic, route alternatives for driving/walking/transit |
| Google Maps Geocoding Scraper | Bidirectional geocoding — address ↔ coordinates, with address components |
| Google Maps Similar Places Scraper | "People also search for" / related place discovery |
| Google Maps Nearby Scraper | Find places near a coordinate point — lightweight POI search by category |
| Google Maps Place List Scraper | Extract Google's curated "Top X in Y" lists |
| Google Maps Timezone Scraper | IANA timezone + current local time from coordinates |

# Actor input Schema

## `placeUrl` (type: `string`):

Google Maps URL of the restaurant whose menu should be scraped. Copy from the address bar after opening the place on Google Maps.

## `maxItems` (type: `integer`):

Maximum number of menu items to extract (1-500).

## `language` (type: `string`):

Interface language for the Google Maps UI.

## `proxyConfiguration` (type: `object`):

Proxy settings (optional). The scraper works reliably without a proxy by default.

## Actor input object example

```json
{
  "placeUrl": "https://www.google.com/maps/place/The+Halal+Guys/@40.7615453,-73.9794252,17z/data=!3m1!4b1!4m6!3m5!1s0x89c258ff097dbc2d:0x86df3a18a06daf7c!8m2!3d40.7615453!4d-73.9768503",
  "maxItems": 50,
  "language": "en"
}
```

# 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 = {
    "placeUrl": "https://www.google.com/maps/place/The+Halal+Guys/@40.7615453,-73.9794252,17z/data=!3m1!4b1!4m6!3m5!1s0x89c258ff097dbc2d:0x86df3a18a06daf7c!8m2!3d40.7615453!4d-73.9768503",
    "maxItems": 50,
    "language": "en"
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawlerbros/google-maps-menu").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 = {
    "placeUrl": "https://www.google.com/maps/place/The+Halal+Guys/@40.7615453,-73.9794252,17z/data=!3m1!4b1!4m6!3m5!1s0x89c258ff097dbc2d:0x86df3a18a06daf7c!8m2!3d40.7615453!4d-73.9768503",
    "maxItems": 50,
    "language": "en",
}

# Run the Actor and wait for it to finish
run = client.actor("crawlerbros/google-maps-menu").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 '{
  "placeUrl": "https://www.google.com/maps/place/The+Halal+Guys/@40.7615453,-73.9794252,17z/data=!3m1!4b1!4m6!3m5!1s0x89c258ff097dbc2d:0x86df3a18a06daf7c!8m2!3d40.7615453!4d-73.9768503",
  "maxItems": 50,
  "language": "en"
}' |
apify call crawlerbros/google-maps-menu --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Google Maps Menu Scraper",
        "description": "Extract restaurant menu items, popular dishes, photos, categories, and external menu links from any Google Maps place page.",
        "version": "1.1",
        "x-build-id": "ewlx63g4RqgdbLR6a"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/crawlerbros~google-maps-menu/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-crawlerbros-google-maps-menu",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/crawlerbros~google-maps-menu/runs": {
            "post": {
                "operationId": "runs-sync-crawlerbros-google-maps-menu",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/crawlerbros~google-maps-menu/run-sync": {
            "post": {
                "operationId": "run-sync-crawlerbros-google-maps-menu",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "placeUrl"
                ],
                "properties": {
                    "placeUrl": {
                        "title": "Place URL",
                        "type": "string",
                        "description": "Google Maps URL of the restaurant whose menu should be scraped. Copy from the address bar after opening the place on Google Maps."
                    },
                    "maxItems": {
                        "title": "Max Items",
                        "minimum": 1,
                        "maximum": 500,
                        "type": "integer",
                        "description": "Maximum number of menu items to extract (1-500).",
                        "default": 100
                    },
                    "language": {
                        "title": "Language",
                        "enum": [
                            "en",
                            "es",
                            "fr",
                            "de",
                            "it",
                            "pt",
                            "ja",
                            "ko",
                            "zh",
                            "ar",
                            "ru"
                        ],
                        "type": "string",
                        "description": "Interface language for the Google Maps UI.",
                        "default": "en"
                    },
                    "proxyConfiguration": {
                        "title": "Proxy Configuration",
                        "type": "object",
                        "description": "Proxy settings (optional). The scraper works reliably without a proxy by default."
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
