Using the Geolocation API

The Geolocation API is a very simple API that allows to get a device’s current location coordinates. It has only two methods: getCurrentPosition and watchPosition and the data returned is very straightforward, but when coupled with a mapping API, complex location-aware web apps can be created.

Setup

Before doing anything, you’ll want to check if the API is available in the user’s browsers:

if (navigator.geolocation) {
  // 🗺️ yep, we can proceed!
} else {
  // no can do
}

Note that your website or app has to be served over https for the API to work. For local development, you’ll want to run a local server instead of opening an html file directly. If you have npm 5.2 or above available on your machine, you can use npx to quickly run an http server:

$ npx http-server

getCurrentPosition

Use the getCurrentPosition method to get the user’s coordinates once. The first and only required argument should be a success callback function that will be called with a position object if the position request is successful.

Here’s a simple example that prints out the device’s longitude and latitude to the console:

if (navigator.geolocation) {
  navigator.geolocation.getCurrentPosition(displayLocationInfo);
}

function displayLocationInfo(position) {
  const lng = position.coords.longitude;
  const lat = position.coords.latitude;

  console.log(`longitude: ${ lng } | latitude: ${ lat }`);
}

Here’s the shape and example data of the position object that’s passed to the success callback:

coords:
  accuracy: 52
  altitude: null
  altitudeAccuracy: null
  heading: null
  latitude: 27.380583
  longitude: 33.631839
  speed: null
timestamp: 1509152059444

As you can see from the above example, some of the properties for coords may have a value of null. The availability of the data will depend on the capabilities of the device that’s under use. The heading value, if any, will be in degrees relating to true North and going clockwise and the speed value, if any, will be in meters per second.

Permission

Because position information is potentially sensitive, the first time a domain makes a call to get a user’s position, the browser will ask the user for permission by showing a widget that looks a little bit like this:

Geolocation permission widget

If the user refuses access, the error callback, if any, will be called with an error code of 1 (PERMISSION_DENIED).

watchPosition

There’s also a watchPosition method that will return new position data each time the device changes position significantly.

In the following example, we initiate a position watcher and then stop it after 15 seconds:

const watcher = navigator.geolocation.watchPosition(displayLocationInfo);

setTimeout(() => {
  navigator.geolocation.clearWatch(watcher);
}, 15000);

function displayLocationInfo(position) {
  // ...do something with the data each time
}

We use clearWatch with a watcher id to stop watching for position data.

Error Handling

You can provide an error handler callback as the second argument to either getCurrentPosition or watchPosition. If the error callback is called, an error object will be passed-in and will contain a code property that will have a value of 3 (TIMEOUT), 2 (POSITION_UNAVAILABLE) or 1 (PERMISSION_DENIED), depending on the nature of the error.

Here’s a simple example where we trigger an automatic error by setting a timeout value of 0ms:

navigator.geolocation.getCurrentPosition(displayLocationInfo, handleLocationError, { timeout: 0 });

function displayLocationInfo(position) {
  // ...do stuff
}

function handleLocationError(error) {
  switch (error.code) {
    case 3:
      // ...deal with timeout
      break;
    case 2:
      // ...device can't get data
      break;
    case 1:
      // ...user said no ☹️
  }
}

Options

Finally, you can pass-in a third argument with options for the following:

  • enableHighAccuracy: Takes a boolean value and defaults to false. Indicates if the position information should be as accurate as possible (more accuracy may be more costly in terms of CPU and battery usage).
  • maximumAge: Number of milliseconds to keep position data cached for. It defaults to a value of 0.
  • timeout: Number of milliseconds after which the error callback will be called if no data has been acquired.

Here’s an example with options passed-in for maximumAge and timeout:

navigator.geolocation.getCurrentPosition(
  displayLocationInfo,
  handleLocationError,
  { maximumAge: 1500000, timeout: 0 }
);

function displayLocationInfo(position) {
  const lng = position.coords.longitude;
  const lat = position.coords.latitude;

  console.log(`longitude: ${lng} | latitude: ${lat}`);
}

function handleLocationError(error) {
  switch (error.code) {
    case 3:
      // timeout was hit, meaning nothing's in the cache
      // let's provide a default location:
      displayLocationInfo({ coords: { longitude: 33.631839, latitude: 27.380583 } });

      // now let's make a non-cached request to get the actual position
      navigator.geolocation.getCurrentPosition(displayLocationInfo, handleLocationError);
      break;
    case 2:
      // ...
      break;
    case 1:
    // ...
  }
}

If there’s cached position data that’s available and that’s a maximum of 25 minutes old (1500000ms) we return that. If not, we error-out immediately (using a timeout of 0ms). In the error handler case for a timeout, we provide a default location value and then make another call to get fresh location data. This way, the app can avoid showing a blank state while fresh position data is being gathered.

Browser Support

Can I Use geolocation? Data on support for the geolocation feature across the major browsers from caniuse.com.

  Tweet It
✖ Clear

🕵 Search Results

🔎 Searching...