JavaScript Geolocation Table
| Piece | What it does | Field note |
|---|---|---|
getCurrentPosition(ok, err) | One-shot location | Async always - GPS can take seconds; design the loading state |
watchPosition(id) | Continuous tracking | Returns an id - clearWatch or the GPS stays hot (battery) |
coords.accuracy | The honesty number | Meters of uncertainty - a 2000m accuracy is a neighborhood, not an address |
Permission prompt | The user decides | Deny = PERMISSION_DENIED forever-ish - design the denied state first |
HTTPS only | The gate | Like clipboard and camera - insecure contexts get no geolocation |
timeout + maximumAge | The patience knobs | maximumAge accepts cached fixes - fresh-only requests drain batteries |
No background tracking | Page-visible only | Real background location needs a native app - web stops with the tab |
reverse geocoding | Coordinates to address | NOT in the API - a map service call (and its key) comes after |
Geolocation returns COORDINATES with an honesty number: coords.accuracy is the uncertainty radius in meters - treating a 2-kilometer fix as a precise address is the classic UX lie, and reading the accuracy before drawing the map is what separates honest location UI from confident nonsense.
Bottom line: the contract is permission-gated (a prompt the user decides once, where deny sticks), HTTPS-only, and page-visible-only - real background tracking is a native-app capability that the web deliberately does not offer. watchPosition holds the GPS radio hot; clearWatch is the battery valve.
The honest part: the API stops at coordinates. Turning them into addresses (reverse geocoding) is a separate map-service call with its own key and quota - and that service, not the browser, decides how much location detail your users actually get.
How to use
- Design the denied state first: the error callback (code 1 = PERMISSION_DENIED) needs a manual-entry fallback - location is an enhancement, not the form.
- Budget the accuracy: if coords.accuracy > 500m, show 'near you' granularity, not an address pin - the honesty number is part of the data, not noise.
- Watch with discipline: watchPosition for live tracking, clearWatch(id) the moment tracking ends - an orphaned watch keeps the GPS radio hot for hours.
Frequently asked questions
Why is my location reading wildly different between requests?
Because the source changes under you. The browser picks the best available fix: GPS (accurate, slow, battery-hungry), Wi-Fi triangulation (medium), or IP geolocation (city-level, instant) - and each request can land on a different source, especially indoors where GPS degrades. coords.accuracy exists precisely to report WHICH quality you got: a 30m fix is GPS, a 2000m fix is probably IP-level. The UX rule: gate your granularity on the accuracy number (a 'near you' radius, not a pin), and use maximumAge to accept a recent cached fix for instant starts instead of demanding a fresh GPS lock for every page view.
What does the permission flow look like when a user denies?
Deny sticks. The prompt appears once per origin per granting decision; a denial is remembered, and subsequent getCurrentPosition calls fail immediately with PERMISSION_DENIED (code 1) without ever re-prompting. The recovery path is user-manual: browser site settings, which no script can open. This is why the denied state is a first-class UI screen, not an error toast: explain what location enables, link the settings instructions, and offer a manual alternative (city picker, postal code) - the same discipline as the notifications permission, because both are relationships the user can end permanently with one click.
How do timeout and maximumAge change the request behavior?
They control patience and freshness. timeout caps how long the browser may work on a fix before erroring (a GPS cold-start can take 30+ seconds; without a timeout the user waits blind). maximumAge says how old a CACHED fix may be and still be returned - maximumAge: 60000 returns a fix up to a minute old instantly, trading freshness for speed; maximumAge: 0 (the default) demands fresh, which is slower and more battery-hungry. The pattern: first call with a generous maximumAge for an instant coarse position, then a fresh request (or watchPosition) to refine - progressive enhancement applied to location itself.
Can a web page track location in the background?
No - by design, and it is one of the sharpest web/native lines. Geolocation callbacks only fire while the page is alive and visible; switching tabs throttles them, closing the tab stops them entirely. Continuous background tracking (a run logger, a delivery app) requires a native app or a browser-specific installable surface with its own stricter permissions. Within a page, watchPosition is the tool - but it is a foreground contract: the GPS radio stays hot while the page lives, which is both the feature (live updates) and the cost (battery) - clearWatch when the user stops moving or the feature ends.