# Google Maps Top List & Ranked Places Extractor (`dataspryva/google-maps-top-list-and-ranked-places-extractor`) Actor

Pull the ranked places from a Google Maps Top list query like 'Top hotels in Paris', or from a list/search URL, with optional full place-page enrichment.

- **URL**: https://apify.com/dataspryva/google-maps-top-list-and-ranked-places-extractor.md
- **Developed by:** [Dataspryva](https://apify.com/dataspryva) (community)
- **Categories:** Travel, Lead generation, Automation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.49 / 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/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Google Maps Top List & Ranked Places Extractor

Google Maps ranks the places in a "Top hotels in Paris" search and in every shared list you save. This actor reads that ranked order — directly from Google's public Maps endpoints, without a browser, cookies, an API key, or proxy setup — and writes one row per place.

It handles two kinds of inputs:

- **Top-list queries** such as *Top hotels in Paris*, *Best coffee in Brooklyn*, or *Things to do in Tokyo*.
- **Shared list links** such as `https://www.google.com/maps/placelists/list/...` or a short `maps.app.goo.gl` link. A Maps search URL is accepted too.

### What you get

- The **rank** Google gives each place, plus the query or list it came from.
- Shared-list context: list title and description, list ID, owner, the saver's note, and the saved date.
- Business facts: category, rating, review count, address, phone, website, hours, open/closed status, coordinates, price, and Place IDs.
- Optional detail enrichment: Plus Code, rating histogram, photos, amenities, service options, booking links, hotel stars and amenities, fuel prices, and closure flags.

No record contains `null`, empty strings, or empty arrays. A field Google does not publish for a place is omitted.

### Example row

```json
{
  "recordType": "business",
  "rank": 1,
  "listSource": "Top hotels in Paris",
  "name": "Four Seasons Hotel George V, Paris",
  "categoryName": "Hotel",
  "categories": ["Hotel", "Spa", "Wedding venue"],
  "totalScore": 4.8,
  "reviewsCount": 7414,
  "address": "31 Av. George V, 75008 Paris, France",
  "phone": "+33 1 49 52 70 00",
  "website": "https://www.fourseasons.com/paris/",
  "price": "PKR 663K",
  "priceLevel": "€€€€",
  "highlights": ["Pool", "Spa", "Hot tub", "Free parking"],
  "placeId": "ChIJAcNYmcJv5kcR7EQ_IeMZp8c",
  "featureId": "0x47e66fc29958c301:0xc7a719e3213f44ec",
  "location": { "lat": 48.8688005, "lng": 2.3008313 },
  "googleMapsUrl": "https://www.google.com/maps/place/?q=place_id:ChIJAcNYmcJv5kcR7EQ_IeMZp8c",
  "scrapedAt": "2026-11-06T09:00:00+00:00"
}
```

#### Field notes

- `rank` is the position Google returned for that query or list, starting at 1. Filtering never renumbers it.
- `placeId` is the canonical `ChIJ...` ID. A legacy `0x...:0x...` token is kept separately in `featureId`.
- `price` is the amount Google prints on a hotel card, kept verbatim (currency and K/M shorthand included). `priceLevel` is Google's standing band such as `$$$` or a dining price range.
- `highlights` are the short feature pills on a hotel list card. `amenities` is the fuller badge set from the place page.
- `note` and `savedAt` come from the shared list and are present only for list rows. `listTitle` and `listDescription` carry the list's own title and description.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | Select | `topList` | `topList` for ranked queries, `listUrl` for shared-list or Maps URLs. |
| `queries` | String list | – (prefill: `["Top hotels in Paris"]`) | One or more ranked queries. |
| `location` | String | – | Appended to every query when the query does not already mention it. |
| `listUrls` | String list | – | Public shared-list links or Maps search URLs. |
| `maxResults` | Integer | `30` | Maximum places per query or list. |
| `enrichDetails` | Boolean | `true` | Visit each place record for the detail-only fields. |
| `language` | Select | `en` | 70+ Google Maps interface languages. |
| `minRating` / `maxRating` | Number | – | Rating bounds (0–5). |
| `minReviews` / `maxReviews` | Integer | – | Review-count bounds. |
| `openNow` | Boolean | `false` | Keep places Google marks open now. |
| `hasWebsite` / `hasPhone` | Boolean | `false` | Require a published website or phone. |
| `includeClosed` | Boolean | `true` | When off, permanently closed places are dropped. |
| `nameFilter` | String | – | Keep names containing this text. |
| `excludeCategories` | String list | – | Drop categories containing any listed word. |
| `includeCategories` | String list | – | Keep categories containing any listed word. |
| `countryCodes` | String list | – | Keep places in these two-letter countries (FR, US, JP…). |

Saved tasks that still send the old single-value `query` or `listUrl` keep working: the actor maps those keys in code.

### Examples

#### Ranked hotels

```json
{
  "mode": "topList",
  "queries": ["Top hotels in Paris"],
  "maxResults": 10,
  "enrichDetails": true,
  "language": "en"
}
```

#### Fast card-only run

```json
{
  "mode": "topList",
  "queries": ["Best sushi restaurants in Tokyo"],
  "maxResults": 25,
  "enrichDetails": false,
  "language": "ja"
}
```

#### A shared list

```json
{
  "mode": "listUrl",
  "listUrls": ["https://www.google.com/maps/placelists/list/oMnWVsXSvFX9Bh2O5-71TApDgffWvg"],
  "maxResults": 5000,
  "enrichDetails": false
}
```

### Use cases

- Travel research: compile ranked hotels, restaurants and attractions per city.
- Local SEO: compare how a category ranks across markets.
- Lead generation: export name, rating, phone, website and address from a shortlist.
- Content: turn shared "best of" lists into structured tables.
- Site selection: measure the density and quality of a category in an area.

### FAQ

**Does it need cookies, a login or an API key?**
No. Every mode reads public Google Maps data.

**Do I need to configure a proxy?**
No. The actor chooses its connection automatically. There is no proxy field to fill in.

**How many places can a query return?**
It varies by query and city. Broad categories commonly expose 150–450 ranked places; narrow queries expose fewer. The actor follows Google's pages until `maxResults`, the end of the result window, or the source's own stop signal.

**How many places can a shared list have?**
The public list endpoint returns the whole list in one response. This actor requests up to 5,000 places per list; that is the practical source window for very large lists.

**Why did I get fewer rows than `maxResults`?**
Google's result window ended, the list was shorter, or filters removed rows. The run status says which case applies and how many rows the filters skipped.

**What does `enrichDetails` add?**
Plus Code, rating histogram, photos, amenities, service options, booking links, hotel details, fuel prices and closure flags. It costs one extra request per place; turn it off when the list-card fields are enough.

**Are sponsored places included?**
No. Google can print paid hotel cards at the top of a feed. They are excluded, so `rank` follows the organic list, as in the previous version.

**Are `popularTimesSummary` and `menuLink` filled?**
`popularTimesSummary` is not published by the public Maps feed used here, so it is not emitted. `menuLink` appears only when a place's detail data exposes a menu URL, which is rare. Use the dedicated popular-times or menu actor when you need those fields.

**Does it support non-English Maps?**
Yes. Pick any language in the dropdown; names, categories, addresses and hours are localized by Google.

**What happens when Google blocks a request?**
The actor retries and escalates its connection automatically. If no result view ever arrives, the run status says it was an upstream block or degraded response — never "no places found".

**Is this affiliated with Google?**
No. It is an independent tool that reads publicly available Google Maps pages. You are responsible for using the data lawfully and consistently with Google's terms.

# Actor input Schema

## `mode` (type: `string`):

Use 'topList' for ranked queries like 'Top hotels in Paris'. Use 'listUrl' for a shared Google Maps list link or a Maps search URL.

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

Ranked list queries. For example: 'Top hotels in Paris', 'Best coffee in Brooklyn', 'Things to do in Tokyo'. Each query is scraped separately.

## `location` (type: `string`):

Optional city, neighborhood or region appended to every query when it is not already mentioned.

## `listUrls` (type: `array`):

Public Google Maps shared-list links (google.com/maps/placelists/list/...) or Maps search URLs. Short maps.app.goo.gl links are resolved automatically.

## `maxResults` (type: `integer`):

Maximum places to return per query or list. The public feed may expose fewer; lists are returned up to the source window.

## `enrichDetails` (type: `boolean`):

Adds Plus Code, rating histogram, photos, amenities, price range, booking links, closure state and hotel details. Turn it off for the fastest, smallest runs using list-feed data only.

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

Google Maps interface language. Names, categories, addresses and hours are localized.

## `minRating` (type: `number`):

Drop places with a lower rating or no published rating.

## `maxRating` (type: `number`):

Drop places with a higher rating.

## `minReviews` (type: `integer`):

Drop places with fewer reviews or no published review count.

## `maxReviews` (type: `integer`):

Drop places with more reviews.

## `openNow` (type: `boolean`):

Keep only places Google currently marks as open.

## `hasWebsite` (type: `boolean`):

Keep only places with a published website.

## `hasPhone` (type: `boolean`):

Keep only places with a published phone number.

## `includeClosed` (type: `boolean`):

When disabled, permanently closed places are dropped. This needs full place details.

## `nameFilter` (type: `string`):

Keep only places whose name contains this text (case-insensitive).

## `excludeCategories` (type: `array`):

Drop places whose primary or secondary category contains any of these words.

## `includeCategories` (type: `array`):

Keep places whose primary or secondary category contains any of these words.

## `countryCodes` (type: `array`):

Keep places in these two-letter countries, e.g. FR, US, JP. Empty means all countries.

## Actor input object example

```json
{
  "mode": "topList",
  "queries": [
    "Top hotels in Paris"
  ],
  "location": "",
  "maxResults": 3,
  "enrichDetails": false,
  "language": "en",
  "minRating": 0,
  "maxRating": 5,
  "minReviews": 0,
  "maxReviews": 0,
  "openNow": false,
  "hasWebsite": false,
  "hasPhone": false,
  "includeClosed": true,
  "nameFilter": "",
  "excludeCategories": [],
  "includeCategories": [],
  "countryCodes": []
}
```

# Actor output Schema

## `places` (type: `string`):

Each item contains only fields observed on the public list or place page.

# 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": [
        "Top hotels in Paris"
    ],
    "location": "",
    "maxResults": 3,
    "enrichDetails": false,
    "language": "en",
    "minRating": 0,
    "maxRating": 5,
    "minReviews": 0,
    "maxReviews": 0,
    "openNow": false,
    "hasWebsite": false,
    "hasPhone": false,
    "includeClosed": true,
    "nameFilter": "",
    "excludeCategories": [],
    "includeCategories": [],
    "countryCodes": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("dataspryva/google-maps-top-list-and-ranked-places-extractor").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": ["Top hotels in Paris"],
    "location": "",
    "maxResults": 3,
    "enrichDetails": False,
    "language": "en",
    "minRating": 0,
    "maxRating": 5,
    "minReviews": 0,
    "maxReviews": 0,
    "openNow": False,
    "hasWebsite": False,
    "hasPhone": False,
    "includeClosed": True,
    "nameFilter": "",
    "excludeCategories": [],
    "includeCategories": [],
    "countryCodes": [],
}

# Run the Actor and wait for it to finish
run = client.actor("dataspryva/google-maps-top-list-and-ranked-places-extractor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).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": [
    "Top hotels in Paris"
  ],
  "location": "",
  "maxResults": 3,
  "enrichDetails": false,
  "language": "en",
  "minRating": 0,
  "maxRating": 5,
  "minReviews": 0,
  "maxReviews": 0,
  "openNow": false,
  "hasWebsite": false,
  "hasPhone": false,
  "includeClosed": true,
  "nameFilter": "",
  "excludeCategories": [],
  "includeCategories": [],
  "countryCodes": []
}' |
apify call dataspryva/google-maps-top-list-and-ranked-places-extractor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,dataspryva/google-maps-top-list-and-ranked-places-extractor"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/YpWNF6hudIGBsowV8/builds/LQuqRWbzWdl2Ey9lU/openapi.json
