From 1 API to 3 Different APIs: The Architecture Required to Unlock Google Maps Restaurant Search

July 26, 2026

When you run a search for restaurants in Google Maps with a 4.5+ star filter, they call their Text Search API, which returns at most 60 places.

Text Search with a query of restaurants and a minimum rating of 4.5 returns at most 60 places, delivered 20 per page across 3 pages.

There can be far more than 60 places matching, but they aren't returned.

Here's how TopSpots gets you all of them:

The reason I started making TopSpots was to find restaurants with 4.5+ stars and 1,000+ ratings on Google Maps. Google Maps has many APIs and filtering by rating (stars) typically exists on those, but filtering by rating count is less supported. Google Maps Place Details API is the one that, given a Place ID, returns everything like name, price, cuisine, and most importantly rating count.

In order to get Place IDs to give to Place Details, we use the Aggregate API, which has no 60 result ceiling. It allows us to filter by minRating/maxRating, place type, price level, and operating status.

We have a few options of what we can give Aggregate API:

  • Circle, defined by a center and a radius.
  • Region, defined by a place ID, which represents a geographical area (such as an area representable by a polygon). For example, the place ID of Tampa, FL is places/ChIJ4dG5s4K3wogRY7SWr4kTX6cGoogle Maps docs
  • Custom polygon, which can have up to 7,000 vertices

When I started making the app I also considered a data visualization feature to compare the ratio of TopSpots to total restaurants within a city as a way to compare cities' food scenes. Region would've been convenient for that, but it's too big. Austin has 1,600+ places with 4.5+ stars so searching all of them to find TopSpots (4.5+, 1,000+) would cost $32 for 1,600 Place Details calls. Circle might be neat but search areas may be irregular like a thin rectangle.

Now that we're left with polygon as our only possible input choice, how many vertices should my polygon have? One issue I ran into is when I realized that Aggregate API returns 100 Place IDs max per search, so I realized I need recursive subdividing. If I have a polygon drawn over a city, how do I break it down into sub-polygons that have at most 100 matches inside? The same Aggregate API call we make to get Place IDs has another mode to return a count of places, so we call that first to get the number of matches then split until it returns anything 100 or less.

There's a range of approaches. You could scale the split to the count: 400+ splits into 4, 200 or fewer into 2. That's about the simplest version of the idea, and it can get far more involved from there. Regardless I just stuck it at 4 to keep it simple:

Recursive quad-tree subdivision: a polygon holding 2,382 places splits into four quadrants, and quadrants still over 100 split again while quadrants of 100 or fewer stop and have their place IDs collected.

That covers the two Aggregate API calls. The last one is Place Details. All we have at this point is a list of IDs like places/ChIJN1t_tDeuEmsRUsoyG83frY4, which tells us a restaurant has 4.5+ stars and nothing else. Place Details takes the ID and gives us the review count, so we can now know which have 1,000+ reviews. This is also where we get all the other information like name, price, cuisine, and more.

The three-part search: step 1 Count and step 2 Collect both use the Aggregate API, step 2 loops back into itself when a polygon holds over 100 places, and when 100 or fewer remain step 3 Hydrate calls the Place Details API.