Skip to content

HTML5 - Geolocation

The HTML5 Geolocation API provides a standard way for web applications to access a user’s geographical location, with their explicit permission. This enables location-aware features like finding nearby points of interest, providing directions, geotagging content, or tailoring content based on region.

The API works by leveraging various data sources available to the device and browser, such as GPS (most accurate, usually on mobile devices), Wi-Fi network positioning, cell tower triangulation, or IP address lookup (least accurate).

Privacy is paramount: The browser must obtain the user’s permission before sharing location data with a website. Users can deny permission, and the API provides mechanisms for handling such denials.

The Geolocation API is accessed through the navigator.geolocation object. You should first check if this object exists to ensure browser support.

if ('geolocation' in navigator) {
// Geolocation is supported
console.log('Geolocation API available.');
// Proceed to use the API methods...
} else {
// Geolocation is not supported by this browser
console.error('Geolocation API is not available in this browser.');
// Inform the user or disable location features
}

The navigator.geolocation object provides three primary methods:

MethodDescription
getCurrentPosition(successCallback, [errorCallback], [options])Retrieves the device’s current location as a one-time request. Calls the successCallback with a GeolocationPosition object on success, or the errorCallback with a GeolocationPositionError object on failure.
watchPosition(successCallback, [errorCallback], [options])Continuously monitors the device’s location and calls the successCallback whenever the position changes significantly. Returns an ID value that can be used to stop monitoring.
clearWatch(watchId)Stops an ongoing location monitoring process initiated by watchPosition(), using the ID returned by that call.

The GeolocationPosition Object (Success Callback)

Section titled “The GeolocationPosition Object (Success Callback)”

The successCallback function passed to getCurrentPosition or watchPosition receives a GeolocationPosition object containing the location information:

PropertyTypeDescription
coordsObject (GeolocationCoordinates)Contains the geographic coordinates and accuracy information.
coords.latitudeNumberLatitude in decimal degrees.
coords.longitudeNumberLongitude in decimal degrees.
coords.accuracyNumberAccuracy of the latitude and longitude estimate in meters.
coords.altitudeNumber | null[Optional] Altitude in meters above the WGS 84 ellipsoid, or null if unavailable.
coords.altitudeAccuracyNumber | null[Optional] Accuracy of the altitude estimate in meters, or null if unavailable.
coords.headingNumber | null[Optional] Direction of travel in degrees (0=North, 90=East, etc.), or null if unavailable.
coords.speedNumber | null[Optional] Current ground speed in meters per second, or null if unavailable.
timestampNumber (DOMTimeStamp)Time when the location information was retrieved (milliseconds since epoch).
function handleSuccess(position) {
const latitude = position.coords.latitude;
const longitude = position.coords.longitude;
const accuracy = position.coords.accuracy;
const timestamp = new Date(position.timestamp);
console.log(`Latitude: ${latitude}°`);
console.log(`Longitude: ${longitude}°`);
console.log(`Accuracy: ${accuracy} meters`);
console.log(`Timestamp: ${timestamp.toLocaleString()}`);
// Update UI, show map, etc.
document.getElementById('locationInfo').innerHTML =
`Lat: ${latitude.toFixed(5)}, Long: ${longitude.toFixed(5)} (Accuracy: ${accuracy}m)`;
}
function handleError(error) {
let errorMessage = 'An unknown error occurred.';
switch (error.code) {
case error.PERMISSION_DENIED:
errorMessage = "User denied the request for Geolocation.";
break;
case error.POSITION_UNAVAILABLE:
errorMessage = "Location information is unavailable.";
break;
case error.TIMEOUT:
errorMessage = "The request to get user location timed out.";
break;
case error.UNKNOWN_ERROR:
errorMessage = "An unknown error occurred.";
break;
}
console.error(`Geolocation Error (${error.code}): ${errorMessage}`);
document.getElementById('locationInfo').textContent = `Error: ${errorMessage}`;
}
function getLocation() {
if ('geolocation' in navigator) {
document.getElementById('locationInfo').textContent = 'Requesting location...';
navigator.geolocation.getCurrentPosition(handleSuccess, handleError, {
enableHighAccuracy: true, // Request more accurate position (might use more power)
timeout: 10000, // Maximum time (ms) to wait for a position
maximumAge: 0 // Don't use a cached position, get a fresh one
});
} else {
document.getElementById('locationInfo').textContent = 'Geolocation is not supported by your browser.';
}
}

The GeolocationPositionError Object (Error Callback)

Section titled “The GeolocationPositionError Object (Error Callback)”

The optional errorCallback function receives a GeolocationPositionError object if location retrieval fails:

PropertyTypeDescription
codeNumberA numeric code representing the error type (see below).
messageStringA human-readable description of the error.

Possible error codes (error.code):

CodeConstantDescription
1PERMISSION_DENIEDThe user denied permission.
2POSITION_UNAVAILABLEThe network is down or a satellite fix cannot be obtained.
3TIMEOUTThe request timed out before a location could be determined.

The optional third argument to getCurrentPosition and watchPosition is a PositionOptions object:

PropertyTypeDefaultDescription
enableHighAccuracyBooleanfalseProvides a hint that the application prefers the most accurate possible result. This may consume more power (e.g., enable GPS) and take longer. Setting to false allows the device to save power.
timeoutNumberInfinityMaximum time in milliseconds the device is allowed to take to return a position. If it takes longer, the errorCallback is invoked with code TIMEOUT.
maximumAgeNumber0Specifies the maximum age (in milliseconds) of a cached position that the application is willing to accept. Set to 0 to force retrieval of a fresh position. Set to Infinity to accept any cached position regardless of age.
<!DOCTYPE html>
<html>
<head>
<title>Geolocation Example</title>
<style>
body { font-family: sans-serif; }
#locationInfo { margin-top: 10px; padding: 10px; border: 1px solid #ccc; background-color: #f9f9f9; }
</style>
</head>
<body>
<h1>HTML5 Geolocation</h1>
<button onclick="getLocation()">Get My Location</button>
<button onclick="watchLocation()">Watch My Location</button>
<button onclick="stopWatching()">Stop Watching</button>
<div id="locationInfo">Click 'Get My Location' or 'Watch My Location'.</div>
<script>
let watchId = null;
function handleSuccess(position) {
const latitude = position.coords.latitude;
const longitude = position.coords.longitude;
const accuracy = position.coords.accuracy;
const timestamp = new Date(position.timestamp);
console.log("Position Update:", position);
document.getElementById('locationInfo').innerHTML =
`Lat: ${latitude.toFixed(5)}, Long: ${longitude.toFixed(5)}<br>
Accuracy: ${accuracy} meters<br>
Timestamp: ${timestamp.toLocaleString()}`;
}
function handleError(error) {
let errorMessage = 'An unknown error occurred.';
// ... (error handling switch statement as above) ...
switch (error.code) {
case error.PERMISSION_DENIED:
errorMessage = "User denied the request for Geolocation.";
break;
case error.POSITION_UNAVAILABLE:
errorMessage = "Location information is unavailable.";
break;
case error.TIMEOUT:
errorMessage = "The request to get user location timed out.";
break;
case error.UNKNOWN_ERROR:
errorMessage = "An unknown error occurred.";
break;
}
console.error(`Geolocation Error (${error.code}): ${errorMessage}`);
document.getElementById('locationInfo').textContent = `Error: ${errorMessage}`;
}
const options = {
enableHighAccuracy: true,
timeout: 10000,
maximumAge: 0
};
function getLocation() {
if ('geolocation' in navigator) {
document.getElementById('locationInfo').textContent = 'Requesting location...';
navigator.geolocation.getCurrentPosition(handleSuccess, handleError, options);
} else {
document.getElementById('locationInfo').textContent = 'Geolocation is not supported.';
}
}
function watchLocation() {
if ('geolocation' in navigator) {
if (watchId) {
console.log("Already watching location.");
return;
}
document.getElementById('locationInfo').textContent = 'Watching location...';
// Start watching, store the returned ID
watchId = navigator.geolocation.watchPosition(handleSuccess, handleError, options);
console.log("Started watching location with ID:", watchId);
} else {
document.getElementById('locationInfo').textContent = 'Geolocation is not supported.';
}
}
function stopWatching() {
if (watchId !== null && 'geolocation' in navigator) {
navigator.geolocation.clearWatch(watchId);
console.log("Stopped watching location with ID:", watchId);
document.getElementById('locationInfo').textContent = 'Stopped watching location.';
watchId = null;
} else {
console.log("Not currently watching location.");
}
}
</script>
</body>
</html>