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.
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);
}
);
| Property | Holds |
|---|---|
position.coords.latitude | north-south position in degrees, like 39.2904 |
position.coords.longitude | east-west position in degrees, like -76.6122 |
position.coords.accuracy | how many meters off the position might be (smaller is better) |
position.coords.altitude, speed, heading | often null: only some devices know them |
position.timestamp | when 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.
The error function receives an object with a code and a message. There are three codes:
| code | Name | Means |
|---|---|---|
1 | PERMISSION_DENIED | the person (or the browser) said no |
2 | POSITION_UNAVAILABLE | the device could not work out a position |
3 | TIMEOUT | it took longer than the timeout option |
console.log(GeolocationPositionError.PERMISSION_DENIED);
console.log(GeolocationPositionError.POSITION_UNAVAILABLE);
console.log(GeolocationPositionError.TIMEOUT);
enableHighAccuracy: true: ask for the best position, using GPS if there is one. Slower and uses more batterytimeout: 10000: give up after this many milliseconds (the default is to wait forever)maximumAge: 60000: accept a saved position up to this old, instead of measuring againThis 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>
Not asked yet.
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);
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));
Which is the correct way to get the result of getCurrentPosition?
const position = navigator.geolocation.getCurrentPosition()navigator.positionGive two reasons the Geolocation API might call your error function.
What does error.code equal when the person clicks "Block"?
navigator.geolocation.getCurrentPosition(
position => {},
error => console.log(error.code)
);
1, which is PERMISSION_DENIED.distanceKm to find the distance from your school to a city you choose (look up its coordinates)watchPosition you startedPress the button.