getCurrentPosition in JS does not work on iOS

iOS and macOS doesn't give you the user's location if they don't allow it or if the system can not trust you. So:

- First (Probably your answer)

It works with the exact code you provided ONLY IF the host (aka the origin) is using https. That is the cause of permission alert not showing up due to your comment to an answer below.

Remember if you not use https, it will be stuck for about a minute and then returns an error about authentication failure. Use error to check that:

navigator.geolocation.getCurrentPosition(success, error, options)

It will tell you something like this:

[blocked] Access to geolocation was blocked over insecure connection to http://example.com.

Tip: You can refresh the page after you requested the location to skip the waiting process. But don't forget to check the Preserve Log option in the inspector.

- Second:

If you are using https, then check your location settings for Safari, which might have been set to OFF somehow, you can change it here: Settings > Privacy > Location Services > Safari. This is not the default option, but maybe you changed it accidentally. So don't worry about the users if this was the issue. And if you use Chrome or any other third party browsers, head to its settings and check for location access. It's not there by default and appears only if location wanted at least once.

- Third:

If you are about to load your web inside an app using webView, make sure to add location permission descriptions to the info.plist file. Add NSLocationWhenInUseUsageDescription versus NSLocationAlwaysUsageDescription versus NSLocationUsageDescription as your needs.

For the sake of completeness, on iOS13, you can not get always permission. But this is not the point here and the point is you have to get the required permissions sometime before you need to get the location from GPS or it is not going to work at all.


You need to check three things

Here's what you need to check to understand why your procedure does not have access to the user's location. Your code should ensure these three things:

  1. The user's Operating System has location services enabled.
  2. The user's browser supports checking for location services.
  3. The user's browser has location services enabled.

Combining the answers on the page and one additional check, we can handle all three of these scenarios:

    /* Set up getCurrentPosition options with a timeout */
    const navigatorLocationOptions = {
      enableHighAccuracy: true,
      timeout: 5000,
      maximumAge: 0
    };

    /* Determine browser permissions status */
    navigator.permissions.query({name:'geolocation'})
      .then((result) => {
        /* result.state will be 'granted', 'denied', or 'error' */
        if (result.state === 'granted') {
          navigator.geolocation.getCurrentPosition(pos => {
             console.log('Retrieved user location', pos);
             /* Got the location! Write your successful code here. */            

          }, (error) => {
            /* System/OS location services disabled */
            console.log('System/OS services disabled', navigator);
            noLocationFound();
          }, navigatorLocationOptions);

        } else {
          /* Browser location services disabled or error */
          console.log('Browser location services disabled', navigator);
          noLocationFound();
        }
      }, (error) => {
        /* Browser doesn't support querying for permissions */
        console.log('Browser permissions services unavailable', navigator);
        noLocationFound()
      }
    );
    
    /* Handle no location found */
    function noLocationFound() {
      /* Write code here to handle: user location is unavailable */
    }

Simply add your handling code for user notification and fallback in the noLocationFound() function.