# Google Maps Popular Times Scraper (`coregent/google-maps-popular-times-scraper`) Actor

Extract Google Maps Popular Times for public places: hourly busyness for all 7 days, live busyness when available, typical visit duration, opening hours and canonical place IDs. Input Maps URLs, Place IDs, CIDs or data IDs. No Google login or API key.

- **URL**: https://apify.com/coregent/google-maps-popular-times-scraper.md
- **Developed by:** [Delowar Munna](https://apify.com/coregent) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.50 / 1,000 place popular times lookups

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/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 Popular Times Scraper

![Google Maps Popular Times Scraper](https://raw.githubusercontent.com/coregentdevspace/google-maps-popular-times-scraper-assets/main/thumbnail-google-maps-popular-times-scraper.png "Google Maps Popular Times Scraper")

**Busy Hours, Live Busyness & Visit Duration**

Extract Google Maps Popular Times for public places. Get hourly busyness patterns for all 7 days, live busyness when Google shows it, typical visit duration, opening hours and canonical place identifiers. Export clean JSON, CSV or Excel.

No Google login, no Google Places API key and no cookies needed.

### ✨ What you get

One row per place (or one row per place × day × hour — your choice):

- 📊 **Weekly Popular Times** — Google's hour-by-hour popularity for Monday to Sunday
- 🔴 **Live busyness** for the current hour, when Google shows it ("Busier than usual", "As busy as it gets"), kept separate from the typical pattern
- ⏱️ **Typical visit duration** — Google's text plus parsed min/max minutes ("People typically spend 45 min to 2.5 hr here" → 45 / 150)
- 🕘 **Opening hours** in the place's local time, including split hours and hours past midnight
- 📈 **Peak-hour metrics** — peak day/hour, quietest observed day/hour, weekday vs weekend average, top 3 busy windows
- 📍 **Place identity** — Place ID, CID, data ID, name, category, address, rating, review count, coordinates, **time zone** and business status
- 🏷️ **Honest coverage labels** — a place with no Popular Times is reported as `NO_POPULAR_TIMES`, not as an error and not as a silent gap

### 📥 Supported place inputs

| Input | Example |
|---|---|
| Google Maps place URL | `https://www.google.com/maps/place/Kmart/data=!4m2!3m1!1s0x6b12afd4fffffe11:0xa145a1af6dc452af` |
| Short share link | `https://maps.app.goo.gl/…` |
| Place ID | `ChIJo8ZIgT6uEmsRYhbUtXBWzhg` |
| CID | `1787461144199566946` |
| Data ID (feature ID) | `0x89c259946d150a4d:0xc0da14d18f1c4ac7` |

Mix and match freely. If the same place arrives twice (say as a URL and a Place ID), it is looked up and charged once. This Actor takes exact places; to find places by keyword first, use a Coregent Google Maps business scraper and pass its Place IDs here.

### ⚙️ Input examples

#### Minimal

```json
{
    "placeIds": ["ChIJo8ZIgT6uEmsRYhbUtXBWzhg"]
}
```

#### Competitor benchmarking (Sydney retail, mixed ID types)

Every `include…` option is on by default, so a list of places is all you need. IDs of different types can be mixed in one run.

```json
{
    "placeIds": ["ChIJISz8NjyuEmsRFTQ9Iw7Ear8", "ChIJLfOL-vCtEmsRqjZ6TfY6YW0"],
    "cids": ["5353329816897319418"],
    "dataIds": ["0x6b12ae3e8148c6a3:0x18ce5670b5d41662"]
}
```

#### Hourly rows for spreadsheets, SQL and BI tools

```json
{
    "placeUrls": ["https://www.google.com/maps/place/Kmart/data=!4m2!3m1!1s0x6b12afd4fffffe11:0xa145a1af6dc452af"],
    "outputShape": "HOURLY",
    "includeLiveBusyness": true
}
```

#### Main options

| Field | Default | What it does |
|---|---|---|
| `placeUrls` / `placeIds` / `cids` / `dataIds` | sample place | The places to look up. At least one is required. |
| `outputShape` | `PLACE` | `PLACE` = one row per place with the week nested inside. `HOURLY` = one row per place × day × hour. |
| `includePopularTimes` | `true` | Weekly histogram. |
| `includeLiveBusyness` | `true` | Live reading for the current hour, when available. |
| `includeVisitDuration` | `true` | Typical visit duration. |
| `includeOpeningHours` | `true` | Weekly opening hours (and `isOpenAtHour` in HOURLY rows). |
| `includePlaceDetails` | `true` | Category, address, rating, review count, business status. IDs, name, coordinates and time zone are always included. |
| `includeDerivedMetrics` | `true` | Peak / quietest / averages / busy windows. |
| `proxyConfiguration` | Apify Datacenter | See [Proxy policy](#-proxy-policy). |

### 📤 Output

Results land in two dataset tabs in Apify Console: **Places** (one row per place) and **Hourly** (one row per place × day × hour). Export either as JSON, CSV, Excel or HTML.

#### Places tab (`outputShape: PLACE`)

![Google Maps Popular Times Scraper — Places table view](https://raw.githubusercontent.com/coregentdevspace/google-maps-popular-times-scraper-assets/main/google-maps-popular-times-scraper-output-places-table-view.png "Places table view")

A real row, with all 7 days, scraped on a Thursday at 5 PM Sydney time. The live reading ("A little busy", 67) sits next to the usual value for that hour (80), not inside the weekly pattern. Hours after midnight stay under the day Google shows them, flagged `overnight: true` (see the FAQ).

```json
{
    "rowType": "popular_times_place",
    "place": {
        "placeId": "ChIJISz8NjyuEmsRFTQ9Iw7Ear8",
        "cid": "13793052373775365141",
        "dataId": "0x6b12ae3c36fc2c21:0xbf6ac40e233d3415",
        "name": "Queen Victoria Building",
        "category": "Shopping mall",
        "categories": ["Shopping mall"],
        "address": "455 George St, Sydney NSW 2000, Australia",
        "rating": 4.6,
        "reviewsCount": 21311,
        "businessStatus": "OPERATIONAL",
        "googleMapsUrl": "https://www.google.com/maps/place/?q=place_id:ChIJISz8NjyuEmsRFTQ9Iw7Ear8&hl=en",
        "latitude": -33.8717161,
        "longitude": 151.2067008,
        "timezone": "Australia/Sydney"
    },
    "status": "SUCCESS",
    "coverageStatus": "FULL_POPULAR_TIMES",
    "hasPopularTimes": true,
    "popularTimes": {
        "monday": [
            { "hour": 6, "popularity": 0 },
            { "hour": 7, "popularity": 0 },
            { "hour": 8, "popularity": 0 },
            { "hour": 9, "popularity": 28 },
            { "hour": 10, "popularity": 41 },
            { "hour": 11, "popularity": 53 },
            { "hour": 12, "popularity": 63 },
            { "hour": 13, "popularity": 68 },
            { "hour": 14, "popularity": 69 },
            { "hour": 15, "popularity": 68 },
            { "hour": 16, "popularity": 65 },
            { "hour": 17, "popularity": 56 },
            { "hour": 18, "popularity": 0 },
            { "hour": 19, "popularity": 0 },
            { "hour": 20, "popularity": 0 },
            { "hour": 21, "popularity": 0 },
            { "hour": 22, "popularity": 0 },
            { "hour": 23, "popularity": 0 }
        ],
        "tuesday": [
            { "hour": 6, "popularity": 0 },
            { "hour": 7, "popularity": 0 },
            { "hour": 8, "popularity": 0 },
            { "hour": 9, "popularity": 30 },
            { "hour": 10, "popularity": 42 },
            { "hour": 11, "popularity": 55 },
            { "hour": 12, "popularity": 66 },
            { "hour": 13, "popularity": 71 },
            { "hour": 14, "popularity": 71 },
            { "hour": 15, "popularity": 71 },
            { "hour": 16, "popularity": 68 },
            { "hour": 17, "popularity": 60 },
            { "hour": 18, "popularity": 0 },
            { "hour": 19, "popularity": 0 },
            { "hour": 20, "popularity": 0 },
            { "hour": 21, "popularity": 0 },
            { "hour": 22, "popularity": 0 },
            { "hour": 23, "popularity": 0 }
        ],
        "wednesday": [
            { "hour": 6, "popularity": 0 },
            { "hour": 7, "popularity": 0 },
            { "hour": 8, "popularity": 0 },
            { "hour": 9, "popularity": 30 },
            { "hour": 10, "popularity": 43 },
            { "hour": 11, "popularity": 56 },
            { "hour": 12, "popularity": 67 },
            { "hour": 13, "popularity": 73 },
            { "hour": 14, "popularity": 73 },
            { "hour": 15, "popularity": 73 },
            { "hour": 16, "popularity": 70 },
            { "hour": 17, "popularity": 63 },
            { "hour": 18, "popularity": 0 },
            { "hour": 19, "popularity": 0 },
            { "hour": 20, "popularity": 0 },
            { "hour": 21, "popularity": 0 },
            { "hour": 22, "popularity": 0 },
            { "hour": 23, "popularity": 0 }
        ],
        "thursday": [
            { "hour": 6, "popularity": 0 },
            { "hour": 7, "popularity": 0 },
            { "hour": 8, "popularity": 0 },
            { "hour": 9, "popularity": 32 },
            { "hour": 10, "popularity": 45 },
            { "hour": 11, "popularity": 58 },
            { "hour": 12, "popularity": 69 },
            { "hour": 13, "popularity": 74 },
            { "hour": 14, "popularity": 75 },
            { "hour": 15, "popularity": 76 },
            { "hour": 16, "popularity": 78 },
            { "hour": 17, "popularity": 80 },
            { "hour": 18, "popularity": 70 },
            { "hour": 19, "popularity": 56 },
            { "hour": 20, "popularity": 41 },
            { "hour": 21, "popularity": 0 },
            { "hour": 22, "popularity": 0 },
            { "hour": 23, "popularity": 0 }
        ],
        "friday": [
            { "hour": 6, "popularity": 0 },
            { "hour": 7, "popularity": 0 },
            { "hour": 8, "popularity": 0 },
            { "hour": 9, "popularity": 31 },
            { "hour": 10, "popularity": 44 },
            { "hour": 11, "popularity": 57 },
            { "hour": 12, "popularity": 67 },
            { "hour": 13, "popularity": 74 },
            { "hour": 14, "popularity": 77 },
            { "hour": 15, "popularity": 77 },
            { "hour": 16, "popularity": 72 },
            { "hour": 17, "popularity": 62 },
            { "hour": 18, "popularity": 0 },
            { "hour": 19, "popularity": 0 },
            { "hour": 20, "popularity": 0 },
            { "hour": 21, "popularity": 0 },
            { "hour": 22, "popularity": 0 },
            { "hour": 23, "popularity": 0 }
        ],
        "saturday": [
            { "hour": 6, "popularity": 0 },
            { "hour": 7, "popularity": 0 },
            { "hour": 8, "popularity": 0 },
            { "hour": 9, "popularity": 30 },
            { "hour": 10, "popularity": 49 },
            { "hour": 11, "popularity": 66 },
            { "hour": 12, "popularity": 80 },
            { "hour": 13, "popularity": 91 },
            { "hour": 14, "popularity": 99 },
            { "hour": 15, "popularity": 100 },
            { "hour": 16, "popularity": 91 },
            { "hour": 17, "popularity": 72 },
            { "hour": 18, "popularity": 0 },
            { "hour": 19, "popularity": 0 },
            { "hour": 20, "popularity": 0 },
            { "hour": 21, "popularity": 0 },
            { "hour": 22, "popularity": 0 },
            { "hour": 23, "popularity": 0 }
        ],
        "sunday": [
            { "hour": 6, "popularity": 0 },
            { "hour": 7, "popularity": 0 },
            { "hour": 8, "popularity": 0 },
            { "hour": 9, "popularity": 0 },
            { "hour": 10, "popularity": 0 },
            { "hour": 11, "popularity": 56 },
            { "hour": 12, "popularity": 71 },
            { "hour": 13, "popularity": 81 },
            { "hour": 14, "popularity": 86 },
            { "hour": 15, "popularity": 82 },
            { "hour": 16, "popularity": 68 },
            { "hour": 17, "popularity": 0 },
            { "hour": 18, "popularity": 0 },
            { "hour": 19, "popularity": 0 },
            { "hour": 20, "popularity": 0 },
            { "hour": 21, "popularity": 0 },
            { "hour": 22, "popularity": 0 },
            { "hour": 23, "popularity": 0 }
        ]
    },
    "live": {
        "available": true,
        "currentBusyness": 67,
        "currentBusynessText": "A little busy",
        "usualPopularity": 80,
        "currentDay": "THURSDAY",
        "currentHour": 17
    },
    "visitDuration": { "minMinutes": 15, "maxMinutes": 60, "text": "People typically spend 15 min to 1 hr here" },
    "openingHours": {
        "monday": ["09:00–18:00"],
        "tuesday": ["09:00–18:00"],
        "wednesday": ["09:00–18:00"],
        "thursday": ["09:00–21:00"],
        "friday": ["09:00–18:00"],
        "saturday": ["09:00–18:00"],
        "sunday": ["11:00–17:00"]
    },
    "derived": {
        "peakDay": "SATURDAY",
        "peakHour": 15,
        "peakPopularity": 100,
        "peakOvernight": false,
        "quietestObservedDay": "MONDAY",
        "quietestObservedHour": 9,
        "quietestObservedPopularity": 28,
        "quietestObservedOvernight": false,
        "weekdayAvgPopularity": 60.6,
        "weekendAvgPopularity": 74.8,
        "topBusyWindows": [
            { "day": "SATURDAY", "startHour": 13, "endHour": 16, "avgPopularity": 96.7 },
            { "day": "SUNDAY", "startHour": 13, "endHour": 16, "avgPopularity": 83 },
            { "day": "THURSDAY", "startHour": 15, "endHour": 18, "avgPopularity": 78 }
        ]
    },
    "provider": "direct",
    "error": null,
    "input": "0x6b12ae3c36fc2c21:0xbf6ac40e233d3415",
    "scrapedAt": "2026-10-22T06:21:28.061Z"
}
```

#### Hourly tab (`outputShape: HOURLY`)

The current hour carries the live reading:

```json
{
    "rowType": "popular_times_hour",
    "placeId": "ChIJo8ZIgT6uEmsRYhbUtXBWzhg",
    "cid": "1787461144199566946",
    "dataId": "0x6b12ae3e8148c6a3:0x18ce5670b5d41662",
    "placeName": "Woolworths Town Hall",
    "timezone": "Australia/Sydney",
    "day": "TUESDAY",
    "dayIndex": 2,
    "hour": 15,
    "overnight": false,
    "popularity": 80,
    "popularityText": "Usually as busy as it gets",
    "isOpenAtHour": true,
    "isCurrentHour": true,
    "currentBusyness": 100,
    "currentBusynessText": "As busy as it gets",
    "coverageStatus": "FULL_POPULAR_TIMES",
    "input": "ChIJo8ZIgT6uEmsRYhbUtXBWzhg",
    "scrapedAt": "2026-10-20T04:16:51.372Z"
}
```

#### No-data example

A place Google shows no Popular Times for is a normal, successful lookup. When Google still shows a typical visit duration for such a place, `visitDuration` is filled.

```json
{
    "rowType": "popular_times_place",
    "place": {
        "placeId": "ChIJ9U1mz_5YwokRosza1aAk0jM",
        "cid": "3734087314244816034",
        "dataId": "0x89c258fecf664df5:0x33d224a0d5dacca2",
        "name": "Rockefeller Center",
        "category": "Historical landmark",
        "categories": [
            "Historical landmark",
            "Tourist attraction"
        ],
        "address": "45 Rockefeller Plaza, New York, NY 10111",
        "rating": 4.7,
        "reviewsCount": 202804,
        "businessStatus": "OPERATIONAL",
        "googleMapsUrl": "https://www.google.com/maps/place/?q=place_id:ChIJ9U1mz_5YwokRosza1aAk0jM&hl=en",
        "latitude": 40.7587402,
        "longitude": -73.9786736,
        "timezone": "America/New_York"
    },
    "status": "NO_POPULAR_TIMES",
    "coverageStatus": "NO_POPULAR_TIMES",
    "hasPopularTimes": false,
    "popularTimes": null,
    "live": {
        "available": false,
        "currentBusyness": null,
        "currentBusynessText": null,
        "usualPopularity": null,
        "currentDay": null,
        "currentHour": null
    },
    "visitDuration": null,
    "openingHours": null,
    "derived": null,
    "provider": "direct",
    "error": null,
    "input": "0x89c258fecf664df5:0x33d224a0d5dacca2",
    "scrapedAt": "2026-10-22T06:26:16.866Z"
}
```

#### Status and coverage values

| `status` | Meaning | Charged |
|---|---|---|
| `SUCCESS` | Lookup succeeded and Google showed Popular Times. | Yes |
| `NO_POPULAR_TIMES` | Lookup succeeded; Google shows no Popular Times for this place. | Yes |
| `INVALID_PLACE` | The input isn't a valid place URL / ID. | No |
| `PLACE_NOT_FOUND` | Google has no place for this identifier. | No |
| `PLACE_UNAVAILABLE` | Permanently closed, with no Popular Times. | No |
| `PARTIAL_RESULT` | Google didn't show a panel for this place, so we couldn't check. Retryable. | No |
| `BLOCKED` / `RATE_LIMITED` / `TEMPORARY_GOOGLE_ERROR` / `PROVIDER_ERROR` | Technical failure. Retryable. | No |

`coverageStatus` is one of `FULL_POPULAR_TIMES`, `PARTIAL_POPULAR_TIMES`, `NO_POPULAR_TIMES`, `LIVE_ONLY`, `PLACE_NOT_FOUND` or `PLACE_UNAVAILABLE`. A day with no bars counts as covered when the place is closed that day.

Every run also writes a `RUN_SUMMARY` record (places looked up, with Popular Times, with live busyness, with visit duration, failed, duplicates merged) and, when some places failed for a retryable reason, a `RETRY_INPUT` record you can paste straight into a new run.

### ❓ FAQ

**What are Google Maps Popular Times?** The "Popular times" chart Google shows for many places: how busy the place usually is, hour by hour, on each day of the week.

**Are the values visitor counts?** No. They are Google's **relative popularity index** for that place. `100` is the place's own busiest hour of the week; every other hour is relative to that.

**Is 100 the same as 100% occupancy?** No. It means "as busy as this place usually gets". It says nothing about capacity, and two places' values can't be compared as head counts.

**What is live busyness?** Google's reading for the current hour compared with what's typical, e.g. "Busier than usual". It is reported in `live`, never mixed into the weekly pattern.

**Is live busyness always available?** No. Google shows it only for some places and some hours (often not when the place is closed). `live.available: false` is a normal result.

**Do I need a Google login or API key?** No.

**Are all 7 days included?** Yes, whenever Google has them. Days the place is closed have no bars.

**What time zone are the hours in?** The **place's local time**, never the server's. `place.timezone` names it (e.g. `Europe/Paris`), and `live.currentDay` / `live.currentHour` are the place-local day and hour when the row was scraped.

**How are hours after midnight handled?** A bar's Friday-night 01:00 stays in **Friday's** list, with `overnight: true`, the way Google draws it, so a late night isn't split in two. Opening hours like `"14:00–04:00"` are kept as one interval.

**Are opening hours included?** Yes (`includeOpeningHours`), including split hours, closed days (`[]`) and 24-hour places (`"00:00–24:00"`).

**Is typical visit duration included?** Yes, when Google shows it. The text is always kept; min/max minutes are filled only when the text parses unambiguously.

**What if a place has no Popular Times?** You get a row with `status: NO_POPULAR_TIMES`. That is the answer to your question, not a technical failure.

**What is PLACE vs HOURLY output?** PLACE gives one row per place with the week nested inside, which suits JSON and APIs. HOURLY gives one row per place × day × hour, which suits spreadsheets, SQL, BI tools and charts. A place is charged once either way; HOURLY costs a little more per place (see [Pricing](#-pricing)).

**Some places came back `BLOCKED` or `TEMPORARY_GOOGLE_ERROR`. What should I do?** Re-run them. Google sometimes throttles automated traffic for a few minutes. The Actor pauses and retries when that happens. If Google keeps blocking for several minutes, the run stops early rather than waiting, and the places it didn't reach come back as `BLOCKED`. Those places are **not charged**, and the run's `RETRY_INPUT` record already lists them: paste it into a new run, ideally 15–30 minutes later. For large or frequent runs, your own residential proxy cuts throttling the most (see [Proxy policy](#-proxy-policy)).

**How does pricing work?** See [Pricing](#-pricing).

**Can I use it through the API or MCP?** Yes. Like every Apify Actor, it can be run through the Apify API, the Apify clients, or as a tool through the Apify MCP server.

**Can I schedule recurring live-busyness checks?** Yes. Create an Apify schedule with the same input; each run records the live reading at that moment with a `scrapedAt` timestamp.

### 💰 Pricing

Pay per event — you pay only for results:

- **One event per unique place whose lookup succeeded**, with or without Popular Times. "No Popular Times" is itself a useful answer, so it counts.
- HOURLY output has its own per-place event, priced a little higher than PLACE because each place produces up to 168 rows. It is still charged once per place, however many hour rows it produces.
- Not charged: duplicate places, malformed inputs, places that couldn't be found or verified, technical failures and retries.
- There is no start fee, so an empty or fully-failed run costs nothing in events.

Live rates are on the Actor's **Pricing** tab in Apify Console. This README deliberately doesn't quote figures, because they can change.

The Actor respects the **Maximum cost per run** you set: it stops looking up new places once the limit is reached and writes the rest to `RETRY_INPUT`.

#### 🚦 Proxy policy

Use **Apify Datacenter** proxy (default) or **no proxy** for normal runs.

**Apify Residential proxy is not supported.** The Actor fails at startup if `apifyProxyGroups` includes `RESIDENTIAL`. Reason: in pay-per-event Actors, residential bandwidth is billed to the developer, not the run user, so one bandwidth-heavy run could exceed the per-place event revenue.

Google throttles datacenter IPs more than home connections. For most runs that only means a few automatic retries. If you run thousands of places, or run often, and see many `BLOCKED` rows, use your own residential provider. Supply it in the proxy editor's **Custom proxy URLs** field. That traffic goes through your provider, not Apify, and is allowed:

```
http://user:pass@proxy.iproyal.com:12321
http://user:pass@proxy.brightdata.com:22225
http://user:pass@proxy.oxylabs.io:7777
```

### 🔗 Works well with

- **Coregent Google Maps business / lead scrapers.** Find places by keyword and location, then feed their Place IDs here.
- **Google Maps Reviews Scraper.** Reviews give the qualitative side; Popular Times gives the traffic pattern. Both use the same `placeId` / `cid` / `dataId` keys.

### ⚖️ Compliance and data interpretation

- This is an unofficial tool. It is not affiliated with, endorsed by or sponsored by Google.
- It reads only publicly visible place information, without logging in.
- Popular Times and live busyness are Google-derived **relative activity indicators**. They are not verified customer counts, occupancy, revenue or sales volume.
- The data changes over time, and live readings change hour to hour.
- You are responsible for how you interpret and use the data, and for complying with applicable laws and Google's terms.

### 🛠️ Limitations

- Popular Times exists only for places Google has enough data on. Many small, new or private places have none (`NO_POPULAR_TIMES`).
- Live busyness is intermittent by nature.
- A long throttling wave stops the run early and leaves the remaining places `BLOCKED`. They are free and listed in `RETRY_INPUT` for a re-run.
- Google's labels (`popularityText`, live text, visit-duration text) are returned in English.
- A permanently closed place without Popular Times is reported as `PLACE_UNAVAILABLE`.
- Keyword or area discovery isn't included; pass exact places.

# Actor input Schema

## `placeUrls` (type: `array`):

Google Maps place URLs or short share links (maps.app.goo.gl/…). One place per URL. The sample place is ignored automatically when you fill in Place IDs, CIDs or data IDs.

## `placeIds` (type: `array`):

Google Place IDs, e.g. ChIJN1t_tDeuEmsRUsoyG83frY4.

## `cids` (type: `array`):

Google Maps CIDs (customer IDs) — digits only, e.g. 17765624140264603025.

## `dataIds` (type: `array`):

Google Maps data / feature IDs in 0x…:0x… form, e.g. 0x6b12ae3e8148c6a3:0x18ce5670b5d41662. Other Coregent Google Maps Actors output these.

## `outputShape` (type: `string`):

PLACE = one row per place with the weekly Popular Times nested inside. HOURLY = one row per place × day × hour — ready for spreadsheets, SQL and BI tools. Either way a place is charged once.

## `includePopularTimes` (type: `boolean`):

The typical hour-by-hour popularity for all 7 days (Google's relative 0–100 index, not visitor counts).

## `includeLiveBusyness` (type: `boolean`):

Google's live reading for the current hour (e.g. "Busier than usual"), when Google shows one. Often unavailable — that is a normal result, not an error.

## `includeVisitDuration` (type: `boolean`):

"People typically spend 15 min to 1 hr here" — the text plus parsed min/max minutes when Google shows it.

## `includeOpeningHours` (type: `boolean`):

Weekly opening hours in the place's local time, including split and past-midnight hours. In HOURLY output this also fills isOpenAtHour.

## `includePlaceDetails` (type: `boolean`):

Category, address, rating, review count and business status. Identifiers, name, coordinates and time zone are always included.

## `includeDerivedMetrics` (type: `boolean`):

Peak day/hour, quietest observed day/hour, weekday vs weekend average and the top busy windows — computed from Google's histogram (PLACE output).

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

Apify Proxy configuration. Defaults to Apify Datacenter (useApifyProxy: true). Apify Residential is NOT supported and fails the run at startup; for residential routing supply your own provider via Custom proxy URLs (proxyConfiguration.proxyUrls).

## Actor input object example

```json
{
  "placeUrls": [
    "https://www.google.com/maps/place/?q=place_id:ChIJo8ZIgT6uEmsRYhbUtXBWzhg"
  ],
  "placeIds": [],
  "cids": [],
  "dataIds": [],
  "outputShape": "PLACE",
  "includePopularTimes": true,
  "includeLiveBusyness": true,
  "includeVisitDuration": true,
  "includeOpeningHours": true,
  "includePlaceDetails": true,
  "includeDerivedMetrics": true,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `overview` (type: `string`):

One row per place: weekly Popular Times, live busyness, visit duration, opening hours, peak-hour metrics and coverage status.

## `hourly` (type: `string`):

One row per place × day × hour (when Output shape = HOURLY).

# 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 = {
    "placeUrls": [
        "https://www.google.com/maps/place/?q=place_id:ChIJo8ZIgT6uEmsRYhbUtXBWzhg"
    ],
    "includePopularTimes": true,
    "includeLiveBusyness": true,
    "includeVisitDuration": true,
    "includeOpeningHours": true,
    "includePlaceDetails": true,
    "includeDerivedMetrics": true,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("coregent/google-maps-popular-times-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 = {
    "placeUrls": ["https://www.google.com/maps/place/?q=place_id:ChIJo8ZIgT6uEmsRYhbUtXBWzhg"],
    "includePopularTimes": True,
    "includeLiveBusyness": True,
    "includeVisitDuration": True,
    "includeOpeningHours": True,
    "includePlaceDetails": True,
    "includeDerivedMetrics": True,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("coregent/google-maps-popular-times-scraper").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 '{
  "placeUrls": [
    "https://www.google.com/maps/place/?q=place_id:ChIJo8ZIgT6uEmsRYhbUtXBWzhg"
  ],
  "includePopularTimes": true,
  "includeLiveBusyness": true,
  "includeVisitDuration": true,
  "includeOpeningHours": true,
  "includePlaceDetails": true,
  "includeDerivedMetrics": true,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call coregent/google-maps-popular-times-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,coregent/google-maps-popular-times-scraper"
        }
    }
}
```

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/PkcrNEoDt2wwzlEfT/builds/v38GHRg2sua6aG536/openapi.json
