Geolocation Api

The Geolocation API was standardized in 2008, uses callbacks instead of promises, and gives you exactly five properties from each location fix. Here is everything the API does.

June 10, 20265 min read5 / 17

Here is the thing about the Geolocation API: it predates promises.

Every other modern web API uses promises. This one was standardized in 2008 and stayed that way. You adapt to it rather than the other way around -- callbacks, error callbacks, and an options object, all in a row.

It is also one of the simplest APIs on the platform once you see the shape of it. Two methods, five useful properties on the position object, three options.

If you want to understand how the browser actually finds you before diving into the API, that post covers the GPS vs Wi-Fi scanning difference and why coords.accuracy is the most useful property the API returns.

Feature Detection

The Geolocation API is green tier -- it works in every major browser on every platform, including iOS Safari. Feature detection is still good practice, particularly to give older browsers a clean failure path:

JavaScript
if ('geolocation' in navigator) { // safe to call the API } else { showNotSupportedMessage(); }

Getting the Location Once

getCurrentPosition fires your success callback once and stops.

JavaScript
navigator.geolocation.getCurrentPosition( position => { const { latitude, longitude, accuracy } = position.coords; console.log(`${latitude}, ${longitude}${accuracy}m)`); }, error => { if (error.code === error.PERMISSION_DENIED) { showSettingsInstructions(); } else if (error.code === error.TIMEOUT) { showRetryUI(); } }, { timeout: 8000, maximumAge: 30000, enableHighAccuracy: false } );

The first argument is the success callback. The second is the error callback. The third is an options object.

Watching the Position Continuously

watchPosition uses the exact same API signature, but fires your callback repeatedly as the user moves.

JavaScript
const watchId = navigator.geolocation.watchPosition( position => updateMapPin(position.coords), error => console.error(error.code) ); // Stop watching when no longer needed navigator.geolocation.clearWatch(watchId);

Call clearWatch() when you're done. Leaving a watch running when the user navigates away from the map feature wastes battery and battery permission. Always pair every watchPosition with a clearWatch.

The Geolocation API: methods, position object, options, and error codes ExpandThe Geolocation API: methods, position object, options, and error codes

What the Position Object Contains

JavaScript
position.timestamp // epoch ms when the fix was acquired position.coords.latitude // decimal degrees, always present position.coords.longitude // decimal degrees, always present position.coords.accuracy // radius in meters -- always present position.coords.altitude // meters above sea level, or null position.coords.altitudeAccuracy // null if altitude is null position.coords.heading // degrees from north, or null position.coords.speed // m/s, or null

The three that are always populated: latitude, longitude, and accuracy. Everything else may be null.

Null values are diagnostic. altitude being null means the fix came from Wi-Fi scanning, not GPS. heading and speed being null means the device isn't moving fast enough to calculate them, or isn't using GPS. accuracy of 16 meters is consistent with Wi-Fi. accuracy of 600 is consistent with a desktop computer using IP address as a fallback.

The Three Options

timeout -- milliseconds to wait before calling the error callback with TIMEOUT. Default is Infinity, which means wait as long as necessary. Setting this to 8000 gives the user 8 seconds before you show a "couldn't get location" message.

maximumAge -- how old a cached location is acceptable, in milliseconds. Default is 0, meaning "give me a fresh fix right now." If you set this to 60000, the browser will return any fix acquired in the last minute without requesting a new one. For most use cases -- "show me nearby cafes" -- a 30-second-old location is perfectly fine, and accepting cached data makes the response noticeably faster.

enableHighAccuracy -- a boolean hint that the device should prefer GPS over Wi-Fi. This is a hint, not a guarantee. Setting it to true increases battery usage and slows the initial response. Use it only when you genuinely need 10-meter precision rather than 50-meter.

One edge case specific to iOS is worth its own post: when a user chooses "approximate" location instead of "precise," Safari's handling of that choice affects every website they visit -- not just yours.

HTTPS and Localhost

The Geolocation API requires a secure context. If you're not on HTTPS, the permission dialog will not appear and the API will error.

The localhost exception applies -- http://localhost works for development. One edge case: http://127.0.0.1 does not count. It has to be the literal hostname localhost, not the IP address. If your local dev server serves to an IP address, add a localhost alias or use HTTPS locally.

Testing with Chrome DevTools

Chrome has a sensor override panel hidden in the DevTools drawer. Open DevTools, click the three-dot menu, choose "More tools" then "Sensors." Under Location, you can set any coordinates you want.

Plain text
DevTools → three-dot menu → More tools → Sensors → Location

Switch the dropdown from "No override" to a preset city, or enter custom latitude and longitude. Any active getCurrentPosition or watchPosition call will immediately return the overridden location.

This is the practical way to test your app against specific coordinates without physically traveling. If you have a watchPosition running, you can also switch between locations while watching -- your app's position tracking will update in real time.

For more complex testing -- replaying a real GPS track -- there are Chrome extensions that accept a .gpx file (the standard format for recorded GPS routes) and replay your walk through the sensor emulator.

The Essentials

  1. getCurrentPosition fires once. watchPosition fires continuously. Both take identical arguments.
  2. Always call clearWatch() when done -- leaving a watch running wastes battery.
  3. coords.accuracy in meters is the most useful diagnostic. ~10m suggests GPS. 50m+ suggests Wi-Fi scanning. null altitude confirms Wi-Fi.
  4. maximumAge accepts cached locations -- set it to 30-60 seconds for most use cases to get faster responses.
  5. Requires HTTPS. http://localhost works for development. http://127.0.0.1 does not.

Further Reading and Watching