HTML5 Geolocation API Accuracy Limits & Handling Location Errors
Whenever a website asks, "Allow this site to access your location?", clicking Allow hands your coordinates to the browser's HTML5 Geolocation API. Yet if you have ever built or used a location-based web app, you have probably noticed that the exact same code sometimes pinpoints your street corner within 5 meters, and other times places you in a district 3 kilometers away. This article explains how browsers actually determine your position under the hood, how to interpret the `accuracy` confidence radius, how to filter noisy GPS jitter, and the five mistakes developers make most often.
1. How Does a Web Browser Determine Your Location?
A surprising detail in the official W3C Geolocation API Specification is that the spec does not mandate how a device calculates position. Instead, the browser delegates positioning to the underlying operating system's location subsystem (CoreLocation on macOS/iOS, Fused Location Provider on Android, Windows Location Service), which blends up to four signal sources depending on hardware availability:
- GNSS Satellite Signals (GPS, GLONASS, Galileo): Delivers 3–10 meter accuracy outdoors under an open sky. However, satellite signals struggle to penetrate concrete roofs, suffer from multipath reflection (urban canyon effect) between glass high-rises, and take several seconds for an initial cold lock.
- Wi-Fi Positioning System (WPS): Scans the MAC addresses (BSSIDs) and signal strengths (RSSI) of nearby Wi-Fi access points—even without connecting to them—and looks up their coordinates in a cloud geolocation database. Usually accurate to 15–40 meters inside urban buildings.
- Cellular Tower Triangulation (Cell-ID): Estimates position from the serving mobile base station. Accuracy ranges from 200 meters in dense city centers to several kilometers in rural areas.
- IP Address Geolocation: Used as a last resort on desktop PCs without Wi-Fi or GPS hardware, or when wireless scanning is disabled. Because ISPs route traffic through regional aggregation hubs, IP geolocation frequently lands 2 to 20 kilometers away from the user's physical desk.
Because the API never tells you which source produced the fix, your code must inspect `position.coords.accuracy` to know whether the returned coordinates represent a rooftop GPS lock or a coarse ISP hub.
2. Calling `getCurrentPosition()` & Configuring Options Properly
navigator.geolocation.getCurrentPosition(
(position) => {
const { latitude, longitude, accuracy } = position.coords;
handleLocationFix(latitude, longitude, accuracy);
},
(error) => {
// error.code: 1 = PERMISSION_DENIED, 2 = POSITION_UNAVAILABLE, 3 = TIMEOUT
handleLocationError(error.code, error.message);
},
{
enableHighAccuracy: true, // Hint to prefer GPS over coarse network location
timeout: 10000, // Abort with TIMEOUT (code 3) after 10 seconds
maximumAge: 60000, // Accept a cached fix up to 60 seconds old
}
);
- `enableHighAccuracy`: A boolean hint asking the OS to power up hardware GPS if available. Turning it on improves precision outdoors but increases response latency and battery drain.
- `timeout`: Defaults to `Infinity`! If you omit `timeout` and the user is inside an underground subway station where GPS cannot lock, the callback can hang indefinitely. Always set a sensible timeout (such as `8000`–`10000` ms).
- `maximumAge`: Defaults to `0` (forcing a fresh hardware lookup every time). For a weather or amenity app where a fix from 60 seconds ago is completely valid, setting `maximumAge: 60000` returns cached coordinates instantaneously.
3. How to Read `position.coords.accuracy`
The `accuracy` property is expressed in meters and is defined by the W3C specification as a 95% confidence radius. If the browser returns `latitude: 37.5665, longitude: 126.9780, accuracy: 1500`, it means: "There is a 95% probability that the user's true physical location lies somewhere inside a circle of radius 1.5 km centered on (37.5665, 126.9780)."
Quick Rule of Thumb for Coordinate Jitter (Around 37.5° N)
0.001°of latitude ≈ 111 meters0.001°of longitude ≈ 88 meters- Therefore, fluctuations in the 4th or 5th decimal place (`0.0001°`–`0.00001°`) represent 1 to 10 meters of normal sensor noise—even when the phone is sitting completely still on a desk.
4. Stabilizing Noisy Fixes in `watchPosition()`
When tracking continuous movement with `navigator.geolocation.watchPosition()`, raw coordinates jitter slightly on every tick. Re-fetching API data or re-centering the map on every 2-meter fluctuation wastes network calls and causes visual jumping. Production location apps apply two simple filters:
- Confidence Threshold Filter: Ignore or flag fixes where `accuracy` exceeds your domain threshold (for example, `accuracy > 100` meters for turn-by-turn walking, or `accuracy > 2000` meters for neighborhood weather), or warn the user that the location is approximate.
- Minimum Displacement (Deadband) Filter: Compute the distance between the previous accepted coordinate and the new fix using the Haversine formula, and trigger a state update only when the user has moved beyond a minimum threshold (e.g., 50 meters and `distance > accuracy * 0.5`).
Always remember to stop continuous tracking when the component unmounts by passing the watch ID to `navigator.geolocation.clearWatch(watchId)` so the device GPS radio can power down.
function haversineDistance(lat1, lon1, lat2, lon2) {
const R = 6371e3; // Earth mean radius in meters
const toRad = (deg) => (deg * Math.PI) / 180;
const dLat = toRad(lat2 - lat1);
const dLon = toRad(lon2 - lon1);
const a =
Math.sin(dLat / 2) ** 2 +
Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) * Math.sin(dLon / 2) ** 2;
return 2 * R * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
}
haversineDistance(37.5665, 126.978, 37.5675, 126.978); // ~111.2 meters
5. Five Common Mistakes in Production
- Calling Geolocation on a non-HTTPS page: `navigator.geolocation` is restricted to Secure Contexts (`https://` or `http://localhost`). On plain HTTP, browsers immediately reject the call.
- Prompting for location on initial page load (`useEffect` on mount): Users instinctively block permission prompts when they haven't clicked anything yet, and modern browsers penalize sites with high dismissal rates. Trigger `getCurrentPosition()` inside an explicit user action like a "Find Weather Near Me" button click.
- Omitting fallback UI when permission is denied: Roughly 15–30% of users decline location prompts or use desktop browsers with inaccurate IP positioning. Always provide a manual neighborhood search bar or map picker alongside automatic GPS.
- Ignoring `accuracy` and trusting coordinates blindly: If a desktop PC returns `accuracy: 5000`, displaying a hyper-specific street address without a manual override confuses users.
- Retaining high-precision coordinates on the server unnecessarily: Exact GPS trajectories are sensitive personal data. Convert coordinates to coarse grid IDs or administrative district codes on the client whenever possible.
6. Summary
Because the HTML5 Geolocation API abstracts away whether a fix came from satellites, Wi-Fi, cell towers, or an ISP router, reliable location web apps always pair HTTPS, explicit user-initiated prompts, `timeout` bounds, `accuracy` confidence checks, and Haversine distance filtering.
To see how HereWeather uses browser geolocation to resolve your local neighborhood forecast, check out our HereWeather User Guide, along with our technical posts on WGS84 vs. UTM-K Coordinate Systems and Map Projections & the KMA 5 km Grid.