geolocation Permission
5 min readgeolocation Permission
Overview
- Permission string:
"geolocation"(optional permission in MV3) - Enables
navigator.geolocationin extension pages - MV3 challenge: service workers cannot use Geolocation API directly
Web API (not chrome.* API)
navigator.geolocation.getCurrentPosition(success, error?, options?)
navigator.geolocation.watchPosition(success, error?, options?)
navigator.geolocation.clearWatch(watchId)
Position Options
| Option | Type | Description |
|---|---|---|
enableHighAccuracy |
boolean | Use GPS if available (slower, more battery) |
timeout |
number | Milliseconds to wait for position |
maximumAge |
number | Accept cached position if younger than this (ms) |
Position Object
coords.latitude,coords.longitude,coords.accuracycoords.altitude,coords.altitudeAccuracy(may be null)coords.heading,coords.speed(may be null)timestamp
MV3: Service Worker Workaround
Service workers do not have access to navigator.geolocation. Use an offscreen document with GEOLOCATION reason:
- SW creates offscreen doc with reason
GEOLOCATION - Send message to offscreen doc requesting position
- Offscreen doc calls
navigator.geolocation - Offscreen doc sends result back to SW
- SW closes offscreen doc (optional)
// background.ts (service worker)
async function getLocation(): Promise<GeolocationPosition> {
if (!(await chrome.offscreen.hasDocument())) {
await chrome.offscreen.createDocument({
url: chrome.runtime.getURL('offscreen.html'),
reasons: [chrome.offscreen.Reason.GEOLOCATION],
justification: 'Access geolocation API'
});
}
return new Promise((resolve, reject) => {
chrome.runtime.sendMessage({ type: 'GET_LOCATION' }, (response) => {
if (response.error) reject(new Error(response.error));
else resolve(response.position);
});
});
}
// offscreen.ts
chrome.runtime.onMessage.addListener((msg, _sender, sendResponse) => {
if (msg.type === 'GET_LOCATION') {
navigator.geolocation.getCurrentPosition(
(pos) => sendResponse({ position: pos }),
(err) => sendResponse({ error: err.message }),
{ enableHighAccuracy: true, timeout: 10000 }
);
return true;
}
});
Manifest Declaration
{
"permissions": ["offscreen"],
"optional_permissions": ["geolocation"]
}
Or declare geolocation as required:
{
"permissions": ["geolocation", "offscreen"]
}
Use Cases
- Local weather widget
- Nearby store/restaurant finder
- Location-based notifications
- Travel distance calculator
- Geo-fencing alerts
Code Examples
Get position from popup (direct)
navigator.geolocation.getCurrentPosition(
(pos) => console.log(pos.coords.latitude, pos.coords.longitude),
(err) => console.error(err.message),
{ enableHighAccuracy: true, timeout: 10000 }
);
Watch position with error handling
const watchId = navigator.geolocation.watchPosition(
(pos) => console.log('Updated:', pos.coords.latitude, pos.coords.longitude),
(err) => {
if (err.code === err.PERMISSION_DENIED) console.error('Denied');
else if (err.code === err.POSITION_UNAVAILABLE) console.error('Unavailable');
else if (err.code === err.TIMEOUT) console.error('Timeout');
},
{ enableHighAccuracy: true, maximumAge: 60000 }
);
navigator.geolocation.clearWatch(watchId);
Get position from service worker via offscreen
// background.ts
async function getLocation() {
if (!(await chrome.offscreen.hasDocument())) {
await chrome.offscreen.createDocument({
url: 'offscreen.html',
reasons: [chrome.offscreen.Reason.GEOLOCATION],
justification: 'Geolocation needs document context'
});
}
return new Promise((resolve, reject) => {
chrome.runtime.sendMessage({ type: 'GET_LOCATION' }, (resp) => {
resp.error ? reject(new Error(resp.error)) : resolve(resp.position);
});
});
}
Cross-References
Frequently Asked Questions
How do I get user’s location in a Chrome extension?
Use the standard Geolocation API (navigator.geolocation) in your content script. The “geolocation” permission is only needed for the background script.
Can extensions override geolocation for testing?
Yes, Chrome DevTools allows you to override geolocation for testing purposes in your content scripts. —
Part of the Chrome Extension Guide by theluckystrike. Built at zovo.one.