The UULE Parameter: How Google Location Targeting Actually Works

By Serpent API Team · · 9 min read

The uule parameter is a URL parameter Google Search accepts to set the searcher's location for a single query. Its value is a base64-encoded protocol buffer: the w+ form carries a canonical place name from Google's Ads geotargets list, while the a+ form carries raw latitude/longitude with a radius. It is how location-aware rank checks simulate searching from a specific place without being there.

Plenty of articles mention uule; very few explain what is actually inside it, and at least one example string that gets copied from guide to guide is subtly malformed. This is the technical reference: both variants decoded byte by byte, working Python you can paste (we ran it — outputs shown), and an honest note on what a uule can and cannot fix. If what you actually need is local-pack strategy, that lives in our geo-grid local rank tracking guide and the local rank tracking API page — this post is the encoding layer underneath them.

Where uule sits among Google's location signals

Google Search takes several location-related inputs, and they do different jobs. Mixing them up is the most common reason a “localized” check silently isn't.

ParameterWhat it doesGranularity
glCountry of the search marketCountry
hlInterface languageLanguage
uuleSets the searcher's location for this queryCity / coordinates
IP addressDefault location signal when nothing else is setWhatever the IP resolves to

A uule doesn't replace gl and hl — location-testing guides pair all three (?q=pizza+delivery&uule=w+CAI…&gl=US&hl=en) so the market, language, and searcher location all agree. And because results still vary by time and personalization even with identical parameters, treat any single check as a sample, not the truth — that problem is why your rank tracker and Search Console never quite agree.

The w+ variant: a canonical name in a protobuf envelope

Strip the w+ prefix and base64-decode the rest and you get a small protocol buffer, as documented in valentin.app's teardown: field 1 is a role identifier (value 2), field 2 is a producer enum (value 32, which the teardown identifies as AdWords), and field 4 is the canonical place name as a length-prefixed string. That's the whole payload — five fixed header bytes, one length byte, then the name:

08 02        field 1, varint = 2      (role)
10 20        field 2, varint = 32     (producer: AdWords)
22 <len>     field 4, length-delimited string
<name>       the canonical name, UTF-8

Because the first five bytes never change, every w+ uule starts with the same seven base64 characters: CAIQICI. The next character encodes the top bits of the length byte — which is why older guides talk about a “secret key” lookup table indexed by name length. There's no secret: it's just the protobuf length prefix landing inside base64.

Where canonical names come from

The name inside a w+ uule is not free text. It must exactly match a canonical name from Google's geo targets list, published in the Google Ads API documentation as a downloadable CSV. Each row carries a Criteria ID, a name, a canonical name in City,Region,Country form, and a target type. New York,New York,United States is valid; NYC is not. When a location check mysteriously returns un-localized results, a misspelled or non-canonical name is the first thing to rule out.

Generate a w+ uule in Python (tested)

Here is a complete generator and decoder. We ran exactly this code before publishing; the output below is real, not typed from memory.

import base64

def make_uule(canonical_name: str) -> str:
    """Build a w+ uule from a Google Ads canonical location name."""
    name = canonical_name.encode("utf-8")
    if len(name) > 127:
        raise ValueError("names longer than 127 bytes need multi-byte varint handling")
    payload = b"\x08\x02\x10\x20\x22" + bytes([len(name)]) + name
    return "w+" + base64.urlsafe_b64encode(payload).decode("ascii").rstrip("=")

def decode_uule(uule: str) -> str:
    """Recover the canonical name from a w+ uule."""
    b64 = uule[2:] if uule.startswith("w+") else uule
    b64 += "=" * (-len(b64) % 4)
    raw = base64.urlsafe_b64decode(b64)
    assert raw[:5] == b"\x08\x02\x10\x20\x22", "unexpected protobuf header"
    n = raw[5]
    return raw[6:6 + n].decode("utf-8")

uule = make_uule("New York,New York,United States")
print(uule)
print(decode_uule(uule))

Output from our run (Python 3, July 17, 2026):

w+CAIQICIfTmV3IFlvcmssTmV3IFlvcmssVW5pdGVkIFN0YXRlcw
New York,New York,United States

The round-trip is the point: generate, decode, and confirm you get the exact canonical name back. The single length byte covers names up to 127 UTF-8 bytes; beyond that, protobuf switches to a multi-byte varint, which the code above deliberately refuses rather than silently mis-encoding — no canonical city name we've seen comes close to that limit.

The malformed example that guides keep copying

While testing, we decoded a w+ example string that circulates through several location-testing guides: w+CAIQICIdQXVzdGluLFRleGFzLFVuaXRlZCBTdGF0ZXM, presented as “Austin,Texas,United States”. Its header decodes to 08 02 10 20 22 1d — a declared length of 29 bytes — but the name that follows is only 26 bytes long. A strict protobuf parser reads three bytes past the string's end. The correctly encoded form, from the code above, is w+CAIQICIaQXVzdGluLFRleGFzLFVuaXRlZCBTdGF0ZXM (length byte 1a = 26). Google's parser appears tolerant of the malformed version, but if your uule “works sometimes,” a wrong length byte from a copied lookup table is worth ruling out — generate, then verify by decoding, and you never inherit someone else's off-by-three.

Why your uule isn't working: the four usual suspects

When a localized check comes back looking suspiciously un-local, the failure is almost always one of four mechanical issues — and each has a distinct symptom:

SymptomLikely causeFix
Results ignore the location entirelyThe name isn't a canonical name (“NYC”, a typo, wrong comma format)Look the place up in the geotargets CSV and copy the canonical name exactly
Location works in the browser but not from codeThe + after w was mangled in transit — in a query string a literal + decodes as a space, and some HTTP libraries encode it as %2B while others don'tLog the exact final URL your client sends and confirm what arrives after decoding is still w+CAIQICI…
Location applies but market/language look wronguule sent without gl/hl, so the market defaults from other signalsAlways pair uule with explicit gl and hl
Works intermittently across toolsA malformed encoding (wrong length byte) copied from a guideGenerate with the code above, then verify with decode_uule() round-trip

The decoder doubles as an audit tool for uule strings you find in the wild: paste any w+ value into decode_uule() and it either returns the exact canonical name or fails loudly on a bad header or length — which is precisely how we caught the malformed example above.

The a+ variant: coordinates, timestamp, radius

The second form starts with a+ and, per the same public teardown, contains readable key-value text after decoding: role, producer, and provenance fields, a timestamp in microseconds since the epoch, latitude and longitude as latlng e7 integers (degrees × 10,000,000), and a radius value. Location-testing guides reach for a+ when they need a precise point — a neighborhood or an exact address — rather than a city centroid. The exact semantics of every a+ field (the radius unit conversion, for one) are not publicly documented by Google; treat third-party descriptions of those details as reverse-engineered observations, not a spec.

What a uule cannot fix

A uule sets where Google thinks the searcher is standing — it does not make local results uniform across a city. Local-pack ordering is heavily proximity-driven, so one city-centroid check can disagree with what a searcher sees three miles away, which is why serious local work samples a grid of points rather than a single uule. That methodology — grid spacing, share-of-local-voice math, and what to do when your data source is country-level — is covered in the geo-grid guide and the broader local SEO rank tracking post; this article stops at the encoding.

uule and SERP APIs: what to check before you build

SERP APIs abstract location differently, and the abstraction determines what tracking you can honestly build. Some accept a raw uule or coordinates per request; others take a location name and build the uule for you; others localize at market level only. Serpent API is in the third group, by design: results are localized by a two-letter country code (112 supported countries) plus a language parameter — there is no uule, latitude/longitude, or street-level input. That's the right shape for country-by-country rank tracking and market-level SERP monitoring at low per-call cost, and the wrong shape for per-coordinate local grids — where a coordinate-accepting tool is the honest recommendation. The full parameter reference is in the API docs, and the SERP API overview shows what each endpoint returns.

Whichever tool you use, the checklist is the same: confirm what location input it accepts (uule, coordinates, name, or country), confirm what the parameter actually controls (searcher location vs. market vs. language), and verify with a decode — or a known-answer query — that the location you asked for is the one being applied.

Track rankings across 112 countries

Serpent API returns localized Google, Bing, Yahoo and DuckDuckGo results by country code — flat per-call pricing, up to 10 pages per call, credits that never expire. Start free — 10 searches, no card required.

Start Free — 10 Searches, No Card

Explore: SERP API · Rank Tracking API · Local Rank Tracking

FAQ

What is the uule parameter in Google Search?

A URL parameter that sets the searcher's location for one query. Its value is a base64-encoded protocol buffer: w+ carries a canonical place name from Google's geotargets list; a+ carries latitude/longitude with a timestamp and radius.

Where do the canonical names come from?

Google's geo targets CSV, published in the Google Ads API documentation. The string must match a canonical name exactly — New York,New York,United States, not NYC.

What's the difference between w+ and a+?

w+ encodes a named place from the geotargets list; a+ encodes precise coordinates (documented by third-party teardowns as e7 integers) with a radius. w+ is more widely used and better documented.

Does a uule guarantee accurate local pack results?

No. It sets the location signal, but local packs are proximity-driven, so one city-centroid check can differ from what searchers see across town. Grid-based sampling is the standard answer.

Can I pass a uule to the Serpent API?

No — Serpent API localizes by two-letter country code (112 countries) plus language, with no uule or coordinate input. It's built for country-level tracking; for per-coordinate grids, use a coordinate-accepting tool.

References

Related Posts