Why Local SERPs Are Different
Google delivers different search results based on where the searcher is located. A query for "best coffee shop" returns completely different results in New York, London, and Tokyo. This localization applies not just to local business queries but also to many commercial and informational keywords.
For businesses that serve specific geographic markets, tracking national-level rankings is misleading. A website might rank #1 in Chicago but #15 in Houston for the same keyword. Without location-specific SERP tracking, you are making SEO decisions based on incomplete data.
This article explains how to implement accurate local SERP tracking using geo-targeted residential proxies. For a broader overview of SERP monitoring, see our complete SERP scraping with proxies guide.
How Google Localizes Search Results
Google uses multiple signals to determine which local results to show:
| Signal | How It Works | Impact on Results |
|---|---|---|
| IP geolocation | Google maps the searcher's IP to a geographic location | Primary factor for local pack and organic results |
| GPS/device location | Mobile devices share precise coordinates | Very precise local results on mobile |
| Google account location | Location history from signed-in users | Personalizes results based on past locations |
| Search parameters | gl (country) and uule (exact location) URL parameters | Override IP-based detection |
| Language settings | hl parameter and Accept-Language header | Influences which language versions appear |
The Local Pack
For queries with local intent, Google displays a "local pack" — a map with three business listings above organic results. This pack captures a significant share of clicks and is entirely location-dependent. A business 2 miles away from the searcher may appear in the pack, while one 20 miles away will not.
Organic Result Variation
Even standard organic results shift by location. Google promotes locally relevant content, adjusts rankings based on regional search behavior, and may show different featured snippets depending on the searcher's city.
Why Geo Proxies Are Essential
To see search results as they appear to users in a specific city, you need an IP address from that city. This is where geo-targeted residential proxies become indispensable.
- Authentic location signal: A residential IP from Denver tells Google the searcher is actually in Denver
- Local pack accuracy: You can only see the correct local pack by querying from the right location
- Regional content differences: Content that ranks in one region may not rank in another
- Competitive analysis: See exactly what your local competitors see in their market
ProxyHat residential proxies support city-level geo-targeting across 190+ locations worldwide, making them ideal for local SERP monitoring.
Implementing Local SERP Tracking
Here is a complete Python implementation that tracks keyword rankings across multiple cities:
import requests
from bs4 import BeautifulSoup
import json
import time
import random
from datetime import date
# ProxyHat proxy with geo-targeting
# Append city/country to your session for geo-targeted requests
# See docs.proxyhat.com for geo-targeting syntax
PROXY_BASE = "http://USERNAME:PASSWORD@gate.proxyhat.com:8080"
LOCATIONS = [
{"city": "New York", "gl": "us", "hl": "en", "uule": "w+CAIQICIITmV3IFlvcms"},
{"city": "Los Angeles", "gl": "us", "hl": "en", "uule": "w+CAIQICILTG9zIEFuZ2VsZXM"},
{"city": "Chicago", "gl": "us", "hl": "en", "uule": "w+CAIQICIHQ2hpY2Fnbw"},
{"city": "London", "gl": "uk", "hl": "en", "uule": "w+CAIQICIGTG9uZG9u"},
{"city": "Berlin", "gl": "de", "hl": "de", "uule": "w+CAIQICIGQmVybGlu"},
]
def track_local_ranking(keyword, domain, location):
"""Track keyword ranking from a specific location."""
proxies = {"http": PROXY_BASE, "https": PROXY_BASE}
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
"Accept-Language": f"{location['hl']};q=0.9,en;q=0.8",
}
params = {
"q": keyword,
"num": 20,
"hl": location["hl"],
"gl": location["gl"],
"pws": 0,
}
# Add UULE parameter for precise city targeting
if "uule" in location:
params["uule"] = location["uule"]
response = requests.get(
"https://www.google.com/search",
params=params,
headers=headers,
proxies=proxies,
timeout=15,
)
response.raise_for_status()
soup = BeautifulSoup(response.text, "html.parser")
# Find organic position
position = None
for i, g in enumerate(soup.select("div#search .g"), 1):
link = g.select_one("a")
if link and domain in link.get("href", ""):
position = i
break
# Check local pack presence
in_local_pack = False
local_pack = soup.select("div.VkpGBb")
for item in local_pack:
if domain in item.get_text().lower():
in_local_pack = True
break
return {
"keyword": keyword,
"city": location["city"],
"position": position,
"in_local_pack": in_local_pack,
"date": str(date.today()),
}
# Track across all locations
keywords = ["best proxy service", "web scraping tools", "seo software"]
all_results = []
for kw in keywords:
for loc in LOCATIONS:
result = track_local_ranking(kw, "proxyhat.com", loc)
all_results.append(result)
city = result["city"]
pos = result["position"] or "Not ranked"
local = " (in local pack)" if result["in_local_pack"] else ""
print(f" {city}: #{pos}{local}")
time.sleep(random.uniform(3, 6))
# Save results
with open(f"local_rankings_{date.today()}.json", "w") as f:
json.dump(all_results, f, indent=2)
Understanding the UULE Parameter
The uule parameter is the most precise way to specify location in Google search URLs. It encodes a geographic location that Google uses instead of IP-based geolocation.
How to Generate UULE Values
UULE values are Base64-encoded strings with a specific format. Here is a utility function to generate them:
import base64
def generate_uule(location_name):
"""Generate a UULE parameter for Google geo-targeting."""
# UULE format: w+CAIQICI{length_char}{base64_location}
encoded = base64.b64encode(location_name.encode()).decode()
# Length character mapping (A=1, B=2, ... Z=26, a=27, etc.)
length = len(location_name)
if length <= 26:
length_char = chr(64 + length) # A=1, B=2, ...
else:
length_char = chr(70 + length) # Adjusted for longer names
return f"w+CAIQICI{length_char}{encoded}"
# Examples
print(generate_uule("New York")) # For New York City
print(generate_uule("Los Angeles")) # For Los Angeles
print(generate_uule("London")) # For London
Combining UULE with Geo Proxies
For maximum accuracy, use both UULE parameters and geo-targeted proxies from the same location. The UULE tells Google where to localize results, while the proxy IP confirms the geographic signal. This double approach produces the most reliable local SERP data.
Use Cases for Local SERP Tracking
Multi-Location Businesses
Franchises, retail chains, and service-area businesses need to track rankings in every city they serve. A pizza chain with 50 locations needs to know their ranking in each market, not just nationally. Local SERP tracking reveals which locations have strong SEO and which need attention.
Local SEO Agencies
SEO agencies managing clients across different cities must report on local rankings accurately. Showing a client their national ranking when they serve a local market erodes trust. Geo-proxy-based tracking provides the precise data clients need.
Competitor Monitoring
Local competitors may rank differently in different neighborhoods. By tracking competitors across multiple locations within a metro area, you can identify geographic gaps in their coverage and target those areas with optimized content.
International SEO
Websites targeting multiple countries need to verify their rankings in each market. Language, currency, and cultural differences all affect which content Google promotes in each locale. Use geo-targeted proxies from each target country to get accurate international SERP data.
Node.js Implementation
const axios = require('axios');
const cheerio = require('cheerio');
const { HttpsProxyAgent } = require('https-proxy-agent');
const agent = new HttpsProxyAgent('http://USERNAME:PASSWORD@gate.proxyhat.com:8080');
const LOCATIONS = [
{ city: 'New York', gl: 'us', hl: 'en', uule: 'w+CAIQICIITmV3IFlvcms' },
{ city: 'London', gl: 'uk', hl: 'en', uule: 'w+CAIQICIGTG9uZG9u' },
{ city: 'Berlin', gl: 'de', hl: 'de', uule: 'w+CAIQICIGQmVybGlu' },
];
async function trackLocal(keyword, domain, location) {
const params = {
q: keyword,
num: 20,
hl: location.hl,
gl: location.gl,
pws: 0,
};
if (location.uule) params.uule = location.uule;
const { data } = await axios.get('https://www.google.com/search', {
params,
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Accept-Language': `${location.hl};q=0.9,en;q=0.8`,
},
httpsAgent: agent,
timeout: 15000,
});
const $ = cheerio.load(data);
let position = null;
$('div#search .g').each((i, el) => {
const href = $(el).find('a').attr('href') || '';
if (href.includes(domain) && !position) {
position = i + 1;
}
});
return { keyword, city: location.city, position };
}
// Track keyword across all locations
async function trackAcrossLocations(keyword, domain) {
const results = [];
for (const loc of LOCATIONS) {
const result = await trackLocal(keyword, domain, loc);
results.push(result);
console.log(`${loc.city}: #${result.position || 'not found'}`);
await new Promise(r => setTimeout(r, 3000 + Math.random() * 3000));
}
return results;
}
trackAcrossLocations('best residential proxies', 'proxyhat.com');
Best Practices for Local SERP Tracking
Choose the Right Location Granularity
- Country level: Use for broad international campaigns. Set
glparameter only - City level: Required for local businesses. Use both
glanduulewith city-level proxy - Neighborhood level: For hyper-local businesses (restaurants, stores). Use very precise UULE coordinates
Track Mobile and Desktop Separately
Local results differ significantly between mobile and desktop. Mobile SERPs show more prominent local packs and different organic rankings. Track both by switching User-Agent strings between mobile and desktop configurations.
Monitor Local Pack Separately
The local pack is a distinct ranking from organic results. Track whether your business appears in the local 3-pack for each location independently of organic position. Many businesses rank well organically but are absent from the local pack, or vice versa.
Schedule Consistently
Run local tracking at the same time each day. Search results fluctuate throughout the day, and inconsistent scheduling introduces noise into your data. Morning tracking (6-8 AM in each target timezone) tends to produce the most stable baseline.
Local SERP tracking without geo-targeted proxies is inherently inaccurate. Invest in residential proxies with city-level targeting to get data that reflects what your actual customers see.
For more details on proxy-based SERP monitoring, read our articles on best proxies for web scraping and how to scrape without getting blocked. Visit the ProxyHat documentation for geo-targeting configuration.






