Geo Consistency in Automation: IP, Timezone and Locale
Published · Updated
A ticket we see often from automation teams reads something like this: the line is in one city, but the script's IP lookup prints a different one, or only a state. The worry is that the bot will look out of place. The answer has two halves. The first is about networks: why a carrier address resolves where it does, and why that is not a defect. The second is about your code: an automated browser reports location through timezone, locale, the geolocation API and WebRTC as well as the address, and those values are yours to set. Getting both halves right gives you sessions that tell one consistent story, run after run.
How a lookup decides what city to print
Nothing in an IP header says where a device is. Geolocation vendors, ipinfo, DB-IP, MaxMind GeoIP2, IP2Location and several others, maintain tables that map address blocks to places. They fill those tables from operator registration records, BGP routing, geofeed files that networks publish following RFC 8805, latency probing, and location hints collected from apps. Your script's lookup call is simply reading one of those tables.
Different vendors weigh that evidence differently and refresh on different cycles, so two calls to two services can legitimately return two answers for the same address.
Where a modem's traffic really surfaces
The modem behind your port talks radio to towers in the city you picked. From there its packets are carried across the operator's backbone to an egress gateway serving a wider region, translated through carrier-grade NAT together with traffic from many everyday phones, and released onto the internet with an address from that gateway's pool. The lookup tables locate the pool. Hence the typical mobile result: a metro or a state, sometimes to a neighbouring hub, and never to a street, block or zip code.
It also explains a detail that surprises people: in smaller markets an operator may treat several states as one pool, and after a rotation your worker may be handed an address some vendor lists under a nearby state.
Same shelf, different answers by carrier
Each operator designs its own backbone. At our Boston site, lines on Verizon look up as Boston, while AT&T lines in the same rack come back as New York; AT&T sends much of its regional traffic through larger central hubs. Real AT&T phones in Boston carry that New York reading too, and they keep using Instagram and TikTok without complaint.
For automation the takeaway is that platforms are relaxed about a mobile address moving within one carrier's footprint, much like a phone that travels. The pattern they catch is a single identity active from two separate places at once, for example the same account driven by two workers on two lines simultaneously.
Making the browser agree with the address
Once a session has its address, the browser should report a matching location everywhere a page can look. These are the settings that matter most in Playwright, Puppeteer and Selenium:
- Timezone: set timezoneId in the Playwright context, or call emulateTimezone in Puppeteer, to the zone of the resolved city, not the zone of your server
- Locale and Accept-Language: use a US English locale for US lines so headers and navigator.language match
- Geolocation API: this reports the device's GPS or Wi-Fi position and is unrelated to the IP; either deny the permission or supply coordinates near the resolved city
- WebRTC: block or proxy it so the host machine's own address never appears next to the proxy's
- Antidetect profiles: GoLogin and Undetectable.io can derive timezone and geolocation from the proxy automatically, which removes a whole class of bugs from your code
Resolving location at session start
Rather than hard-coding a city per line, have the worker discover it. At startup, call two or three lookup services through the proxy, ipinfo.io is a dependable one and browserleaks.com/ip displays several vendors on one page, and take the city that most answers share. Derive the timezone from that result and pass it into the browser context before the first navigation.
Log the resolved city and carrier with every run. Because databases refresh and operators shift ranges between markets, a rotation can change the reading; with logging in place you notice it from your own records, and the worker can rotate again or pause if the new reading falls outside what the job allows. The checker on our Tools page is handy for a manual spot check while debugging.
Choosing the precision the job needs
Most automation only needs a convincing US or state-level location; localized QA, ad verification for a single market and local listings work may need the metro. Decide which before scaling out. If a line's readings do not fit, you can move it to another city from the dashboard at no cost, and support can switch you to the carrier that resolves the way your flows require.
Frequently asked
Should my script set the timezone from the city I bought or from the lookup result?
From the lookup result. Sites compare the browser with what their database says about the address, so the resolved city is the one to match. In most cases it is the same metro anyway.
The lookup changed state halfway through a job after a rotation. Is the line broken?
No. The new address probably comes from a range the database files under a neighbouring state, or the vendor refreshed its data. Rotate again if the job needs the original reading, and have the worker update its timezone from the new result.
Does the geolocation permission expose where my server is?
Only if you let it. In headless automation it usually returns nothing unless you grant it, but if you grant it, supply coordinates consistent with the proxy's city rather than letting the host report its own position.
Can I run one account on two lines at once to spread the load?
Avoid it. Two simultaneous locations for one identity is exactly the signal platforms look for. Keep each account on a single line and let it move only through normal rotation.
