Geolocation in Chrome Extensions: How to Access User Location (2026)
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
| Context | Direct API Access | Approach |
|---|---|---|
| Popup / Side Panel | Yes | Standard navigator.geolocation |
| Content Script | Yes | Standard API (browser permission prompt) |
| Service Worker | No | Offscreen 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
| Option | Default | Description |
|---|---|---|
enableHighAccuracy | false | Uses GPS when available (slower, more battery) |
timeout | Infinity | Max wait time in milliseconds |
maximumAge | 0 | Accept 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
I Built the Same Chrome Extension With 5 Different Frameworks. Here's What Actually Happened.
WXT vs Plasmo vs CRXJS vs Extension.js vs Bedframe. Real benchmarks, honest opinions, and the framework with 12K stars that's quietly dying.
5 Best Email Marketing Services to Grow Your Chrome Extension (2026)
Compare the top email marketing platforms for SaaS and Chrome extension developers. MailerLite, Mailchimp, Brevo, ActiveCampaign, and Drip reviewed.
15 Best Practices to Build a Browser Extension That Users Love (2026 Guide)
Master browser extension development in 2026. Manifest V3, security, performance, and UX best practices to build extensions users love.