Google Maps Popular Times Scraper avatar

Google Maps Popular Times Scraper

Pricing

from $2.50 / 1,000 place popular times lookups

Go to Apify Store
Google Maps Popular Times Scraper

Google Maps Popular Times Scraper

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.

Pricing

from $2.50 / 1,000 place popular times lookups

Rating

0.0

(0)

Developer

Delowar Munna

Delowar Munna

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Categories

Share

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

InputExample
Google Maps place URLhttps://www.google.com/maps/place/Kmart/data=!4m2!3m1!1s0x6b12afd4fffffe11:0xa145a1af6dc452af
Short share linkhttps://maps.app.goo.gl/…
Place IDChIJo8ZIgT6uEmsRYhbUtXBWzhg
CID1787461144199566946
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

{
"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.

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

Hourly rows for spreadsheets, SQL and BI tools

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

Main options

FieldDefaultWhat it does
placeUrls / placeIds / cids / dataIdssample placeThe places to look up. At least one is required.
outputShapePLACEPLACE = one row per place with the week nested inside. HOURLY = one row per place × day × hour.
includePopularTimestrueWeekly histogram.
includeLiveBusynesstrueLive reading for the current hour, when available.
includeVisitDurationtrueTypical visit duration.
includeOpeningHourstrueWeekly opening hours (and isOpenAtHour in HOURLY rows).
includePlaceDetailstrueCategory, address, rating, review count, business status. IDs, name, coordinates and time zone are always included.
includeDerivedMetricstruePeak / quietest / averages / busy windows.
proxyConfigurationApify DatacenterSee 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

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

{
"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:

{
"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.

{
"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

statusMeaningCharged
SUCCESSLookup succeeded and Google showed Popular Times.Yes
NO_POPULAR_TIMESLookup succeeded; Google shows no Popular Times for this place.Yes
INVALID_PLACEThe input isn't a valid place URL / ID.No
PLACE_NOT_FOUNDGoogle has no place for this identifier.No
PLACE_UNAVAILABLEPermanently closed, with no Popular Times.No
PARTIAL_RESULTGoogle didn't show a panel for this place, so we couldn't check. Retryable.No
BLOCKED / RATE_LIMITED / TEMPORARY_GOOGLE_ERROR / PROVIDER_ERRORTechnical 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).

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

How does pricing work? See 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.