A proposal to add approximate location to Geolocation API.
Sharing precise location information puts the user's privacy at risk as it can reveal sensitive information about the user's personal life such as home address, workplace, or place of worship. However, users may still wish to share location information to enable a more localized experience or facilitate a transaction. Approximate information about the user's location (for instance, a postal code) has a lower privacy risk and is typically sufficient for most applications. Extending Geolocation API to support approximate location would empower users to protect their location privacy and enable sites to request safer defaults when precise location is not needed.
Some jurisdictions have passed laws defining "precise" location in terms of a maximum accuracy radius. These provide real-world examples of what developers might expect to receive from users sharing precise location vs. approximate location:
- The California Privacy Rights Act defines precise geolocation as having an accuracy radius of 1,850 feet (564 meters) or less.
- The Connecticut Data Privacy Act defines precise geolocation as 1,750 feet (533 meters) or less.
- The Utah Consumer Privacy Act defines precise geolocation as 1,750 feet (533 meters) or less.
- The Virginia Consumer Data Protection Act defines precise geolocation as 1,750 feet (533 meters) or less.
Mobile operating systems already provide user controls for approximate location.
- iOS 14 introduced a Precise Location app setting which may be turned off to use approximate location. When precise location is off, the app receives an approximate location estimate with accuracy between 2 kilometers and 10 kilometers based on the population density of the user's location.
- On Android 12 and later, users choose to grant approximate or precise location permissions. When an app has the approximate location permission and not the precise location permission, it receives an approximate location estimate with a minimum accuracy of 2 kilometers.
This proposal introduces the concepts of approximate and precise location data. For the purpose of this proposal, precise location data is location data with an accuracy radius less or equal to than some bound, and all other location data is approximate. This proposal recommends adopting a bound of at least 2 kilometers.
New permission. A new approximate geolocation permission is introduced and the existing geolocation permission becomes the precise geolocation permission. A site is allowed to access geolocation if it has either the approximate or the precise permission. A site that does not have the precise location permission must not receive precise location data. A corresponding policy-control feature is introduced.
Permission Prompt and UI. While this explainer does not go into the details of how the permission prompt and permission settings for geolocation should or could be updated to support approximate geolocation, the expectation is that the user agent surfaces the choice between approximate and precise geolocation to the user.
Generate approximate location data. To generate an approximate position estimate the browser should prefer to use the system's approximate location source if available, but may acquire a precise position estimate and apply a coarsening algorithm. The coarsening algorithm must ensure it is not possible to infer the user's precise location from an approximate position estimate.
As an example of a coarsening algorithm, see LocationFudger which is used by the platform location API on Android. This algorithm uses two techniques: snap-to-grid and random offsets. Snap-to-grid creates a many-to-one mapping of precise locations to approximate locations within a local area. Random offsets ensure precise location information cannot be inferred when crossing a grid boundary.
Request approximate location.
When calling getCurrentPosition or watchPosition, the caller may pass a
parameter to request approximate location mode.
If the caller requests approximate location mode it must only receive
approximate location data.
navigator.geolocation.getCurrentPosition(
onsuccess, onerror, {accuracyMode: 'approximate'});The introduction will be updated to introduce the concepts of precise and approximate location and define the accuracy bound for precise location.
Section 7 defines the PositionOptions
dictionary.
Callers of getCurrentPosition and watchPosition can pass a PositionOptions
parameter to modify the position request.
dictionary PositionOptions {
boolean enableHighAccuracy = false;
[Clamp] unsigned long timeout = 0xFFFFFFFF;
[Clamp] unsigned long maximumAge = 0;
// New
AccuracyMode accuracyMode = "precise";
};
enum AccuracyMode {
// Request precise location.
"precise",
// Require approximate location.
"approximate"
}PositionOptions will be extended to add an accuracyMode member. Callers can
pass "approximate" to request approximate location or "precise" to request
precise location. If accuracyMode is not set, it defaults to "precise" (for
backwards compatibility, so that we do not break existing use cases).
Although we initially considered exposing the accuracy mode in the returned
GeolocationPosition, it was eventually decided not to do so. In this way, the
user choice (approximate/precise) is not exposed to the website. The website can
still rely, for its functionality, on the accuracy of the returned
GeolocationCoordinates, which can be higher or lower for a number of possible
reasons. This now includes the possibility that the user only granted
approximate geolocation access.
Support for approximate location can be detected with the following code:
function browserImplementsAccuracyMode() {
try {
navigator.geolocation.getCurrentPosition(
() => {},
() => {},
{
get accuracyMode() { throw new Error('1'); },
get enableHighAccuracy() { throw new Error('2'); }
}
);
} catch (e) {
if (e.message === '1') {
return true;
}
console.assert(e.message === '2');
return false;
}
console.assert(false, 'this code will never be reached');
}Section 3.1 defines a powerful feature "geolocation". It will define an
additional powerful feature "geolocation-approximate". Setting "geolocation"
to "granted" will automatically set "geolocation-approximate" to "granted",
while setting "geolocation-approximate" to "denied" will automatically set
"geolocation" to "denied". In other words, if the user denies access to
approximate location then the User Agent denies access to location at all, while
if the user grants access to precise location, also approximate location is
granted.
If "geolocation"'s state is "denied" but "geolocation-approximate"'s state
is "prompt" or "granted", a call to getCurrentPosition() or
watchPosition() would trigger a permission prompt for approximate location or
return approximate location, respectively. Correspondingly, the
Permissions.query() method
for "geolocation" would return "prompt" or "granted" (even if only
approximate geolocation is granted).
More details on how possible permission states and transitions would look like
and on how Permissions.query() would behave can be found in this
analysis.
The choice of whether the website should have access to precise or approximate geolocation should of course be under the user's control. If the website only queries approximate location, the user agent should simply ask the user if they want to grant access to approximate location. On the other hand, if the website queries precise location, the user should be presented with the choice between approximate or precise location (or nothing). In particular, the user should always have the possibility to only grant access to approximate location, even if the website requested access to precise location.
To address the use case of different accuracy levels of geolocation needed for different parts or functionalities of the website, the user agent should also offer an "upgrade prompt", asking the user who already granted access to approximate location whether they actually want to upgrade that and grant access to precise geolocation. The website can trigger such "upgrade prompt" by first querying approximate geolocation and later querying precise geolocation.
The various prompt possibilities would reflect the possible transitions between permission states.
It must always be possible for the user to revoke the permission granted to a website or change its granularity at a later point in time.
Section 11. defines a policy-controlled
feature
"geolocation". It will be updated to define an additional policy-controlled
feature "geolocation-approximate", also with a default value of "self", that
will only allow approximate location. The "geolocation" feature will imply the
"geolocation-approximate" feature.
In Section 6.5, the request a
position algorithm
requests permission to use "geolocation". It will be updated to allow for
three different prompt cases:
- If the website doesn't set
accuracyMode="approximate", the user will be prompted to choose between approximate and precise location. - If the website sets
accuracyMode="approximate", the user will only be prompted for approximate location. - If the website has already been granted approximate location (as result of a
request with
accuracyMode="approximate") and now requests precise location, the user will be prompted to upgrade their choice from approximate to precise location.
In Section 6.6, the acquire a
position algorithm
says "try to acquire position data from the underlying system, optionally
taking into consideration the value of options.enableHighAccuracy during
acquisition". It will be updated to also consider the location accuracy mode.
Additionally, the algorithm will be updated to handle acquired position
estimates that do not satisfy the accuracy bound. In particular, if the
implementation is not able to generate an approximate position estimate then
getCurrentPosition and watchPosition must return POSITION_UNAVAILABLE
when the PositionOptions parameter requires approximate location.
A privacy risk of approximate location is that a malicious actor could potentially infer a user's precise position by collecting and correlating multiple, distinct approximate positions over a short period of time. This explainer refers to this as a "precise location reconstruction" attack.
To mitigate this risk, this proposal includes a caching mechanism. When a site receives an approximate position, any subsequent calls from that same site within a user-agent-defined time window (e.g., 15 minutes) should return the exact same, cached approximate position data. This mitigates the risk by significantly slowing down the time it would take for an attacker to collect enough distinct approximate positions to reconstruct a user's precise location.
A boolean option enableHighAccuracy is already specified and its default value
is false. As an alternative to approximate location as an opt-in mode, provide
approximate location by default and only provide precise location when it is
explicitly requested.
This was rejected because changing the behavior would degrade location quality
for existing applications.
enableHighAccuracy is specified as a hint that may be ignored by the
implementation.
Historically, the high accuracy hint indicates the implementation should prefer
accuracy over speed; specifically, if the system has GPS capabilities it should
wait for a GPS fix instead of returning a less precise result.
This tradeoff is not necessary on modern systems as system location providers
are able to generate a precise estimate quickly without waiting for GPS.
As a result, the behavior on most systems is not affected by the
enableHighAccuracy option and many applications use the default value
regardless of whether precise location is needed.
We could consider treating enableHighAccuracy=true the same as
accuracyMode="precise". However, that would have a small backwards compatibility
issue with navigator.permissions.query({ name: "geolocation" }), since it
could result in different prompting behaviours (while querying the permission
state would only return one state).
This explainer proposes to gate approximate location behind a new powerful
feature "geolocation-approximate", which would be added on top of the already
existent powerful feature "geolocation", with the following rationale. A
separate powerful feature allows browsers to display a permission prompt for
approximate location only which is different than the permission prompt for
precise geolocation.
We considered the alternative of keeping a single powerful feature "geolocation"
and letting the user agent store the granted granularity (approximate or
precise) in a separate bit. However, with such model there is no way to
distinguish between the following two cases:
- The website requested approximate geolocation and the user granted.
- The website requested precise geolocation but the user decided to grant approximate only.
This means that user agents cannot, in case 1., return approximate geolocation for an approximate geolocation request while showing an upgrade prompt for a precise geolocation request (because the specification would see the same single value in both cases when querying the permission state internally). And this seems undesirable, as websites which wanted to request approximate location only would not have a way of eventually switching to precise location in the future if they needed it (at least for user agents which persist permission states beyond a single session).
We also thought about why the new powerful feature "geolocation-approximate"
should be queryable via permissions.query() given that its returned state is
mostly the same as for "geolocation" (see the permission states
analysis). The answer to this is that we want to keep
the invariant that getCurrentPosition() prompts, resolves successfully or
throws with permission error if and only if permissions.query() resolves with
"prompt", "granted" or "denied", respectively. This allows websites
currently relying on the API to easily switch to approximate location with
minimal code changes, e.g. from
navigator.permissions.query({ name:'geolocation' }).then((result) => {
if (result.state === 'granted') {
navigator.geolocation.getCurrentPosition(onGotPosition);
} else if (result.state === 'denied') {
showMessage("Geolocation access denied");
} else {
showHelpfulUI("Grant location access to see the store closest to you.");
navigator.geolocation.getCurrentPosition(onGotPosition);
}into
navigator.permissions.query({ name:'geolocation-approximate' }).then((result) => {
if (result.state === 'granted') {
navigator.geolocation.getCurrentPosition(onGotPosition, {accuracyMode: 'approximate'});
} else if (result.state === 'denied') {
showMessage("Geolocation access denied");
} else {
showHelpfulUI("Grant location access to see the store closest to you.");
navigator.geolocation.getCurrentPosition(onGotPosition, {accuracyMode: 'approximate'});
}This seems the best solution to make adoption of approximate location easy and possible for websites.
Note anyway that the existence of the two geolocation powerful features does
not expose the granularity granted by the user after seeing a permission
prompt with the options approximate/precise: After such a prompt is displayed,
if the user grants any location access, querying both "geolocation" and
"geolocation-approximate" would resolve as "granted", and the user choice
(approximate/precise) is protected. In particular, this doesn't seem to expose
more information than needed.
Privacy concerns with regards to
being able to discern that a permission is granted seem to apply in the same way
to both the existent "geolocation" and "geolocation-approximate" powerful
feature, and might be addressed, orthogonally from this proposal, by
allowing user agents to mask the
queried permission states.
An earlier version of this explainer was proposing adding an accuracyMode
aspect to the powerful feature
"geolocation" and implementing a custom permission descriptor
GeolocationPermissionDescriptor. This has been discarded in response to
feedback.