Geolocation in Chrome Extensions: How to Access User Location (2026)

AppBooster Team · · 4 min read
Map with location pin on a device

Adding Location Awareness to Your Chrome Extension

Geolocation lets your extension access the user’s physical location — essential for weather tools, local search extensions, store finders, and location-based productivity apps. In Manifest V3, the approach depends on which extension context needs the location data.

The challenge: service workers don’t have access to navigator.geolocation. This guide covers every context with working code.


Geolocation by Extension Context

ContextDirect API AccessApproach
Popup / Side PanelYesStandard navigator.geolocation
Content ScriptYesStandard API (browser permission prompt)
Service WorkerNoOffscreen document pattern

Approach 1: Service Worker via Offscreen Document

Service workers lack a navigator object, so you need an offscreen document as a bridge.

manifest.json

{
  "manifest_version": 3,
  "name": "Location Extension",
  "version": "1.0",
  "permissions": ["offscreen", "geolocation"],
  "background": {
    "service_worker": "service-worker.js"
  }
}

offscreen.html

<!DOCTYPE html>
<html><body><script src="offscreen.js"></script></body></html>

offscreen.js

chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (message.action !== 'getLocation') return false;

  navigator.geolocation.getCurrentPosition(
    (position) => {
      // Geolocation objects lose properties during message passing
      // Deep clone the data we need
      sendResponse({
        success: true,
        coords: {
          latitude: position.coords.latitude,
          longitude: position.coords.longitude,
          accuracy: position.coords.accuracy,
          altitude: position.coords.altitude,
          altitudeAccuracy: position.coords.altitudeAccuracy,
          heading: position.coords.heading,
          speed: position.coords.speed
        },
        timestamp: position.timestamp
      });
    },
    (error) => {
      sendResponse({
        success: false,
        error: { code: error.code, message: error.message }
      });
    },
    {
      enableHighAccuracy: message.highAccuracy || false,
      timeout: message.timeout || 10000,
      maximumAge: message.maximumAge || 0
    }
  );

  return true; // Keep channel open for async response
});

service-worker.js

async function ensureOffscreenDocument() {
  const existingContexts = await chrome.runtime.getContexts({
    contextTypes: ['OFFSCREEN_DOCUMENT']
  });

  if (existingContexts.length > 0) return;

  await chrome.offscreen.createDocument({
    url: 'offscreen.html',
    reasons: [
      chrome.offscreen.Reason.GEOLOCATION ||
      chrome.offscreen.Reason.DOM_SCRAPING
    ],
    justification: 'Access geolocation API for location-based features'
  });
}

async function getCurrentLocation(options = {}) {
  await ensureOffscreenDocument();

  return chrome.runtime.sendMessage({
    action: 'getLocation',
    highAccuracy: options.highAccuracy || false,
    timeout: options.timeout || 10000,
    maximumAge: options.maximumAge || 0
  });
}

// Example: get location on extension icon click
chrome.action.onClicked.addListener(async () => {
  const location = await getCurrentLocation({ highAccuracy: true });

  if (location.success) {
    console.log(`Lat: ${location.coords.latitude}, Lng: ${location.coords.longitude}`);
  } else {
    console.error(`Geolocation error: ${location.error.message}`);
  }
});

Important: Chrome allows only one offscreen document at a time. Always check for existing documents before creating one, and close it when done.


Approach 2: Popup or Side Panel

Direct API access is available — the simplest approach:

// popup.js
document.getElementById('locate-btn').addEventListener('click', () => {
  navigator.geolocation.getCurrentPosition(
    (position) => {
      document.getElementById('result').textContent =
        `${position.coords.latitude.toFixed(4)}, ${position.coords.longitude.toFixed(4)}`;
    },
    (error) => {
      document.getElementById('result').textContent = `Error: ${error.message}`;
    },
    { enableHighAccuracy: true, timeout: 5000 }
  );
});

Add "geolocation" to your manifest permissions to suppress the browser’s permission dialog:

{
  "permissions": ["geolocation"]
}

Approach 3: Content Scripts

Content scripts have DOM access and can use navigator.geolocation directly. However, the user sees the standard browser permission prompt for the host page’s origin — not your extension’s.

// content-script.js
navigator.geolocation.getCurrentPosition(
  (position) => {
    chrome.runtime.sendMessage({
      action: 'locationUpdate',
      coords: {
        latitude: position.coords.latitude,
        longitude: position.coords.longitude
      }
    });
  },
  (error) => {
    console.error('Geolocation denied:', error.message);
  }
);

Note: Declaring "geolocation" in manifest permissions does not auto-grant access in content scripts. The user must still approve via the browser prompt.


Error Handling

Handle all three geolocation error codes:

function handleGeolocationError(error) {
  switch (error.code) {
    case error.PERMISSION_DENIED:
      return 'Location access denied. Please enable in browser settings.';
    case error.POSITION_UNAVAILABLE:
      return 'Location unavailable. Check your device settings.';
    case error.TIMEOUT:
      return 'Location request timed out. Try again.';
    default:
      return 'Unknown location error.';
  }
}

Geolocation Options Explained

OptionDefaultDescription
enableHighAccuracyfalseUses GPS when available (slower, more battery)
timeoutInfinityMax wait time in milliseconds
maximumAge0Accept cached position up to this age (ms)

Pro Tip: For one-time lookups (weather, locale detection), use maximumAge: 300000 (5 minutes) to avoid unnecessary GPS requests.


What’s Next

Geolocation opens up location-aware features that differentiate your extension. Use offscreen documents for service worker access, direct API calls for popups, and always handle permission denials gracefully.

Want more developer insights? ExtensionBooster provides free tools to help you build better Chrome extensions.

Share this article

Build better extensions with free tools

Icon generator, MV3 converter, review exporter, and more — no signup needed.

Related Articles