Geolocation
Getting the user's location — getCurrentPosition, watchPosition, permissions, accuracy, and handling errors.
What it is, in plain English: The Geolocation API lets a web page request the user's physical location. The browser asks the user for permission first — you cannot get location silently. getCurrentPosition() gets the location once. watchPosition() tracks the location continuously (for navigation apps). Location data includes latitude, longitude, accuracy, altitude, speed, and heading.
Where this bites you
coords.speed (like heading, altitude and altitudeAccuracy) is null when the device can't measure them, which is usual on laptops and on Wi-Fi-based fixes. JavaScript happily calculates null * 3.6 as 0, so a speed display shows a confident 0.0 km/h instead of admitting it doesn't know.
// <span id="speed"></span>
const speedDisplay = document.getElementById("speed");
navigator.geolocation.getCurrentPosition((position) => {
speedDisplay.textContent = `${(position.coords.speed * 3.6).toFixed(1)} km/h`;
console.log(position.coords.speed, speedDisplay.textContent);
});
// null "0.0 km/h"Getting the user's location
User permission required. The browser always asks before sharing location.
You cannot get location without explicit user consent.
Also requires HTTPS (or localhost for development).
getCurrentPosition — one-time location
navigator.geolocation.getCurrentPosition(
// Success callback:
(position) => {
const { latitude, longitude, accuracy } = position.coords;
console.log(`Lat: ${latitude}, Lng: ${longitude}`);
console.log(`Accuracy: ±${accuracy} metres`);
showOnMap(latitude, longitude);
},
// Error callback:
(error) => {
if (error.code === error.PERMISSION_DENIED) {
showMessage("Please allow location access to use this feature");
} else {
showMessage("Could not get your location — try again");
}
},
// Options:
{
enableHighAccuracy: true, // use GPS if available (slower, uses more battery)
timeout: 10000, // give up after 10 seconds
maximumAge: 0, // don't use cached position (always fresh)
}
);watchPosition — continuous tracking
// For navigation — fires every time position changes:
const watchId = navigator.geolocation.watchPosition(
(position) => {
updateMapMarker(position.coords.latitude, position.coords.longitude);
speedDisplay.textContent = `${(position.coords.speed * 3.6).toFixed(1)} km/h`;
},
(error) => console.error(error.message),
{ enableHighAccuracy: true }
);
// Stop tracking:
navigator.geolocation.clearWatch(watchId);The watchPosition example above has exactly this line. Only latitude, longitude and accuracy are always numbers. Check every other field for null before you do arithmetic with it:
const speedDisplay = document.getElementById("speed");
navigator.geolocation.getCurrentPosition((position) => {
const { speed } = position.coords; // null when the device can't measure it
speedDisplay.textContent = speed === null
? "speed unavailable"
: `${(speed * 3.6).toFixed(1)} km/h`;
console.log(speed, speedDisplay.textContent);
});
// null "speed unavailable"Calculate distance between two coordinates
// Haversine formula — great-circle distance:
function getDistance(lat1, lng1, lat2, lng2) {
const R = 6371; // Earth radius in km
const dLat = (lat2 - lat1) * Math.PI / 180;
const dLng = (lng2 - lng1) * Math.PI / 180;
const a = Math.sin(dLat/2) ** 2 +
Math.cos(lat1 * Math.PI/180) * Math.cos(lat2 * Math.PI/180) * Math.sin(dLng/2) ** 2;
return R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
}
// Mumbai to Delhi:
console.log(getDistance(19.076, 72.878, 28.644, 77.216).toFixed(0), "km"); // 1151 km
Try It Yourself
Official Sources
- MDN Web Docs — Geolocation API
- MDN Web Docs — Using the Geolocation API
- W3C Geolocation API Specification
- OpenStreetMap Nominatim — Reverse geocoding
The Codex links only to official documentation and the ECMAScript specification. No third-party tutorials.