SKU // 133

JS Geolocation

The Geolocation API lets a page ask where the device is. It is the clearest example of a browser API that touches something private, so it always asks permission first, can be refused, and can fail in several ways. This lesson covers asking for a position, reading the answer, handling each way it can go wrong, and the privacy rules that go with it.

A note about the examples. Asking for a location needs the person to allow it, and the Try It editor may be blocked from asking at all. Where an example cannot run here, the lesson shows what you would see. Everything about the code is the same on a page of your own.

// Asking for the Position

navigator.geolocation.getCurrentPosition(success, error, options) asks once. It does not return the position: it calls one of the two functions you give it, later, after the person answers:

navigator.geolocation.getCurrentPosition(
  function (position) {
    console.log(position.coords.latitude, position.coords.longitude);
  },
  function (error) {
    console.log("Could not get location:", error.message);
  }
);

// What a Position Holds

Property Holds
position.coords.latitudenorth-south position in degrees, like 39.2904
position.coords.longitudeeast-west position in degrees, like -76.6122
position.coords.accuracyhow many meters off the position might be (smaller is better)
position.coords.altitude, speed, headingoften null: only some devices know them
position.timestampwhen the position was measured

Latitude runs from -90 (the South Pole) to 90 (the North Pole). Longitude runs from -180 to 180, west of Greenwich to east. A position is only as good as its accuracy: a phone with GPS may be within 10 meters, while a laptop on wifi may be off by a kilometer.

// When It Goes Wrong

The error function receives an object with a code and a message. There are three codes:

code Name Means
1PERMISSION_DENIEDthe person (or the browser) said no
2POSITION_UNAVAILABLEthe device could not work out a position
3TIMEOUTit took longer than the timeout option
console.log(GeolocationPositionError.PERMISSION_DENIED);
console.log(GeolocationPositionError.POSITION_UNAVAILABLE);
console.log(GeolocationPositionError.TIMEOUT);
1 2 3

// Options

// Trying It: a Button and a Message

This page asks for the location when you click, and reports the coordinates or the reason it failed. Because it needs permission, it only runs when the person clicks, never on its own:

<button id="where">Where am I?</button>
<p id="out">Not asked yet.</p>

<script>
  const out = document.getElementById("out");

  document.getElementById("where").addEventListener("click", function () {
    if (!("geolocation" in navigator)) {
      out.textContent = "No geolocation here";
      return;
    }
    out.textContent = "Asking...";
    navigator.geolocation.getCurrentPosition(
      function (position) {
        const c = position.coords;
        out.textContent = c.latitude.toFixed(2) + ", " + c.longitude.toFixed(2) +
          " (within " + Math.round(c.accuracy) + " m)";
      },
      function (error) {
        out.textContent = "Could not get location (code " + error.code + ")";
      },
      { timeout: 10000 }
    );
  });
</script>

// Following Movement: watchPosition

watchPosition calls your function again every time the position changes, until you stop it with clearWatch. It is how a map follows you:

const id = navigator.geolocation.watchPosition(function (position) {
  console.log("now at", position.coords.latitude, position.coords.longitude);
});

// when you are done (this saves the battery):
navigator.geolocation.clearWatch(id);

// Using a Position: Distance

Latitude and longitude are angles, so the distance between two places is a bit of trigonometry. The haversine formula gives the straight-line distance over the earth's surface. It is just math, so you can run it without any permission:

function distanceKm(lat1, lon1, lat2, lon2) {
  const toRad = deg => deg * Math.PI / 180;
  const earthRadiusKm = 6371;
  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 earthRadiusKm * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
}

// Baltimore to New York City
console.log(Math.round(distanceKm(39.2904, -76.6122, 40.7128, -74.0060)), "km");
// the same place twice
console.log(distanceKm(10, 10, 10, 10));
273 km 0

// Privacy

Never rely on it
Geolocation can be denied, unavailable, slow, or wrong. A page that only works when it succeeds is broken for many people. Design the page so that it still does something useful without a location.

// Quick Check

Which is the correct way to get the result of getCurrentPosition?

  1. const position = navigator.geolocation.getCurrentPosition()
  2. Pass a success function (and an error function) that the browser calls later
  3. Read navigator.position
  4. It always returns instantly
Show answer
B. The call does not return the position. It calls your success function once the person has answered and the position is known (or your error function if it fails).

Give two reasons the Geolocation API might call your error function.

Show answer
The person denied permission, the device could not work out a position, or the request timed out. (Also: the page was not served over https.)

What does error.code equal when the person clicks "Block"?

navigator.geolocation.getCurrentPosition(
  position => {},
  error => console.log(error.code)
);
Show answer
1, which is PERMISSION_DENIED.

// Try It

  1. Click Open Playground and press the button. Allow, then try again and block
  2. Change the Playground to also show the accuracy in meters
  3. Use distanceKm to find the distance from your school to a city you choose (look up its coordinates)
  4. Write the one line that stops a watchPosition you started
// Video Walkthroughs
Last updated: Oct 11, 2026, 8:13 PM ET