The browser exposes a navigator.geolocation
object, through which we’ll do all the geolocation operations.
It’s only available on pages served using HTTPS, for security purposes, and it’s available on all modern browsers.
navigator.geolocation
Since
window
is the global object, we can accessnavigator
without specifyingwindow.navigator
The window.navigator
property exposed by browsers points to a Navigator object which is a container object that makes a lot of Web Platform APIs available to us.
The geolocation
object provides the following methods:
getCurrentPosition()
watchPosition()
clearWatch()
The first one is used to get the current position coordinates. When we call this method for the first time, the browser automatically asks the user for the permission to share this information to us.
This is how this interface looks in Chrome:
on Firefox:
and on Safari:
This needs to be done only once per origin. You can change the decision you made, and revert a permission decision. This is how you do so with Chrome, by clicking the lock icon near the domain:
Once this permission is granted, we can proceed.
Getting the user’s position
Let’s start with this sample code:
navigator.geolocation.getCurrentPosition(() => {})
The permission panel should appear. Allow the permission.
Notice how I passed an empty arrow function, because the function wants a callback function.
This function is passed a Position
object, which contains the actual location:
navigator.geolocation.getCurrentPosition(position => {
console.log(position)
})
This object has 2 properties:
coords
, aCoordinates
objecttimestamp
, the UNIX timestamp when the position was retrieved
The Coordinates
object comes with several properties that define the location:
accuracy
the accuracy of the position measured, expressed in metersaltitude
the altitude value measuredaltitudeAccuracy
the accuracy of the altitude measured, expressed in metersheading
the direction towards which the device is traveling. Expressed in degrees (0 = North, East = 90, South = 180, West = 270)latitude
the latitude value measuredlongitude
the longitude value measuredspeed
the speed at which the device is traveling, expressed in meters per second
Depending on the implementation and the device, some of those will be null
. For example on Chrome running on my MacBook Air I only got values for accuracy
, latitude
and longitude
.
navigator.geolocation.getCurrentPosition(position => {
console.log(position.coords.latitude)
console.log(position.coords.longitude)
})
Watching the position for changes
In addition to getting the user position once, which you can do using getCurrentPosition()
, you can use the watchPosition()
method of navigator.geolocation
to register a callback function that will be called upon each and every change that the device will communicate to us.
Usage:
navigator.geolocation.watchPosition(position => {
console.log(position)
})
Of course the browser will ask for the permission also with this method, if it was not already granted.
We can stop watching for a position by calling the navigator.geolocation.clearWatch()
method, passing it the id
returned by watchPosition()
:
const id = navigator.geolocation.watchPosition(position => {
console.log(position)
})
//stop watching after 10 seconds
setTimeout(() => {
navigator.geolocation.clearWatch(id)
}, 10 * 1000)
If the user denies the permission
Remember the permission popup window the browser shows when we call one of the methods to get the position?
If the user denies that, we can intercept this scenario by adding an error handling function, as the second parameter to the methods getCurrentPosition()
and watchPosition()
.
navigator.geolocation.getCurrentPosition(position => {
console.log(position)
}, error => {
console.error(error)
})
The object passed to the second parameter contains a code
property to distinguish between error types:
1
means permission denied2
means position unavailable3
means timeout
Adding more options
When I talked about errors previously, I mentioned the timeout error. Looking up the position can take some time and we can set a maximum time allowed to perform the operation, as an option.
You can add a timeout by adding a third parameter to the methods getCurrentPosition()
and watchPosition()
, an object.
navigator.geolocation.getCurrentPosition(position => {
console.log(position)
}, error => {
console.error(error)
}, {
})
Inside this object we can pass the properties
timeout
to set the number of milliseconds before the request errors outmaximumAge
to set the maximum “age” of the position cached by the browser. We don’t accept one older than the set amount of millisecondsenableHighAccuracy
a boolean by defaultfalse
, requires a position with the highest level of accuracy possible (which might take more time and more power)
Example usage:
navigator.geolocation.getCurrentPosition(position => {
console.log(position)
}, error => {
console.error(error)
}, {
timeout: 1000,
maximumAge: 10000,
enableHighAccuracy: true
})
Download my free JavaScript Beginner's Handbook
More browser tutorials:
- Some useful tricks available in HTML5
- How I made a CMS-based website work offline
- The Complete Guide to Progressive Web Apps
- The Fetch API
- The Push API Guide
- The Channel Messaging API
- Service Workers Tutorial
- The Cache API Guide
- The Notification API Guide
- Dive into IndexedDB
- The Selectors API: querySelector and querySelectorAll
- Efficiently load JavaScript with defer and async
- The Document Object Model (DOM)
- The Web Storage API: local storage and session storage
- Learn how HTTP Cookies work
- The History API
- The WebP Image Format
- XMLHttpRequest (XHR)
- An in-depth SVG tutorial
- What are Data URLs
- Roadmap to learn the Web Platform
- CORS, Cross-Origin Resource Sharing
- Web Workers
- The requestAnimationFrame() guide
- What is the Doctype
- Working with the DevTools Console and the Console API
- The Speech Synthesis API
- How to wait for the DOM ready event in plain JavaScript
- How to add a class to a DOM element
- How to loop over DOM elements from querySelectorAll
- How to remove a class from a DOM element
- How to check if a DOM element has a class
- How to change a DOM node value
- How to add a click event to a list of DOM elements returned from querySelectorAll
- WebRTC, the Real Time Web API
- How to get the scroll position of an element in JavaScript
- How to replace a DOM element
- How to only accept images in an input file field
- Why use a preview version of a browser?
- The Blob Object
- The File Object
- The FileReader Object
- The FileList Object
- ArrayBuffer
- ArrayBufferView
- The URL Object
- Typed Arrays
- The DataView Object
- The BroadcastChannel API
- The Streams API
- The FormData Object
- The Navigator Object
- How to use the Geolocation API
- How to use getUserMedia()
- How to use the Drag and Drop API
- How to work with scrolling on Web Pages
- Handling forms in JavaScript
- Keyboard events
- Mouse events
- Touch events
- How to remove all children from a DOM element
- How to create an HTML attribute using vanilla Javascript
- How to check if a checkbox is checked using JavaScript?
- How to copy to the clipboard using JavaScript
- How to disable a button using JavaScript
- How to make a page editable in the browser
- How to get query string values in JavaScript with URLSearchParams
- How to remove all CSS from a page at once
- How to use insertAdjacentHTML
- Safari, warn before quitting
- How to add an image to the DOM using JavaScript
- How to reset a form
- How to use Google Fonts