How websites know where you are

sgro2 pts0 comments

How Websites Actually Know Where You Are | GeoSpoof BlogSkip to main content<br>Download<br>All postsBrowsers can locate you through at least eight independent signals: your IP address, the Wi-Fi access points around you, GPS, cell-tower triangulation, your timezone offset, your IANA timezone name, JavaScript Date formatting, and WebRTC (which can expose your real IP even behind a VPN). A VPN only changes the IP signal, which is why it isn't enough on its own for location privacy.

A laptop with no GPS chip, sitting in a basement, can tell a website which block<br>it's on. It doesn't need satellites and it doesn't need you to click anything.<br>It just needs to overhear the names of your neighbors' routers, which it is<br>already doing, constantly, for reasons that have nothing to do with you.

Most people picture location as one of two things: GPS, or the little dot an IP<br>address puts on a map. It's neither, or rather it's both plus six other things.<br>Browsers pull from a whole stack of independent signals, and the reason this<br>matters is that a VPN<br>only deals with one of them. Here's the rest of the stack.

Your IP address

The one everyone knows about. Every connection has a public<br>IP address, and commercial databases<br>like MaxMind and<br>IP2Location map ranges of them to places by<br>stitching together registration records, routing data, and active probing.<br>Accuracy is usually city-level for home broadband, vaguer on mobile.

This is the signal a VPN actually changes: your traffic exits from the VPN's<br>server, so the lookup returns the server's city instead of yours. Useful, and<br>also the entire extent of what a VPN does for your location. Everything below<br>this line, it leaves completely untouched.

The Wi-Fi networks around you

This is the one that surprises people. When a page calls<br>navigator.geolocation.getCurrentPosition(),<br>your browser asks the operating system for a list of nearby<br>Wi-Fi access points, their<br>names and hardware addresses, and ships that list to a location service run by<br>Google, Apple, or Mozilla.

Those services know where the routers are because companies literally drove<br>around and wrote it down. The practice is called<br>wardriving: cars with GPS and Wi-Fi<br>receivers building a global map of which router lives where, topped up with<br>crowdsourced pings from phones. Hand the service a list of the routers you can<br>see and it cross-references its database and hands back coordinates good to<br>within 10 to 20 meters. No GPS hardware required. Hence the basement laptop.

GPS

On phones, tablets, and some laptops, the OS can pull coordinates straight from<br>GPS satellites,<br>accurate to a few meters outdoors. Browsers reach it through the same<br>navigator.geolocation API. You don't get to pick the source; the OS quietly<br>decides whether GPS, Wi-Fi, or cell towers answers the question.

Cell towers

When Wi-Fi is thin on the ground, a mobile device can estimate position from the<br>signal strength of nearby cell towers<br>and a bit of trilateration.<br>Roughly 100 meters in a dense city, several kilometers out in the country. Less<br>precise than Wi-Fi, but it works anywhere there's coverage.

Your timezone

Two ways in, both free of charge and free of permission prompts.

new Date().getTimezoneOffset() // e.g. 480 for UTC-8 (PST)<br>Intl.DateTimeFormat().resolvedOptions().timeZone // e.g. "America/Los_Angeles"

The offset<br>just bands you to a slice of the planet. The<br>IANA identifier is the chatty one.<br>"America/Los_Angeles" puts you on the West Coast; "Asia/Kolkata" gives up the<br>whole country, since India is the only place running UTC+5:30, a detail<br>fingerprinting scripts are very aware of. This single signal gives away a<br>surprising amount on its own.

The timezone signal: simple, until you look at it.

Date formatting

Adjacent to the timezone, and easy to forget:

new Date().toString()<br>// "Sat May 03 2026 14:23:45 GMT-0800 (Pacific Standard Time)"

Date.prototype.toString()<br>and toLocaleString() happily print the timezone name right there in the<br>output. A script doesn't even have to ask nicely; it just formats a date and<br>reads what falls out.

The Temporal API

The newer Temporal API replaces the<br>ancient Date object and is more upfront about timezones, not less:

Temporal.Now.timeZoneId() // "America/Los_Angeles"

As it ships in more browsers it becomes one more door that has to be locked. If<br>you spoof Date and Intl but forget Temporal, you've left it open.

WebRTC, the one that leaks through your VPN

WebRTC powers in-browser calls and<br>file transfer. To connect two peers it uses<br>ICE,<br>which enumerates your network interfaces looking for a path. That enumeration<br>can surface your local IPs and, the part that stings, your real public IP, even<br>with a VPN running. The VPN adds a virtual interface, but ICE may also list the<br>physical one and attach the public IP it sees. A page can trigger this with a<br>few lines of JavaScript and read the result without ever placing a call.

This is the WebRTC leak, and it isn't a bug.<br>It's the spec working as...

date timezone signal from address cell

Related Articles