Published · Updated
Your Proxy's Location Is Not Your Search Location
Say you need to know how a page ranks in Paris, so you route the request through a residential proxy with a French exit IP. The response comes back in French, with .fr domains near the top and French brands in the results. It looks exactly like what you expected, so nobody checks it again.
But you're not seeing what a Paris searcher sees. You're seeing what Google shows a request it believes came from somewhere in France, which is a much weaker statement. For a large class of queries, it's also a materially different page.
Geography in Google search is made of four independent layers, and most scrapers control only one of them.
The Google Search API guide shows how these controls fit into a programmatic request, while the broader SERP API overview covers the normalized response, pagination, and request history around it.
Layer 1: the proxy exit IP is only a hint
Google infers an approximate location from the request's IP address, but treats it as one signal among several. Explicit location signals in the request override it.
There's also a more basic problem: IP geolocation is unreliable below the country level. Residential proxy pools inherit whatever the geolocation databases claim about each address, and those claims are frequently stale or wrong at city granularity. An address advertised as Lyon may resolve to Paris, or to nothing more specific than "France." Country-level accuracy is generally solid. City-level accuracy, which is what rank tracking needs, is something an IP alone can't reliably give you. Keep that in mind when planning a proxy strategy. Proxies are good at IP reputation and spreading requests out, and our guide to rotating proxies covers those strengths in more detail.
Layer 2: the gl country parameter boosts results
The gl parameter sets the result country. It's common to assume gl=fr means "give me only French results." In fact, results matching that country get boosted in ranking, and nothing is filtered out.
That distinction has real consequences for anyone comparing numbers. A domain that's absent from your gl=fr check can still appear for actual French searchers, and international domains you didn't expect will still show up in a country-targeted request because they were only down-weighted. If you're treating gl as a filter and reporting the result as "rankings in France," you're reporting something narrower than what you measured.
Layer 3: the hl language parameter does two jobs
hl sets the interface language. It also influences which results get selected for international queries, and that second job makes it look like a geography control.
Language and country are separate questions. A French speaker in Montreal and a French speaker in Paris get meaningfully different results for the same query in the same language. Setting hl=fr and calling it French targeting mixes up two decisions that should be made separately. If you only set hl, you've specified the language while leaving the geography to be decided by whatever your infrastructure happened to do.
Layer 4: UULE, the city-level location control
The signal that actually moves Google's location resolution at city granularity is UULE, a Base64-encoded location value that overrides the IP-inferred location. It's the layer that changes the local pack. It's also undocumented. It has been stable for roughly a decade, which is why every SERP tool depends on it, but Google has never committed to it, and a change to their pipeline could deprecate it without notice.
This is the layer most homegrown scrapers skip entirely, because it isn't discoverable from Google's own documentation. It also matters most for the local queries that rank trackers are usually built to watch.
Test location targeting with local queries
The mistake survives because broad informational queries barely move between cities in the same country. You can have your location stack completely misconfigured and get results that look right, because for best project management software there's very little for the geography to change.
Queries with local intent (services, retail, restaurants, anything phrased as "near me") change a lot between cities. The local results block is driven almost entirely by the resolved location, and shopping results shift with it too. If you want to know whether your location targeting actually works, test it with a query that has local intent. A broad informational query can't tell you, which is why the setup at the top of this post can go unnoticed for so long.
Wrong location targeting fails silently
When you get blocked, you see a 403, a CAPTCHA, or an empty page, which you can alert on (our guide to avoiding blocks covers that problem).
Wrong location targeting gives you no such signal. You get a 200 and a full page of entirely plausible results. Run the same query under three different location configurations and you get three different answers, all successful, with nothing in any response indicating which one corresponds to what a real searcher sees. The discrepancy typically surfaces months later, when someone compares your rank report against what they see on their own phone.
This also undermines historical data. A rank number recorded last quarter means nothing unless you also recorded every layer that produced it. If any layer was inherited from infrastructure rather than set explicitly (the proxy pool's exit region, a default country, a datacenter's location), it may have changed since, and you have no way to tell whether a movement in the chart is a ranking change or a targeting change.
Pin every layer explicitly
Any layer you don't set is being set for you by your proxy pool, your datacenter region, or somebody's default. Set all four explicitly.
// The same query asking three different questions
{ "query": "coffee roasters", "gl": "fr", "hl": "fr" }
{ "query": "coffee roasters", "gl": "fr", "hl": "fr",
"location": "Paris,Ile-de-France,France" }
{ "query": "coffee roasters", "gl": "fr", "hl": "fr",
"coordinates": { "latitude": 48.8566, "longitude": 2.3522 } }
The first asks for country-weighted results with a French interface and no city resolution. The second resolves to a specific city. The third resolves to a point. All three succeed and return different local results, so pick one deliberately and record it alongside the data.
In practice, decide language and country separately, use a stable location identifier rather than a hand-encoded blob, store the full parameter set with each result so a historical number can be re-derived, and keep the choice consistent for as long as you intend to compare numbers over time.
How PrismCrawl handles the location stack
PrismCrawl exposes these as explicit parameters on the Google search endpoint rather than leaving them to infrastructure:
locationtakes an Active Canonical Name such as"Austin,Texas,United States"from a pinned Google geo-target dataset, currently version2026-07-16. Pinning matters for the reproducibility problem above: the identifier you stored last quarter still refers to the same place, which isn't guaranteed when you're encoding location values by hand.coordinatestakes a latitude and longitude for point precision. It's mutually exclusive withlocation, so you choose one or the other.uuleaccepts a raw Google-encoded location (w+...ora+...) and forwards it unchanged, for teams that already store UULE values from an existing pipeline. It's mutually exclusive withlocation,coordinates, andradius. PrismCrawl checks only that the value is structurally valid, so Google may still ignore a payload it doesn't recognize. Preferlocationfor anything new; the pinned dataset is what makes it reproducible.glcovers over 250 country codes andhlcovers more than 70 interface languages, kept as the separate decisions they are.pwscontrols Google's personalization flag:0requests personalization off,1permits it, and omitting it leaves Google's default unchanged. It doesn't disable any of the location layers above. It just removes one more setting you'd otherwise inherit.search_parametersechoes every parameter back on the response, nulled where you didn't set one. The record of what you asked travels with the answer, so a stored result stays interpretable later.
One scoping note: the engines don't have matching controls. The Bing endpoint uses cc and setlang for country and language, and it accepts coordinates, which PrismCrawl sends to Bing as a client-location signal. Bing treats that as a relevance bias rather than a strict geographic filter, and it has no location or uule equivalent. Don't assume parity across engines when you're building comparisons.
Updated September 25, 2026: added the uule and pws parameters, and Bing's coordinates support.
If you're building geo-sensitive tracking, test it against real data before committing. The free tier is 100 credits with no credit card, which is enough to run the same query under several location configurations and compare the answers. Full parameter details are in the API reference, and there's more on the surrounding architecture in our SEO rank tracker guide.
Frequently asked questions
Does a residential proxy in a city give me that city's search results?
Not reliably. Google treats the exit IP as one location signal among several, and it can be overridden by explicit signals in the request. IP geolocation is also frequently wrong below the country level, so a proxy advertised as being in one city often resolves somewhere else entirely. You get roughly country-level accuracy, not the city-level targeting most rank tracking assumes.
What is the difference between gl and hl?
gl is a result-country signal and hl is an interface-language signal. gl boosts results matching that country rather than strictly filtering to it, so you still see results from elsewhere, just re-weighted. hl sets the language of the interface and also influences which results get selected for international queries. They are independent: French-language results and results targeted at France are not the same set.
Do I need city-level location targeting, or is country enough?
It depends entirely on the query's intent. Broad informational queries barely move between cities in the same country, so country-level targeting is usually fine. Anything with local intent — services, retail, "near me" phrasing — swings hard between cities, and the local pack in particular is driven almost entirely by the resolved location. If you are tracking those, country-level targeting will produce plausible-looking results that do not match what a real searcher sees.