---
title: "Fix Geolocation Request on Page Load"
description: "Stop requesting geolocation permission on page load. Users distrust sites that ask for location without context - tie requests to user actions instead."
canonical_url: "https://unlighthouse.dev/learn-lighthouse/best-practices/geolocation-on-start"
last_updated: "2025-01-18"
---

Requesting location permission the moment someone lands on your page is the fastest way to get denied. Users don't trust sites that ask for sensitive permissions without context.

## What's Happening

Your JavaScript calls `navigator.geolocation.getCurrentPosition()` or `navigator.geolocation.watchPosition()` during page load - before the user has done anything that suggests they want location features. The browser shows a permission prompt immediately, the user reflexively clicks "Block," and now your location features are permanently broken for that visitor.

Lighthouse flags this because it's both bad UX and counterproductive. Studies show permission grant rates drop significantly when prompts appear without context.

## Diagnose

### DevTools Console

Lighthouse reports the source location in the audit details. You can also find it manually:

1. Open DevTools > Sources
2. Search all files (`Cmd/Ctrl+Shift+F`) for `geolocation`
3. Look for calls to `getCurrentPosition` or `watchPosition`
4. Check if they're inside event handlers (good) or top-level/immediately invoked (bad)

### Common Patterns That Trigger This

```js
// Bad: Runs on script load
navigator.geolocation.getCurrentPosition((pos) => {
  console.log(pos.coords)
})

// Bad: Runs immediately when module loads
const position = await new Promise((resolve) => {
  navigator.geolocation.getCurrentPosition(resolve)
})

// Bad: Inside DOMContentLoaded or load event
window.addEventListener('load', () => {
  navigator.geolocation.getCurrentPosition(handlePosition)
})
```

## Fix

### 1. Request After User Action

Move geolocation requests inside user-triggered event handlers:

**Before (bad):**

```js
// Runs on page load
navigator.geolocation.getCurrentPosition(
  position => showNearbyStores(position.coords),
  error => console.error(error)
)
```

**After (good):**

```js
document.querySelector('#find-stores-btn').addEventListener('click', () => {
  navigator.geolocation.getCurrentPosition(
    position => showNearbyStores(position.coords),
    error => showLocationError(error)
  )
})
```

The user clicks "Find stores near me," the prompt appears, and they understand why you're asking.

### 2. Show a Pre-Permission Prompt

For better UX, explain before the browser prompt appears:

```js
const locationBtn = document.querySelector('#use-location')

locationBtn.addEventListener('click', async () => {
  // Check current permission state
  const permission = await navigator.permissions.query({ name: 'geolocation' })

  if (permission.state === 'granted') {
    // Already have permission, proceed
    getLocation()
  }
  else if (permission.state === 'prompt') {
    // Show custom UI explaining why
    showLocationExplainer()
  }
  else {
    // Denied - show alternative
    showManualLocationInput()
  }
})

function showLocationExplainer() {
  const modal = document.querySelector('#location-explainer')
  modal.showModal()

  modal.querySelector('#confirm-location').addEventListener('click', () => {
    modal.close()
    getLocation()
  }, { once: true })
}

function getLocation() {
  navigator.geolocation.getCurrentPosition(
    position => handleSuccess(position.coords),
    error => handleError(error)
  )
}
```

### 3. Provide a Fallback

Always have a non-location path:

```js
function initStoreLocator() {
  // Default: show all stores or ask for zip code
  showAllStores()

  // Enhance with location button
  const locationBtn = document.querySelector('#use-my-location')
  locationBtn.addEventListener('click', requestLocation)
}

function requestLocation() {
  navigator.geolocation.getCurrentPosition(
    pos => filterStoresByProximity(pos.coords),
    () => showZipCodeInput() // Fallback on denial/error
  )
}
```

## Verify the Fix

1. Clear site data (DevTools > Application > Clear site data)
2. Reload the page
3. No permission prompt should appear
4. Interact with the feature that needs location
5. Now the prompt should appear

Run Lighthouse again - the "Requests the geolocation permission on page load" audit should pass.

## Common Mistakes

- **Moving to DOMContentLoaded** - Still runs automatically, still bad. The user must *do* something first.
- **Using setTimeout to delay** - `setTimeout(() => { geolocation... }, 5000)` is still automatic. Lighthouse may not catch it, but users will still see an unexplained prompt.
- **Checking permissions then requesting** - Even `navigator.permissions.query()` followed by an automatic request is wrong. The permission check is fine; the automatic request isn't.
- **Third-party scripts** - Analytics or mapping libraries request location on load. Check your dependencies and configure them to defer location requests.

## Test Your Entire Site

Location requests might be buried in a script that only loads on certain pages. [Unlighthouse](/) scans every page on your site and flags any that trigger geolocation requests on load.
