How to Use the Google Places API for Location Analysis and More | by Jordan Bean | Towards Data Science

One topic in analytics that interests me is location analytics and thinking about how to bring a more data-driven approach to location scouting, especially for smaller companies that don’t have the resources of, say, a Target or Starbucks. I’ve written a couple of articles (here, here, and here) about different approaches we can take and examples of how to put them into practice.
As a part of a recent consulting project, I found myself searching how to gather location-level competitive information. Not just how many competitors exist in a region, but at a specific street level. Further, the information available from official sources didn’t work for this business because the categorization was too broad and would include companies this business wouldn’t consider like-for-like competitors.
During this search, I came across the Google Places API. Imagine you want to find a coffee shop near you. You head to Google Maps and do a freeform search for coffee. Several pins pop up with local results that match your search.
When you click on one, it displays some helpful information about the location, like its Google Reviews rating, number of reviews, price category (the single $ next to the reviews), address, and more.
The Google Places API effectively executes this search for you within the specified parameters and returns the results for each location that appears from the search. This allows us to pull information on any business type that appears in a Google Maps search in any location where Google Maps operates (which, according to Google, is 200+ countries and 99% global coverage).
As someone without a programming background, I found it a little difficult to try and interpret how to use the API for the first time and to understand how pricing works (it’s not free, but they have recurring monthly credits that give you substantial access before you start paying).
Below, I’ll lay out easy-to-follow steps on how to access the API to use the data for your own projects and purposes. As an example I’m going to walk through the process I used to pull coffee shop locations in a series of zip codes as a part of a hypothetical location analysis for Starbucks.
First thing first is to register for a Google Cloud account. Upon signing up, you may receive a $300 credit in addition to a free $200 per month in credits.
Once you’ve made an account and are on the Google Cloud platform, you’ll want to go to use the drop down navigation in the top left and choose API & Services > Credentials. Once there, you’ll want to hit Create Credentials on the top followed by API key. This will generate an alphanumeric string that identifies your Google Cloud account when you make a call to the API.
We’ll use the credential later when making a call to the Places API, but for now, that’s all you need to get going!
Once you have your API credential, the next part of the process can be done in the programming language of your choice. I’ve used Python but if you’re an R user you can very easily modify the last steps of the process to be done with R code.
Though intimidating at first, the Places API Documentation has all of the information you need to execute the call to the API with your specified parameters.
Since we’ll be executing an “ambiguous text string” (i.e. not searching for a specific location but rather for coffee shops generally), I’ll cover how to use the Text Search requests within the Places documentation/API.
To make a call to the API, we need to construct a URL string. Each required and optional parameter that we want to use needs to be included in the string. We can find each of the parameter options, what they are, and how to use them under the Optional Parameters section of the documentation.
To construct the string, let’s go step-by-step to see what’s actually happening and how to use it. Most of these are optional parameters that you can switch out depending on your use case but the essence of how to use any parameters in the documentation is the same.
https://maps.googleapis.com/maps/api/place/textsearch/
The above connects to the Google Maps API (maps.googleapis.com/maps/api) and establishes that we want to use the place API (/place) and the text search (/textsearch) component of the Places API.
https://maps.googleapis.com/maps/api/place/textsearch/output_type?
the output_type? defines how we want the output to be created. The options are json or xml, and you’ll simply replace output_type? with either json? or xml? depending on your choice.
https://maps.googleapis.com/maps/api/place/textsearch/output_type?query=your_query
The query parameter defines our “ambiguous” search term. We separate any words with a plus sign. So, to search for coffee shop, we’ll replace your_query with coffee+shop.
https://maps.googleapis.com/maps/api/place/textsearch/output_type?query=your_query&location=latitude,longitude
We separate parameters with the & symbol. We can define our desired location by providing a latitude and longitude coordinate. This will be the center point for the search. You could also put a location in your search term and skip the lat/lon, something like “coffee+shop+raleigh+nc”.
https://maps.googleapis.com/maps/api/place/textsearch/output_type?query=your_query&location=latitude,longitude&radius=number_of_meters
The radius parameters define how wide the search will occur. To search within 1,000 meters from the latitude and longitude coordinate, we can replace the number of meters with 1000 (don’t use a comma in the string). A higher radius will cover a wider area. That said, it’s also susceptible to missing locations.
Think about when you zoom out on a Google Maps search — you’ll get a wider range of locations but not as many actually pop up. Check out the images below — on the right-hand side, we have a wider Zoom radius for the search. We get more results, but some from the left-hand image don’t show up even though they’re still in the search area. Test a couple of different radiuses to see what works best for your use case. A smaller radius will give you more accurate results but also take longer to run and cost more as a result of making more calls to the API.
https://maps.googleapis.com/maps/api/place/textsearch/output_type?query=your_query&location=latitude,longitude&radius=number_of_meters&region=region_code
Region code is a 2-digit code for the country where you want to search. For example, working with a UK company I used the code uk, while in the United States, we could use the region code of us.
https://maps.googleapis.com/maps/api/place/textsearch/output_type?query=your_query&location=latitude,longitude&radius=number_of_meters&region=region_code&type=establishment_type
The type parameter allows us to specify the type of establishment as tagged in the Google data. For coffee shops, we can provide bakery and café as types to ensure that we don’t get results that aren’t relevant. The full list of types can be found here. We separate types with a comma and no space. For bakeries and cafe, the type parameter would be bakery,cafe.
https://maps.googleapis.com/maps/api/place/textsearch/output_type?query=your_query&location=latitude,longitude&radius=number_of_meters&region=region_code&type=establishment_type&key=YOUR_API_KEY
Last but not least is entering the API key. Use the API key created earlier in this parameter.
Bring it all together and you get something like this that was used for this project:
"https://maps.googleapis.com/maps/api/place/textsearch/json?query=coffee+shop&location=35.792491,-78.653009&radius=2000&region=us&type=cafe,bakery&key=MY_API_KEY"
Many of these are optional parameters that may or may not be relevant for your use, but the essence of the API is choosing your relevant parameters, entering the required value, and separating your parameters with the & symbol. All required and optional parameters can be found under the Text Search header of the documentation page.
Once we’ve constructed our URL string, we access and parse the information using a mix of basic coding and web scrapes. Below is how I approached it but there are likely more efficient ways to pull it. You’ll need the requests, json, and time packages.
In the code shortly below, I start by establishing an empty list to place the results and an empty dictionary for future parameters, then establish the URL we just created as its own variable.
I send a URL request using requests.get then, since I used a json output, use json.loads on the result to translate the URL output to a workable json output. I append the results to the empty list that I created then put in a brief pause before making the next call using time.sleep(2).
Each call to the API returns up to 20 results per page and up to 3 total pages for a total of 60 results. The time.sleep argument is required as the API will not return results if you try to just send all of your requests at once without a break.
The while loop recognizes when there are additional results in the call and makes the proper API call to also grab those by adding the next page token parameter to the empty dictionary.
import requestsimport jsonimport timecoffee_shops = []params = {}  endpoint_url = "https://maps.googleapis.com/maps/api/place/textsearch/json?query=coffee+shop&location=35.7790905,-78.642413&radius=2000&region=us&type=cafe,bakery&key=MY_API_KEY"         res = requests.get(endpoint_url, params = params)results =  json.loads(res.content)coffee_shops.extend(results['results'])time.sleep(2)while "next_page_token" in results:     params['pagetoken'] = results['next_page_token'],     res = requests.get(endpoint_url, params = params)     results = json.loads(res.content)     coffee_shops.extend(results['results'])     time.sleep(2)
The output is a list of dictionaries where each dictionary contains the information for a single coffee shop.
We can pull all kinds of information from this, including the address, latitude/longitude coordinates, business name, price level, rating, number of ratings, photos, and more. Depending on your use case you can use all or some of this data.
To extract the information in the dictionaries, I established an empty list for each of the fields that I wanted to extract, then wrote a simple for loop that accesses each shop (i.e. dictionary) by index and the relevant fields, then added that value to list. Finally, you can convert the output to a data frame. Since I was looping through several zip codes to do searches, I then appended that data frame to a master data frame and constructed a new column to filter out duplicates to only keep unique values.
Just like that, we have a clean, ready-to-use data frame with all of our data elements in a cleanly formatted table!
If you’re using R or another programming language, you’ll create the URL string the same then adjust the code to do a URL request, set up empty vectors as opposed to lists, and so forth.
I’ve only scratched the surface with how the output can be used and there are several exciting possibilities both for location analysis or other use cases.
One of the ways I used this in a separate project was using a geopandas spatial join to map the latitude/longitude coordinates to a custom output level then assessing competition within each of those bounded areas. We can also look at customer satisfaction, in addition to competitive density, using the weighted average rating within a geographic area.
A simple and powerful tool is to drop this data onto a Tableau map to see exactly where competitors are (and aren’t) located. This can be combined with a demographic analysis to prioritize which locations have the right demographics for your business to succeed, then see exactly where the competition is to avoid cannibalization or overlap.
The Places API is among the more expensive of the Google Maps API, but there’s ample work you can do with it before having to go out-of-pocket. When I signed up, there was a $300 credit that had to be used within 3 months. Google also provides a free $200 credit every single month. This doesn’t carry over, so you have up to $200 to use each month which then resets.
An approximate rule of thumb for the API is that it will cost about $40 for every 1,000 API requests. Remember, you can get up to 20 locations per request, so you can get up to 20,000 locations for $40. With the $200 monthly credit, this equates to about 5,000 free requests before you start paying.
Full pricing details are available here, but an example is below for the Text Search API. We cannot control which data points are returned; the Places, Basic Data, Contact Data, and Atmosphere Data are all returned for each API call.
One last note on pricing that I didn’t understand at first is that each time you submit a URL string to pull information, it can be up to 3 total requests. I mentioned above that each URL call provides up to 20 results across 3 pages. To access each additional page is a new request to the API. So, to get all 60 results will be considered 3 total requests to the API.
I’m excited by the possibilities unlocked by understanding how to access and work with the data from this API. Across my time using it I’ve found a couple pros and cons to where and how the data can be used.
The optimal use case is for a targeted search in a narrow geographic area. In dense places like a city with broad search terms like coffee shop, you need to get very narrow in your search radius, as low as 500 meters for best results. The way I’ve accounted for this is to get bounded lat/lon geographic areas, like a zip code, and write code to do a grid search across that location that iteratively executes the search at staggered lat/lon entries with a small search radius, then filters out duplicate results on the back end.
This approach is not always the best option for wide search areas as the number of requests to the API may be excessive/expensive and time consuming (remember, it’s a 2-second break after each call, so 1,000 calls to the API will take 2,000+ seconds/more than 30 minutes).
It’s best to start by using a handful of targeted search areas, testing the code and results (and understanding how pricing works), then expanding out to a broader geographic area.
Do you have other thoughts on how the data can be used? Interested in learning more or connecting? Reach out to me on LinkedIn or by email at jordan@jordanbean.com.