Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Google Popular Times Scraper API

google-popular-times-scraper-api

checks license

If you are here for the bar chart, read this section before you write any code. A google popular times api that returns the hour by hour busyness histogram does not exist in this endpoint, and this README says so up front rather than letting you find out after a hundred calls.

What the Maps endpoint does return is the rest of the place record, including full opening hours, ratings and review volume, for 10 credits. For the staffing and footfall questions people actually bring to popular times, those fields get you most of the way, and this repo shows how.

Built on ScrapingBee's Google endpoint. Verified live on 2026-09-15.

The negative, stated plainly

search_type=maps returns a maps_results array of 20 places. Every field on it, checked against a live response:

position  title  link  address  rating  reviews  price  category  cid  phone  opening_hours

Searching the full JSON payload for popular_times, populartimes, popular times, busy, live_busy and histogram returns false on all six. The documented parameter list for the endpoint is search, search_type, country_code, device, latitude, longitude, radius, page, pages, date_range, sort_by, min_price, max_price, nfpr, add_html, light_request, extra_params, name and tag. There is no popular times parameter and no popular times field.

Going around the endpoint does not help either. A google.com/search URL through the HTML API requires custom_google=true at 20 credits, and the attempt returned "reason": "Server responded with 500", "help": "CAPTCHA".

So: opening hours yes, live busyness no.

Pin the map, or your results are 1,500 km away

This is the failure that wastes the most time, because it returns confident, well formed, completely wrong data.

Query by name alone and the endpoint centres the map on the geographic middle of the United States:

"meta_data": {
  "url": "https://www.google.com/maps/search/starbucks%20times%20square%20new%20york/@38.0,-97.0,10z",
  "location": "lat:38.0,lon:-97.0,zoom:10"
}

Two live examples of what that produces:

Query Result
starbucks manhattan First hit is 4747 S Broadway, Wichita, KS
starbucks times square new york 0 results

Putting the city in the search string does nothing, and neither does country_code. The map pin is set by latitude, longitude and radius, and only by those:

curl -G "https://app.scrapingbee.com/api/v1/google" \
  -H "Authorization: Bearer $SCRAPINGBEE_API_KEY" \
  --data-urlencode "search=starbucks" \
  -d search_type=maps -d latitude=40.7580 -d longitude=-73.9855 -d radius=1000 -d country_code=us

Now the map reads lat:40.758,lon:-73.9855,zoom:16 and the results are real:

Starbucks Coffee Company   1500 Broadway, New York, NY 10036    4.0  2255 reviews
Starbucks Coffee Company   1585 Broadway, New York, NY 10036    3.9  1371 reviews
Starbucks Coffee Company   770 8th Ave, New York, NY 10036      3.5   497 reviews
Starbucks Coffee Company   750 7th Ave, New York, NY 10019      3.9   544 reviews

Twenty results, all within a few blocks. Note the radius is in metres. Drop the coordinates and you are back in Kansas.

What you get instead of a histogram

opening_hours is the field that carries most of the staffing answer:

{
  "current": "Open · Closes 12 AM",
  "per_day": [
    {"name": "Tuesday",   "value": "5 AM–12 AM"},
    {"name": "Wednesday", "value": "5 AM–12 AM"},
    {"name": "Thursday",  "value": "5 AM–12 AM"},
    {"name": "Friday",    "value": "5 AM–12 AM"},
    {"name": "Saturday",  "value": "5 AM–12 AM"}
  ]
}

current is a live status string, so it tells you open or closed at fetch time and when the state next changes. per_day gives the weekly schedule. Between them you can answer "which of these sites is open at 6am on a Sunday" without any busyness data at all.

For the competitor footfall question, reviews is the usable proxy. Review count is a rough function of how many people pass through a location over its lifetime, so within one brand and one city it ranks locations by traffic reasonably well. On the four stores above, 2,255 against 497 reviews is a real signal about which of two Starbucks four blocks apart is the busier site. It is a cumulative measure rather than an hourly one, so it answers "which location" and not "which hour".

cid is the stable Google place identifier, which is what you key a table on across repeated pulls. title, address, category, phone, rating and price complete the record.

Sweeping an area properly

Because the pin is coordinate based, area coverage is a grid rather than a list of place names:

for lat, lon in grid(city_bbox, step_m=800):
    places = maps("coffee", latitude=lat, longitude=lon, radius=1000)

Twenty results per call is the cap, so in a dense area one point does not see everything. Overlapping circles at a step smaller than the radius, then deduplicating on cid, is what gives you real coverage. At 10 credits a call, a 5 by 5 grid is 250 credits per category per city.

Credit cost

Measured from spb-cost response headers:

Call Credits
/api/v1/google with search_type=maps 10
google.com URL through the HTML API, needs custom_google=true 20, and it hit a CAPTCHA
Rejected or failed request 0

The Google endpoint also has a light_request toggle, as the other dedicated endpoints do. A failed request costs nothing, which matters here because the transient {"error": "Please try again (you will not be charged for this request)"} does show up and is worth one retry.

Plan tiers are on the pricing page.

Scope

Public Google Maps place results. Nothing here signs in, and scraping under login credentials is prohibited by ScrapingBee's terms of service.

Place records describe real businesses and carry phone numbers, so treat them accordingly. Google publishes an official Places API whose Place Details response does include a current_opening_hours structure, and which is the supported route when you need guaranteed fields and licensing. Google Maps Platform terms apply to that route.

Reference: Google API documentation, extraction rules, AI web scraping.

Adjacent local endpoints: local results API, Google reviews results API, review API, Bing maps API, Bing local search API, Naver places reviews API.

FAQ

Does this return Google popular times? No. The histogram is not in the response and there is no parameter for it. Six different field name probes against the live payload all came back empty. Opening hours, ratings and review counts are what the endpoint carries.

Why are my results in the wrong city? Because you did not pass coordinates. Name alone centres the map at lat 38.0, lon -97.0, which is the middle of the United States. Use latitude, longitude and radius.

Does country_code fix the location? No. It sets the Google domain and locale, not the map centre. Only the coordinate parameters move the pin.

What unit is radius? Metres.

How do I estimate how busy a location is? Use reviews as a cumulative footfall proxy and compare locations within the same brand and city. It ranks sites, it does not give you hours.

How many results per call? Twenty. Cover an area with overlapping coordinate points and deduplicate on cid.

License

MIT. See LICENSE.