Google search results by city: how much the location parameter changes them
We ran 13 searches in 4 cities with location set. Local searches shared 0.2 links between cities, others 6.3. The local pack stayed stable on repeats.
CrawlerData teamPublished 6 min read
Contents
Local SEO runs on one fact: the results someone sees depend on where they are. If you track rankings for a business, or sell to businesses that do, “where” has to be part of every check.
We measured how much a city changes Google’s search results. We ran 13 searches in four cities with the location parameter set, and compared the cities with each other, with a no-location baseline and with repeat runs of the same city. This guide has the numbers, a function that does the comparison, and what it means for tracking. We used the Google Search API in October 2026. Results change, so yours will differ.
How we ran it
We used 13 searches, each in us with location set to one of Austin,Texas,United States, Brooklyn,New York,United States, Denver,Colorado,United States and Miami,Florida,United States, plus one run with no location:
- 10 local searches: plumber, best pizza, coffee shop, dentist, gym, personal injury lawyer, car repair, hair salon, apartments for rent, wedding photographer.
- 3 non-local controls: how to tie a tie, what is inflation, python tutorial.
That is 65 searches. We compared every pair of cities, and each city with the no-location run. It is a small set we chose, so the numbers describe it and nothing wider.
Local searches: the cities hardly overlap
For the 10 local searches, a result page held about 8.4 organic results. Across the 60 pairs of cities:
- Two cities shared 0.22 organic links on average. For 7 of the 10 searches they shared none at all.
- They shared 2.6 domains on average, so the same sites appeared with different pages.
- The first result was the same in 0 of 60 pairs.
- A city compared with no location at all shared 0.38 links, so setting a location moved the results about as much as the difference between two cities does.
- All 40 city requests returned a local pack.
The per-search picture:
| Search | Organic links shared between two cities (average) | Local pack in 4 cities |
|---|---|---|
| plumber | 1.0 | 4 of 4 |
| coffee shop | 1.0 | 4 of 4 |
| personal injury lawyer | 0.2 | 4 of 4 |
| best pizza, dentist, gym, car repair, hair salon, apartments for rent, wedding photographer | 0.0 | 4 of 4 |
The local packs named businesses in each city. For plumber, the first three were:
austin We Plumb LLC, Chase LLC, Magic Plumbing ATX
brooklyn Brooklyn Plumber, NONSTOP PLUMBERS CORP, Joe The Plumber - Plumbing & Heating
denver Brown Brothers Plumbing and HVAC, B.C. Plumbing Services, Cap Hill Plumbing
miami Mr. Clog Plumbing, Main Plumbing Services, Miami 24/7 Plumbing - Miami Emergency Plumbers
And for dentist, the Miami ones were Dental World of Miami and Dentists in Brickell, and the Denver ones were several Comfort Dental branches.
Non-local searches: location barely matters
For the 3 control searches, the cities were nearly the same:
| Measure | 10 local searches | 3 non-local searches |
|---|---|---|
| Organic links shared between two cities | 0.22 | 6.28 of about 7 |
| Same first result in two cities | 0 of 60 pairs | 13 of 18 pairs |
| Local pack present | 40 of 40 | 0 of 12 |
So the effect is specific to searches with local intent. A location did not hurt the informational ones, it just changed little, so there is no reason to set it for them.
The local pack is stable; the organic list is not
A city comparison is only meaningful if one city gives the same answer twice. We repeated 8 checks, 4 searches in Austin and Brooklyn, and compared each with its first run:
| Search | Austin: organic links shared across two runs | Brooklyn: organic links shared across two runs | Local pack names shared |
|---|---|---|---|
| plumber | 6 of 8 | 0 of 8 | 3 of 3, both cities |
| dentist | 9 of 9 | 0 of 9 | 3 of 3, both cities |
| gym | 7 of 8 | 0 of 8 | 3 of 3, both cities |
| hair salon | 8 of 8 | 8 of 9 | 3 of 3, both cities |
Two things stand out. The local pack was identical in all 8 repeats, the same three businesses every time. The organic results were not: Austin repeats mostly matched, but Brooklyn’s organic links shared nothing across two runs for three of the four searches. We do not know why. Whatever the cause, it means a single organic check of a local search is a poor measurement.
For tracking local rankings, that suggests:
- Prefer the local pack or the Google Local API for businesses. It was the stable part of the page.
- Repeat organic checks and read a trend over days, as in rank tracking.
- Store the location with every rank, the way you store the device and the country.
The code
Put your key in an environment variable:
export CRAWLERDATA_API_KEY="YOUR_API_KEY"
import os
import time
from concurrent.futures import ThreadPoolExecutor
import requests
API_URL = "https://api.crawlerdata.com/v1/jobs"
HEADERS = {"Authorization": f"Bearer {os.environ['CRAWLERDATA_API_KEY']}"}
CITIES = {
"austin": "Austin,Texas,United States",
"brooklyn": "Brooklyn,New York,United States",
"denver": "Denver,Colorado,United States",
"miami": "Miami,Florida,United States",
}
def google_search(query, country="us", location=None, retries=4):
params = {"query": query, "country": country}
if location:
params["location"] = location
body = {"endpoint": "google-search", "params": params, "queue": "live"}
for attempt in range(retries):
resp = requests.post(API_URL, json=body, headers=HEADERS, timeout=180)
if resp.status_code == 429:
time.sleep(int(resp.headers.get("retry-after", 10)))
continue
resp.raise_for_status()
job = resp.json()["job"]
if job["status"] == "completed":
return resp.json()["result"]
if "retry" in (job["error"] or "").lower(): # "service is busy" and "temporarily blocked" both say retry
time.sleep(5 * (attempt + 1))
continue
raise RuntimeError(job["error"])
raise RuntimeError("Search failed after retries")
def compare_cities(query, cities=CITIES, workers=3):
"""Run one search per city with location set. Returns per-city organic links and local pack names."""
with ThreadPoolExecutor(workers) as pool:
results = dict(zip(cities, pool.map(lambda loc: google_search(query, location=loc), cities.values())))
return {
city: {
"organic": [o["link"] for o in r["organic_results"]],
"local_pack": [x["title"] for x in r["local_pack"]],
}
for city, r in results.items()
}
def shared_links(report):
"""How many organic links each pair of cities has in common."""
names = list(report)
return {
f"{a}/{b}": len(set(report[a]["organic"]) & set(report[b]["organic"]))
for i, a in enumerate(names)
for b in names[i + 1:]
}
For plumber it printed:
austin | organic results: 8 | local pack: ['We Plumb LLC', 'Chase LLC', 'Magic Plumbing ATX']
brooklyn | organic results: 9 | local pack: ['Brooklyn Plumber', 'NONSTOP PLUMBERS CORP', "Joe The Plumber - Plumbing & Heating"]
denver | organic results: 8 | local pack: ['Brown Brothers Plumbing and HVAC', 'B.C. Plumbing Services', 'Cap Hill Plumbing']
miami | organic results: 7 | local pack: ['Mr. Clog Plumbing', 'Main Plumbing Services', 'Miami 24/7 Plumbing - Miami Emergency Plumbers']
shared organic links per pair: {'austin/brooklyn': 1, 'austin/denver': 1, 'austin/miami': 1, 'brooklyn/denver': 1, 'brooklyn/miami': 1, 'denver/miami': 1}
The location names must be Google’s own. Look them up with the public endpoint, which needs no key, for example GET https://api.crawlerdata.com/public/locations?q=austin. A name that is not valid is rejected with a 400. For the other side of the question, see Google results by country, and for news, local news by city, where location behaves very differently.
What it costs
Every request is 1 credit, on every queue. Starter is $1.00 per 1,000 requests and the largest pack is $0.30 per 1,000, see pricing.
| What you run | Requests | At $1.00 per 1,000 | At $0.30 per 1,000 |
|---|---|---|---|
| One search in 4 cities | 4 | $0.004 | $0.0012 |
| 50 local keywords in 10 cities, daily for a month | 15,000 | $15.00 | $4.50 |
| The same, with 3 repeats a day | 45,000 | $45.00 | $13.50 |
Failed requests are not charged. The tests behind this guide used about 77 credits.
Check one city for free
To see one search as a person in a given city sees it, our free Google results by city checker runs without an account.
Next steps
You now have numbers on how far a city changes Google’s results, a function that compares cities for any search, and a clear rule: local-intent searches need a location, the local pack is the stable part, and organic local results need repeating. Local rank tracking puts this into a tracker for individual businesses, and the Google Search API page lists every parameter with a full example response.
Frequently asked questions
- How much do Google results change by city?
- For searches with local intent, almost completely. In our October 2026 test of 10 local searches in Austin, Brooklyn, Denver and Miami, two cities shared on average 0.22 organic links out of about 8, and never had the same first result. For 3 non-local searches the cities shared 6.3 of about 7 links and had the same first result in 13 of 18 comparisons.
- How do I get Google results for a specific city?
- Add the location parameter to a google-search or google-local request, using a Google location name such as Austin,Texas,United States. Look names up with the public GET /public/locations?q=austin endpoint, which needs no key. It costs the same 1 credit.
- Does the local pack show up when I set a location?
- Yes. All 40 city requests for the 10 local searches returned a local pack, and none of the 12 city requests for the non-local searches did. The business names followed the city, for example Brooklyn Plumber, Miami 24/7 Plumbing and Austin Emergency Dentist.
- Are the results the same if I check twice?
- The local pack was. In 8 repeat checks, all 3 local pack names matched every time. The organic results were less stable: Austin repeats shared 6 to 9 of 8 or 9 links, but three of the four Brooklyn repeats shared none. Track local rankings from the local pack or the google-local endpoint, and repeat organic checks.
- Should I set a location for every search?
- No. For informational searches such as how to tie a tie, what is inflation or python tutorial, the cities shared most of their results, so a location changes little. Use it for searches where someone wants a business or a place nearby.
- How much does a city comparison cost?
- 1 credit per city per search. Comparing 4 cities for one search is 4 credits. Our 65 searches cost 65 credits, $0.065 at the Starter rate of $1.00 per 1,000 requests, and the repeat and code tests added about 12.
- Google results by city
- Local SEO
- Location parameter
- Rank tracking
- Local pack
- Python
- Data