Difficulty: Advanced
The Geolocation API allows web applications to access the user's geographical location. It is accessed through the navigator.geolocation object and requires explicit user permission before any location data is shared. This permission model is enforced by the browser - the user sees a prompt asking whether to allow or block location access, and they can revoke it at any time through browser settings.
The primary method is getCurrentPosition(successCallback, errorCallback, options). When called, the browser requests the user's location from the device (using GPS, Wi-Fi triangulation, cell tower data, or IP geolocation as fallback). On success, the callback receives a GeolocationPosition object containing a coords property with latitude, longitude, accuracy (in meters), and optionally altitude, altitudeAccuracy, heading, and speed. The timestamp property indicates when the position was determined.
For applications that need continuous location tracking (fitness trackers, navigation, delivery tracking), the watchPosition() method works identically to getCurrentPosition() but fires the success callback every time the device's position changes. It returns a watchId that you must pass to clearWatch(watchId) to stop tracking. Failing to clear a watch drains the device's battery and continues background GPS usage.
The optional third parameter is an options object with three properties. enableHighAccuracy (boolean) requests GPS-level precision when available, at the cost of battery life and response time. timeout (milliseconds) sets the maximum wait time before the error callback fires with a TIMEOUT error. maximumAge (milliseconds) allows the browser to return a cached position if it is newer than the specified age, reducing GPS queries.
Error handling is critical for geolocation. The error callback receives a GeolocationPositionError with a code property: PERMISSION_DENIED (1) means the user blocked the request, POSITION_UNAVAILABLE (2) means the device could not determine its location, and TIMEOUT (3) means the request exceeded the timeout. Your application must handle all three cases gracefully, providing fallback behavior or informative messages. The Geolocation API only works on secure contexts (HTTPS), so it will fail silently on HTTP pages.
<button id="locate-btn">Get My Location</button>
<p id="location-output">Click the button to get your location.</p>
<script>
const btn = document.getElementById('locate-btn');
const output = document.getElementById('location-output');
btn.addEventListener('click', () => {
if (!navigator.geolocation) {
output.textContent = 'Geolocation is not supported by your browser.';
return;
}
output.textContent = 'Locating...';
navigator.geolocation.getCurrentPosition(
(position) => {
const { latitude, longitude, accuracy } = position.coords;
output.textContent =
`Lat: ${latitude.toFixed(6)}, ` +
`Lng: ${longitude.toFixed(6)}, ` +
`Accuracy: ${accuracy.toFixed(0)}m`;
},
(error) => {
output.textContent = `Error: ${error.message}`;
}
);
});
</script>
Always check for navigator.geolocation before calling methods. The success callback receives coords with latitude, longitude, and accuracy. The error callback provides an error message and code.
<script>
const options = {
enableHighAccuracy: true, // Use GPS if available
timeout: 10000, // Fail after 10 seconds
maximumAge: 60000 // Accept cached position up to 1 min old
};
navigator.geolocation.getCurrentPosition(
(position) => {
console.log('Latitude:', position.coords.latitude);
console.log('Longitude:', position.coords.longitude);
console.log('Accuracy:', position.coords.accuracy, 'meters');
console.log('Altitude:', position.coords.altitude); // May be null
console.log('Speed:', position.coords.speed); // May be null
console.log('Heading:', position.coords.heading); // May be null
console.log('Timestamp:', new Date(position.timestamp));
},
(error) => {
switch (error.code) {
case error.PERMISSION_DENIED:
console.log('User denied location permission.');
break;
case error.POSITION_UNAVAILABLE:
console.log('Location information unavailable.');
break;
case error.TIMEOUT:
console.log('Location request timed out.');
break;
}
},
options
);
</script>
enableHighAccuracy uses GPS for precision. timeout sets a maximum wait (ms). maximumAge allows cached results. The error codes cover all failure scenarios - always handle all three.
<button id="start-watch">Start Tracking</button>
<button id="stop-watch" disabled>Stop Tracking</button>
<div id="tracker"></div>
<script>
let watchId = null;
const tracker = document.getElementById('tracker');
const startBtn = document.getElementById('start-watch');
const stopBtn = document.getElementById('stop-watch');
startBtn.addEventListener('click', () => {
watchId = navigator.geolocation.watchPosition(
(position) => {
const { latitude, longitude, speed } = position.coords;
tracker.innerHTML = `
<p>Lat: ${latitude.toFixed(6)}</p>
<p>Lng: ${longitude.toFixed(6)}</p>
<p>Speed: ${speed ? (speed * 3.6).toFixed(1) + ' km/h' : 'N/A'}</p>
<p>Updated: ${new Date(position.timestamp).toLocaleTimeString()}</p>
`;
},
(error) => {
tracker.textContent = `Tracking error: ${error.message}`;
},
{ enableHighAccuracy: true }
);
startBtn.disabled = true;
stopBtn.disabled = false;
});
stopBtn.addEventListener('click', () => {
if (watchId !== null) {
navigator.geolocation.clearWatch(watchId);
watchId = null;
}
startBtn.disabled = false;
stopBtn.disabled = true;
tracker.textContent = 'Tracking stopped.';
});
</script>
watchPosition fires the callback each time the position changes. Always store the watchId and call clearWatch() when done to stop GPS usage and save battery. Speed is in m/s - multiply by 3.6 for km/h.
<script>
// Haversine formula: distance between two GPS coordinates
function getDistance(lat1, lng1, lat2, lng2) {
const R = 6371; // Earth's radius in km
const dLat = toRad(lat2 - lat1);
const dLng = toRad(lng2 - lng1);
const a = Math.sin(dLat / 2) 2 +
Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) *
Math.sin(dLng / 2) 2;
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return R * c; // Distance in km
}
function toRad(degrees) {
return degrees * (Math.PI / 180);
}
// Usage with geolocation
const TARGET = { lat: 48.8566, lng: 2.3522 }; // Paris
navigator.geolocation.getCurrentPosition((pos) => {
const dist = getDistance(
pos.coords.latitude, pos.coords.longitude,
TARGET.lat, TARGET.lng
);
console.log(`You are ${dist.toFixed(1)} km from Paris.`);
});
</script>
The Haversine formula calculates the great-circle distance between two points on a sphere. It accounts for Earth's curvature, making it accurate for distances from a few meters to thousands of kilometers.
navigator.geolocation, getCurrentPosition, watchPosition, Permissions, Error Handling