HTML5 Geolocation API allows you to request geolocation data including longitude, latitude, altitude, speed & direction of travel allowing you to create powerful & useful applications for your users.
Are you unable to retrieve your location? This could be due to your browser security settings or a known issue with embedded iframes when using Chrome. If you experience this, please try the demo directly on CodePen.
Step-by-Step Guide to HTML5 Geolocation
Everyone on Earth has a position specified by a geographic coordinate system of latitude, longitude and altitude. The HTML5 Geolocation API is able to retrieve this information upon the user’s consent. Here’s how it works:
- A user visits a site that has the HTML5 geolocation implemented
- The site checks if the user’s browser supports geolocation (e.g.
navigator.geolocation
) - If supported, the browser requests the user’s permission to access their location
- Once permission is granted, the
navigator.geolocation.getCurrentPosition
method is able to return the user’s longitude, heading, speed, altitude, accuracy and altitude accuracy.
You can also retrieve a user’s approximate address when used in conjunction with a geolocation service like Google (see the example below). This allows developers the ability build super useful apps for its users:
- Showing user’s location on a map especially in an unfamiliar area
- Provide turn-by-turn navigation while driving
- Finding points of interest in a user’s vicinity
- Getting the latest weather or news of a user’s area
- Tagging the location of picture or video
- Location tracking for a fleet of delivery trucks
Take a look at a basic example of the HTML5 geolocation API:
function geolocate() { function success(position) { console.log("Latitude: " + position.coords.latitude); console.log("Longitude: " + position.coords.longitude); console.log("Speed: " + position.coords.speed); console.log("Heading: " + position.coords.heading); console.log("Altitude: " + position.coords.altitude); console.log("Accuracy: " + position.coords.accuracy); console.log("Altitude Accuracy: " + position.coords.altitudeAccuracy); } function error() { console.log("Unable to retrieve your location."); } if (navigator.geolocation) { navigator.geolocation.getCurrentPosition(success, error); } else { console.log("Geolocation is not supported by your browser."); } }
Browser Geolocation and How It Works
The HTML5 Geolocation API is used to get the geographical position of a user. Unfortunately, since this can compromise user privacy, the position is not available unless the user approves it. W3C has developed a set of APIs to effectively allow the user or client-side device to retrieve geographic positioning information with JavaScript.
HTML5 geolocation is slowly finding its way to the mainstream applications. In the past two years, there’s been an explosion in geolocation based tools. Google Maps is a great example of this. They fully support geolocation in all major browsers. See a current list of supported browsers and devices below.
HTML5 Geolocation Supported Devices
- Firefox 3.5+
- Chrome 5+
- iPhone Safari
- Opera 10.6+
- Opera Mobile 10.1+
- Safari 5+
- iPhone 3.0+
- Android 2.0+
- Internet Explorer 9+
- Symbian (S60 3rd & 5th generation)
- Palm WebOS 2.0+
- Blackberry OS 6
- Maemo

If you’re interested in the HTML5 Geolocation API specs, you can read W3C’s Geolocation API Specification. If you just skim through it, an important section to pay attention to is section 6.2.8 titled: “The geolocation API must be agnostic to the underlying sources of location information“. Basically, it’s saying that the underlying technology on the device may achieve geolocation via either GPS, cell tower triangulation or possibly other techniques. The down side here is the geolocation API won’t identify how that location was determined. That’s usually not going to be a problem, but you’ll notice the accuracy of the location may vary greatly depending on which technique was used.
Geolocation Sources
Desktop browsers are most likely to use WiFi which is accurate up to 20m or IP-based geolocation which is what most people are used to (though this method can provide false positives). Mobile devices tend to use triangulation techniques such as GPS which is accurate up to 10m. WiFi and GSM/CDMA cell IDs are accurate up to 1000m.
Protecting Your Data
Is big brother really watching? In W3C’s specification, it says that since the API exposes the user’s location it therefore could compromise their privacy. To combat this, W3C says the user’s permission must be obtained first before any geolocation information is given. I know that doesn’t give the conspiracy theorist out there peace of mind—but then again, will anything really? The browser will take care of this by displaying a message as either a pop-up box or at the top of the browser (implementation is browser specific) requesting the user’s permission.
How the HTML5 Geolocation API Works
Luckily, once you understand how to geolocation API works, it’s a cinch to implement it. With the HTML5 Geolocation API, you must use asynchronous functions. Big word, I know and if you don’t know what it means, I’ll try to explain it to you below. But before that, you’ll first need to know if user’s browser supports the API.
Checking for Browser Support
It’s always a good idea to check if a user’s environment supports features like the geolocation API. Luckily the API provides a function for this which can be called doing the following:
if ( navigator.geolocation ) { // do fancy stuff }
If it returns false, you should probably tell the user that they’re browsers blows and they shouldn’t be allowed near a computer… not (But if you do, I’d love to see it). If you’re already using Modernizr, you can also use it to check for geolocation device support:
if ( Modernizr.geolocation ) { // do fancy stuff }
How Asynchronous Functions Work
So what’s an asynchronous function? It’s a function that is executed outside of the main program flow. In the context of JavaScript, it means our code will call a function and then continue to execute statements before the function returns. So basically it allows you to run other functions before your function is completed.
An Asynchronous function is one that is executed outside of the main program flow.
When we follow this model, our code should look something similar to this:
// The function we want to call. do_something( handle_response_to_do_something ); // The function that will handle the response of the above function call. function handle_response_to_do_something( response ) { alert( response ); }
Since the response to do_something()
function is given to us asynchronously, we must choose a function that will receive a response and use it. In this case, we must define another function, handle_response_to_do_something()
, that will display the result in a dialog box.
So why do we need to use asynchronous functions when using the HTML5 Geolocation API? Well, when our application tries to query its location, the user of the device must first agree to share their location with our application. If we didn’t make this action a asynchronous one, then everything inside the browser would freeze until the user responds; not exactly user-friendly.
How to Use the getCurrentPosition
API
Now let’s dig into the geolocation API. The first API we’re going to work with is the getCurrentPosition()
API. When that function is called, it must immediately return and then asynchronously acquire a new Position object. If it worked, this method must call it’s associated successCallback
argument with a Position
object as an argument. If it fails and the method was invoked with a non-null errorCallback
argument, this method must invoke the errorCallback with a PositionError
object as an argument.
I’m going to assume that you already know how to create an HTML document so I’m not going to walk you through the process as if you were in kindergarten. In our example, we have a basic HTML document with the HTML5 doctype defined using the latest version of jQuery. On the page we’ll put a button the user can click on to grab their location information using the HTML5 Geolocation API.
Step 1: Create the action button
<input id="find-me" type="button" value="Find my location" />
Simple.
Step 2: Build the JS functions to get the user’s information
Now we’re going to build the functions the button we created will call when it get’s clicked on.
$( function() { $( "#find-me" ).live( "click", function( e ) { e.preventDefault(); find_me(); }); }); function find_me() { if ( navigator && navigator.geolocation ) { navigator.geolocation.getCurrentPosition( geo_success, geo_error ); } else { alert( "Your browser sucks balls and so do you!" "); } } function geo_success( position ) { printLatLong( position.coords.latitude, position.coords.longitude ); } // The PositionError object returned contains the following attributes: // code: a numeric response code // PERMISSION_DENIED = 1 // POSITION_UNAVAILABLE = 2 // TIMEOUT = 3 // message: Primarily for debugging. It's recommended not to show this error // to users. function geo_error( err ) { if ( err.code == 1 ) { error( "The user denied the request for location information." ) } else if ( err.code == 2 ) { error( "Your location information is unavailable." ) } else if ( err.code == 3 ) { error( "The request to get your location timed out." ) } else { error( "An unknown error occurred while requesting your location." ) } } // Output lat and long. function printLatLong( lat, long ) { $( "body" ).append( "Lat: "" + lat ); $( "body" ).append( "Long: "" + long ); } function error( msg ) { alert( msg ); }
The markup above listens to when the button is clicked and then calls the find_me()
function. Next, it determines if the user’s browser supports the HTML5 Geolocation API feature natively. If it does, we can call the getCurrentPosition()
method. Since this method executes asynchronously, pass it two callback functions: geo_success
and geo_error
.The error callback is passed a position error object that contains a code and a message property. Here’s a list of the possible messages:
- Unknown
- Permission Denied
- Position Unavailable
- Timeout
The success callback is passed a position object that contains a coordinates object and a timestamp. The coordinates object contains the following:
latitude
, which is specified in decimal degreeslongitude
, which is specified in decimal degreesaltitude
, which is specified in meters above the ellipsoidaccuracy
, which is specified in metersaltitudeAccuracy
, which is specified in metersheading
, which is the direction of travel specified in degreesspeed
, which is specified in meters per second
Of those seven, only three are guaranteed to be there: latitude, longitude, and accuracy.
Step 3: Run the Code!
Once you run the code above, assuming it’s in a browser that supports geolocation, you should see your latitude and longitude coordinates displayed to you. This all goes to plan if the user has agreed to share their location information, but what if they don’t want to share that information? Or what if something went wrong trying to get that information? Wouldn’t it be nice to be notified of the problem? You can.
Our code can detect HTML5 geolocation issues by calling the geo_error()
function. In the code above, geo_error()
takes the error argument. With this information we can check for the kind of error that’s occurred. Usually, the browser will identify one of the following three errors as the cause:
- User chose to not share location data
- Device was unable to obtain position data
- Device timed out while waiting to retrieve position data
How to Use the watchPosition
and clearWatch
APIs
We’ve learned how to use the getCurrentPosition
API, now let’s quickly look at the watchPosition
API. When this function is called, it must immediately return and then asynchronously start a watch process defined by the following steps:
- Acquire a new Position object. If successful, invoke the associated successCallback with a Position object as an argument. If the attempt fails, and the method was invoked with a non-null errorCallback argument, this method must invoke the errorCallback with a PositionError object as an argument.
- Invoke the appropriate callback with a new Position object every time the implementation determines that the position of the hosting device has changed.
This method will return an integer value that uniquely identifies the watch process. When the clearWatch()
function is called with this identifier, the watch process will stop acquiring any new position fixes and will cease invoking any callbacks. So in other words this API enables our code to repeatedly receive location information as the device location changes.
Step 1: Create the scaffolding
<script src="js/jquery-1.4.2.min.js"></script> <script>// <![CDATA[ jQuery(window).ready(function(){ jQuery("#btnInit").click(initiate_watchlocation); jQuery("#btnStop").click(stop_watchlocation); }); var watchProcess = null; function initiate_watchlocation() { } function stop_watchlocation() { } function handle_errors(error) { switch(error.code) { case error.PERMISSION_DENIED: alert("user did not share geolocation data"); break; case error.POSITION_UNAVAILABLE: alert("could not detect current position"); break; case error.TIMEOUT: alert("retrieving position timedout"); break; default: alert("unknown error"); break; } } function handle_geolocation_query(position) { } // ]]></script> <button id="btnInit">Monitor my location</button> <button id="btnStop">Stop monitoring</button> <div id="”info”"></div>[/code_highlight]
So what’s new in the code above? Well, first we have added a new button to allow us to stop the watch process with the stop_watchlocation() function to handle its click. We also have a watchProcess variable to keep track of the watch process.
Step 2: Add code to call the watchPosition()
API
To start the process we need to add the code that calls the watchPosition() API like the code below:
function initiate_watchlocation() { if ( watchProcess == null ) { watchProcess = navigator.geolocation.watchPosition( handle_geolocation_query, handle_errors ); } }
Step 3: Add code to call the clearWatch()
API
To stop the process we need to add the code that calls the clearWatch() API like the code below:
function stop_watchlocation() { if ( watchProcess != null ) { navigator.geolocation.clearWatch( watchProcess ); watchProcess = null; } }
Step 4: Display the geolocation data
Finally, we handle displaying the geoposition data like this:
function handle_geolocation_query( position ) { var text = "Latitude: " + position.coords.latitude + "<br />"; text += "Longitude: " + position.coords.longitude + "<br />"; text += "Accuracy: " + position.coords.accuracy + "m<br />"; text += "Time: " + new Date( position.timestamp ); jQuery( "#info" ).html( text ); }
What’s in Geolocation Data
Inspecting what we receive from the geolocation API will give us the coords and timestamp fields. The timestamp field simply denotes the time at which the instance of geolocation data was created. The coords attribute contains a set of geographic coordinates together with their associated accuracy as well as a set of other optional attributes such as altitude and speed. Per W3C specs:
- The latitude and longitude attributes are geographic coordinates specified in decimal degrees.
- The accuracy attribute denotes the accuracy level of the latitude and longitude coordinates. It is specified in meters and must be supported by all implementations.
- The altitude attribute denotes the height of the position, specified in meters above the WGS84 ellipsoid. If the implementation cannot provide altitude information, the value of this attribute must be null.
- The altitudeAccuracy attribute is specified in meters. If the implementation cannot provide altitude information, the value of this attribute must be null.
- The heading attribute denotes the direction of travel of the hosting device and is specified in degrees counting clockwise relative to the true north. If the implementation cannot provide heading information, the value of this attribute must be null.
- The speed attribute denotes the current ground speed of the hosting device and is specified in meters per second. If the implementation cannot provide speed information, the value of this attribute must be null.
Data for some of these fields may not be available depending on the target device.
Getting Geolocation Data with a Fallback
What happens if something goes wrong when attempting to get your user’s geolocation data? Don’t worry, there’s fallback options available. You can still get your user’s geolocation, it just won’t be as accurate. You can perform an IP-to-location lookup as a fallback using an external geolocation service. It’s certainly not as accurate as latitude and longitude coordinates, but it’s far better than not having any location data at all. These services are better than you just using PHP to get the user’s IP address because they do their best to map the IP of a device to the geographic location using large geolocation databases. There’s still some downsides though:
- IP addresses may be associated with the wrong location (e.g., the wrong postal code, city or suburb within a metropolitan area).
- Addresses may be associated only with a very broad geographic area (e.g., a large city, or a state). Many addresses are associated only with a city, not with a street address or latitude/longitude location.
- Some addresses will not appear in the database and therefore cannot be mapped (often true for IP numbers not commonly used on the Internet).
- The important thing to remember is that when an external geolocation service is used, the accuracy is not as good as geolocation native to the device, and in some scenarios it may be completely off. Additionally, such services do not provide any information regarding the altitude, speed or heading of the device. Regardless, when GPS or triangulation are not available, they are a good fallback.
3rd Party Geolocation Services
- Google offers the
google.loader.ClientLocation
object in it’s Google Maps API, but at last check, doesn’t work for many US IP addresses. - The MaxMind GeoIP JavaScript Web Service seems more accurate and up-to-date. Also, it’s free as long as you link back to their website. Alternatively, MaxMind offers a JavaScript attribution-free license that can be purchased for $250/year.
- geoPositon.js is an open source, MIT-licensed JavaScript library that smooths over the differences between the W3C geolocation API, IP geolocation services, and the APIs provided by mobile platforms.
Coding the Fallback Solution
Now let’s get into actually coding a fallback solution. I’m going to show you how to do it using Yahoo’s library and MaxMind. I’m not going to include Google’s since currently it doesn’t work for many US IP addresses or geoPositon.js because it’s not really a fallback, more of an alternative.
MaxMind’s Geolocation Fallback Solution
Whoops, couldn’t get your location, never fear MaxMind is here. Let’s start by modifying our previous code to use MaxMind as a fallback. First, you’ll need to add the JavaScript library to the page.
<script src="https://j.maxmind.com/app/geoip.js"></script>
Next, add the MaxMind fallback:
$(document).ready(function () { // wire up button click $('#go').click(function () { // test for presence of geolocation if (navigator && navigator.geolocation) { // make the request for the user's position navigator.geolocation.getCurrentPosition(geo_success, geo_error); } else { // use MaxMind IP to location API fallback printLatLong(geoip_latitude(), geoip_longitude(), true); } }); }); // output lat and long function printLatLong(latitude, longitude, isMaxMind) { $('body').append(' Lat: ' + latitude + ' '); $('body').append(' Long: ' + longitude + ' '); // if we used MaxMind for location, add attribution link if (isMaxMind) { $('body').append('<a href="http://www.maxmind.com" target="_blank">IP to Location Service Provided by MaxMind</a>'); } } function geo_error(err) { // instead of displaying an error, fall back to MaxMind IP to location library printLatLong(geoip_latitude(), geoip_longitude(), true); }
When calling printLatLong()
using MaxMind, pass in an extra true parameter.
A Closer Look
When navigator errors and you’re unable to get the user’s location, instead of showing an error, use the geoip_latitude()
and geoip_longitude()
functions that MaxMind’s JS library provides. Looking at the source of the MaxMind geoip.js
file, you’ll notice that it’s already translated your IP address into location data. MaxMind create a dynamic JS file by reading the IP address that made the HTTP request, doing the IP-to-location translation on the server side and then outputting the results. In addition to latitude and longitude, the location data shown below is also available:
geoip_country_code()
, Country Codegeoip_country_name()
, Country Namegeoip_city()
, Citygeoip_region_name()
, Regiongeoip_postal_code()
, Postal Codegeoip_area_code()
, Telephone Area Codegeoip_metro_code()
, Metro Code
An advantage to using MaxMind to a fallback is it’s free as long as you give them attribution in the form of a back link to their website. Depending on your project, if the browser fails to get the user’s location and you end up using MaxMind, you could comply with their usage terms by doing the following using the example above:
function printLatLong( latitude, longitude, isMaxMind ) { $( "body" ).append( "Lat: " + latitude ); $( "body" ).append( "Long: ' + longitude ); // If we used MaxMind for location, add attribution link. if ( isMaxMind ) { $( "body" ).append( '<a href="http://www.maxmind.com" target="_blank">IP to Location Service Provided by MaxMind</a>' ); } }
See also
MaxMind provides free/open source geolocation solutions for city, country, and IP lookups at www.maxmind.com/app/ip-location.
YQL Geo Library Fallback Solution
Another fallback option you have when the browser fails to get the user’s geolocation data is YQL Geo Library. This library can do other things which I’ll leave to you to discover, but for now let’s look at how we should modify our code to successfully detect the location on both supporting and non-supporting browsers. First, we need to add the JS:
<script src="//code.jquery.com/jquery-2.1.4.min.js"></script> <script src="js/yqlgeo.js"></script>
Then code the geolocation methods:
;( function( $ ) { "use strict"; $( function() { function initiate_geolocation() { if ( navigator.geolocation ) { navigator.geolocation.getCurrentPosition( handle_geolocation_query, handle_errors ); } else { yqlgeo.get( "visitor", normalize_yql_response ); } } function handle_errors( error ) { switch( error.code ) { case error.PERMISSION_DENIED: alert( "User did not share geolocation data." ); break; case error.POSITION_UNAVAILABLE: alert( "Could not detect current position." ); break; case error.TIMEOUT: alert( "Retrieving position timed out." ); break; default: alert( "Unknown error." ); break; } } function normalize_yql_response( response ) { if ( response.error ) { var error = { code : 0 }; handle_error( error ); return; } var position = { coords: { latitude : response.place.centroid.latitude, longitude : response.place.centroid.longitude }, address: { city : response.place.locality2.content, region : response.place.admin1.content, country : response.place.country.content } }; handle_geolocation_query( position ); } function handle_geolocation_query( position ) { alert( "Lat: "" + position.coords.latitude + " " + "Lon: " + position.coords.longitude ); } // Click handler for the button. $( "#btnInit" ).click( initiate_geolocation ); }); })( jQuery );
So what’s going on in the markup above?
- We are importing the YQL Geolocation Library into the page
- Inside the initiate_geolocation() function, the code checks to make sure geolocation is natively supported. If not it makes use of the YQL Geolocation Library.
- Finally we’ve defined the normalize_yql_response(response) function to turn the result of the YQL Geolocation Library into an output format similar to the W3C geolocation API specs.
In Conclusion
After reading though this guide, hopefully you now understand the HTML5 Geolocation API, how to use it and implement it in your next project. Your imagination truely is the limit with what you can build. For example, imagine how useful your site could be if it provided online timetables for all public transportation in a particular city. Using geolocation, the site could recommend optimal travel routes to get people where they’re going as quickly as possible. Desktop users could get their start location sorted by proximity to their computer. Mobile users trying to get home after a night out could quickly find the closest bus stop within walking distance. These possibilities are limitless.
HTML5 Geolocation Real-World Scenarios
Here’s just a few example that show how a website might implement the HTML5 Geolocation API. Keep in mind, it’s the small things on a site that make a huge difference. Some of these may seem obvious, but can make a huge difference in the user’s experience.
- Public transportation sites can list nearby bus stops and metro locations.
- Late night out? Taxi or car service Web sites can find where you are, even if you don’t know.
- Shopping sites can immediately provide estimates for shipping costs.
- Travel agencies can provide better vacation tips for current location and season.
- Content sites can more accurately determine the language and dialect of search queries.
- Real estate sites can present average house prices in a particular area, a handy tool when you’re driving around to check out a neighborhood or visit open houses.
- Movie theater sites can promote films playing nearby.
- Online games can blend reality into the game play by giving users missions to accomplish in the real world.
- News sites can include customized local headlines and weather on their front page.
- Online stores can inform whether products are in stock at local retailers.
- Sports and entertainment ticket sales sites can promote upcoming games and shows nearby.
- Job postings can automatically include potential commute times.
HTML5 Geolocation Application Tutorials & Demos
Frequently Asked Questions
I don’t want people knowing my location! Can I turn it off?
Privacy is an obvious concern when you’re talking about sharing your physical location with a remote web server. The geolocation API explicitly states: User Agents must not send location information to Web sites without the express permission of the user.
In other words, sharing your location is always opt-in. If you don’t want to, you don’t have to.
Does the geolocation API work on the International Space Station, on the moon, or on other planets?
The geolocation specification states, The geographic coordinate reference system used by the attributes in this interface is the World Geodetic System (2d) [WGS84]. No other reference system is supported.
The International Space Station is orbiting Earth, so astronauts on the station can describe their location by latitude, longitude, and altitude. However, the World Geodetic System is Earth-centric, so it can’t be used to describe locations on the moon or on other planets.
What about Internet Explorer?
Prior to version 9 (technically 9.0RC1), Internet Explorer did not support the W3C geolocation API. But no worries! Like I described above, there’s JS fallback options you can use. It’s not quite the same as the W3C geolocation API, but it serves the same purpose.
While we’re on the subject of legacy platforms, I should point out that many older mobile phone platforms had their own device-specific geolocation APIs. BlackBerry, Nokia, Palm, and OMTP BONDI all provide their own geolocation APIs. Of course, they all work differently which in turn works differently from the W3C geolocation API.
Additional Resources
- W3C geolocation API
- geoPosition.js, a geolocation API wrapper script
- Internet Explorer 9 Guide for Developers: Geolocation
1 comment on “HTML5 Geolocation API — A Simple & Comprehensive Guide”.
# May 31, 2017
Hi Ben,
Thank you for the article – The maxmind fall back however is not working for me. do they still offer the free service in exchange for displaying their URL , or is there something I’m doing wrong perhaps ?
Any advice / help would be great
All comments posted on 'HTML5 Geolocation API — A Simple & Comprehensive Guide' are held for moderation and only published when on topic and not rude. Get a gold star if you actually read & follow these rules.
You may write comments in Markdown. This is the best way to post any code, inline like `<div>this</div>` or multiline blocks within triple backtick fences (```) with double new lines before and after.
Want to tell me something privately, like pointing out a typo or stuff like that? Contact Me.