A “Use my location” button can save someone from typing an address, searching for a place, or copying coordinates from another app.
For a map application, it is also a useful starting point: get the user's latitude and longitude, then use those coordinates to show a marker, look up an address, or search for nearby places.
In this tutorial, we will build a small browser example that requests location after a button click, displays the result, handles common errors, and creates a link to open the coordinates in Google Maps.
Start with the browser's Geolocation API
The Geolocation API is available through navigator.geolocation. For a single location request, use getCurrentPosition().
It accepts a success callback, an error callback, and an optional configuration object:
navigator.geolocation.getCurrentPosition(
(position) => {
const { latitude, longitude } = position.coords;
console.log({ latitude, longitude });
},
(error) => {
console.error(error.code, error.message);
},
{
enableHighAccuracy: true,
timeout: 10000,
maximumAge: 0,
}
);
The call is asynchronous. The coordinates arrive in the success callback; they are not the method's return value.
For a deployed website, use HTTPS. The user must allow location access, and a site's Permissions Policy can also block the feature. Local development on http://localhost is generally treated as a potentially trustworthy origin.
Build a complete example
Save the following as index.html, then serve it through localhost or HTTPS.
The page requests location only when the user clicks the button. It disables the button while the request is pending and shows a readable message if the request fails.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Find My Current Coordinates</title>
</head>
<body>
<main>
<h1>Find My Current Coordinates</h1>
<p>Allow location access to see your latitude and longitude.</p>
<button id="locate" type="button">Use my location</button>
<p id="status" role="status" aria-live="polite"></p>
<section id="result" hidden>
<h2>Your reported location</h2>
<dl>
<dt>Latitude</dt>
<dd id="latitude"></dd>
<dt>Longitude</dt>
<dd id="longitude"></dd>
<dt>Estimated accuracy radius</dt>
<dd id="accuracy"></dd>
<dt>Position timestamp</dt>
<dd id="timestamp"></dd>
</dl>
<a id="map-link" target="_blank" rel="noopener noreferrer">
Open in Google Maps
</a>
</section>
</main>
<script>
const button = document.querySelector("#locate");
const status = document.querySelector("#status");
const result = document.querySelector("#result");
const mapLink = document.querySelector("#map-link");
const errorMessages = {
1: "Location access was denied or blocked. Check site permissions, or enter coordinates manually.",
2: "Your device could not determine a position. Check location services and try again.",
3: "The location request timed out. Try again, or enter coordinates manually.",
};
button.addEventListener("click", () => {
result.hidden = true;
mapLink.removeAttribute("href");
if (!window.isSecureContext) {
status.textContent = "Open this page over HTTPS or on localhost.";
return;
}
if (!navigator.geolocation) {
status.textContent = "Geolocation is unavailable in this browser.";
return;
}
button.disabled = true;
status.textContent = "Requesting your location. Please respond to any permission prompt.";
navigator.geolocation.getCurrentPosition(
(position) => {
const { latitude, longitude, accuracy } = position.coords;
document.querySelector("#latitude").textContent = latitude.toFixed(6);
document.querySelector("#longitude").textContent = longitude.toFixed(6);
document.querySelector("#accuracy").textContent = `${Math.round(accuracy)} meters`;
document.querySelector("#timestamp").textContent =
new Date(position.timestamp).toLocaleString();
const url = new URL("https://www.google.com/maps/search/");
url.searchParams.set("api", "1");
url.searchParams.set("query", `${latitude},${longitude}`);
mapLink.href = url.toString();
result.hidden = false;
status.textContent = "Location received. Check the accuracy estimate before using it.";
button.disabled = false;
},
(error) => {
status.textContent =
errorMessages[error.code] || "Unable to get your location. Please try again.";
button.disabled = false;
},
{
enableHighAccuracy: true,
timeout: 10000,
maximumAge: 0,
}
);
});
</script>
</body>
</html>
For example, if you have Python installed, start a local server from the folder containing the file:
python -m http.server 8000
Then open http://localhost:8000. Opening the file through a local server gives you a more predictable development setup than relying on file:// behavior.
This example displays the coordinates without uploading them to an application server. Clicking the Google Maps link sends the coordinates to Google Maps in the URL.
Choose options for your use case
The configuration above favors a fresh result and requests better accuracy. Those choices may be appropriate for placing someone on a map, but they are not the best settings for every feature.
| Option | Example value | Purpose |
|---|---|---|
enableHighAccuracy |
true |
Request better accuracy, potentially at the cost of more time and power |
timeout |
10000 |
Limit position acquisition time to 10 seconds |
maximumAge |
0 |
Require a fresh position rather than accepting a cached result |
The acquisition timeout does not include time spent waiting for permission or for the document to become visible. A user who leaves the permission prompt unanswered can therefore wait longer than ten seconds.
For a nearby-city feature, consider allowing a recent cached position:
const options = {
enableHighAccuracy: false,
timeout: 10000,
maximumAge: 60000,
};
That allows the browser to reuse a position up to one minute old. Pick the settings based on how current and precise the result needs to be.
See the getCurrentPosition documentation and W3C Geolocation specification for the option definitions.
Show accuracy alongside the coordinates
A coordinate pair can look precise even when the underlying position is uncertain.
For example, displaying six decimal places does not prove that the device knows its position to that level of accuracy. In our example, toFixed(6) controls the presentation only.
The accuracy property reports a horizontal accuracy estimate in meters, specified at a 95% confidence level.
A reported radius of 20 meters and a reported radius of 2,000 meters should lead to different interface decisions. With the larger radius, a map can show a broader area and let the user adjust the location.
Browser geolocation also does not guarantee a GPS reading. The device and browser choose the available positioning sources. Treat the result as a reported position with an accuracy estimate.
Put the location on a MapLibre map
If your application already has an initialized MapLibre GL JS map, you can add a marker from the success callback.
Assume maplibregl is available and map refers to your map instance. Declare the marker variable once, outside the callback:
let userMarker;
// Call this from the geolocation success callback.
function showUserLocation(position) {
const { latitude, longitude } = position.coords;
// MapLibre expects longitude first.
const lngLat = [longitude, latitude];
if (userMarker) {
userMarker.setLngLat(lngLat);
} else {
userMarker = new maplibregl.Marker()
.setLngLat(lngLat)
.addTo(map);
}
map.setCenter(lngLat);
}
Updating the existing marker prevents repeated button clicks from creating duplicate markers.
Pay attention to coordinate order. The Google Maps search query in our HTML example uses latitude,longitude; MapLibre uses [longitude, latitude]. The MapLibre Marker documentation describes its setLngLat() method.
Handle errors as part of the interface
The GeolocationPositionError codes identify three common failure cases:
| Code | Name | Useful response |
|---|---|---|
1 |
PERMISSION_DENIED |
Explain that access was denied or blocked; offer manual input |
2 |
POSITION_UNAVAILABLE |
Suggest checking device location services and trying again |
3 |
TIMEOUT |
Offer a retry and another way to choose a location |
Permission denial does not always mean the user clicked “Block” just now. Access may already have been denied or prevented by a policy.
Avoid retrying automatically after denial. Leave the person in control and provide an alternative, such as address search, coordinate input, or selecting a point on the map.
Try the workflow in a map tool
I built CoordMap's My Location tool around this workflow: start with an approximate IP location, then let the user request device location with the Use Precise Location button.
You can view the coordinates, copy them, and open the location in Google Maps. The page also supports searching for a place or entering coordinates manually.
IP location and device location can differ. An IP result is an approximate starting point, and it should be labeled separately from a position reported by the browser.
Use the coordinates for the next step
Once you have latitude and longitude, decide what the person needs to do next.
An address lookup needs reverse geocoding. A nearby-place search needs a search radius. A map marker needs the coordinate order expected by the mapping library.
For a “Use my location” feature, a useful first version is small: an explicit button, a position with its accuracy estimate, a map action, and a clear alternative when location is unavailable.
Top comments (0)