DEV Community

Cover image for Why Your Browser Won't Open Maps with a geo: URI (And a Workaround)
Tomas Gallucci
Tomas Gallucci

Posted on

Why Your Browser Won't Open Maps with a geo: URI (And a Workaround)

Cover Photo by GeoJango Maps on Unsplash




Mapping software has existed for years on machines connected to the internet, be that in apps or websites. (Remember printing out directions from Mapquest?)

On mobile (read phones and tablets), we have Google Maps, Apple Maps or Waze. Desktop is trickier because neither Windows or Linux come with default, client-side mapping software. macOS, however, does come with (Apple) Maps.

It would be nice if, on websites, we could create one link that had enough data in it that it could open a default app or website for people to get driving directions. In other words, not a link to Google Maps. Not a link to Apple Maps. Just enough metadata for the browser to open the mapping software of the user’s choice.

Defining the Problem

First, some definitions.

URL, an acronym that stands for Uniform Resource Locator, best known as web links. URLs have the following format:

[scheme]://[host]/[path]?[query]#[fragment]

If we take a web address, say https://apple.com, we can see that there is a scheme (https) and a host (apple.com). We can omit a path because web servers will provide a default path even if one is not specified. But if we want a specific resource from the domain, then we would add the path. For example, if we want to look at the iPhone page, we would specify https://www.apple.com/iphone/.

It turns out that URLs are a highly familiar form of a URI or Uniform Resource Identifier. A URI is a string of characters that identifies a resource, either by its location, name, or both, in a standardized way. URIs are structured like this:

[scheme]:[scheme-specific-part][#fragment]

As you can see, the format of a URI is a more generic form of a URL.

URI Schemes in Action

With a URL, the scheme part of the URI is also the protocol that is to be used e.g. http or https. Web browsers handle both of these protocols because web sites run on the Hype*text **Transfer **P*rotocol. HTTP protocol; HTTPS adds encryption or the "security" the "S" stands for in the acronym.

It turns out that there are URIs that are useful for other things like creating a link to a phone number or an email address. For example

<a href=”tel:2595556455”>Might Actually be a Valid Phone Number</a> 
Enter fullscreen mode Exit fullscreen mode

will render like this: Might Actually be a Valid Phone Number. If you were to click or tap the link, your device will try to place a phone call to 2595556455 with some kind of telephony app. For iOS, this would be the phone app that comes pre-installed on the phone. (You can change the default to FaceTime; Zoom is also an option if installed, but Signal is not.) There are also default dialers for Androids of all kinds. And it's possible that you could default to an app like Signal.

On macOS, FaceTime will open if you click on a link that has a tel: URI scheme.

<a href=”mailto:janedoe@spamspamspam.com”>Totally Legit Email</a> 
Enter fullscreen mode Exit fullscreen mode

will render like this: Totally Legit Email

If you were to click or tap that link, your default email client would open on both desktop and mobile.

What if there was a URI scheme that could do the same for addresses?

The loc: URI Scheme

What many web programmers don’t know is that there is a geolocation URI scheme that has been defined since 2010. Here are two examples:

<a href=”geo:112.0,-112.0;u=35”>Example of a Geolocation Tag</a> 
Enter fullscreen mode Exit fullscreen mode
<a href="geo:0,0?q=1600+Pennsylvania+Ave+NW,+Washington,+DC+20500" rel="noopener">1600 Pennsylvania Ave NW, Washington, DC 20500</a> 
Enter fullscreen mode Exit fullscreen mode

In the first example, what follows geo: is latitude and longitude coordinates with an optional “uncertainty” radius parameter defined by the u=35. In the second example, we see we can zero out the lat and long and use a mailing address instead.

This seems like nirvana, one geolocation URI scheme to rule them all!

Unfortunately, not all is well in Elsinore.

It Doesn't Really Work

The only device that seems to support it half way decently, is a major browser (i.e. Firefox) on an Android phone.

The major reason that geo: URI schemes don't work is that the browsers don't register handlers for the URI schemes.

We'll show you a lame workaround towards the end of this post that relies on browsers not handling the loc: URI scheme throwing an error that can be handled in a try/catch, but it turns out even that doesn't work.

Firefox, Chrome, and Safari don’t even recognize the thing, apparently

Firefox

Firefox console when clicking an `<a>` with a `geo:` URI scheme
Firefox console when clicking an <a> with a geo: URI scheme

The fact that this is not an error means that it cannot be handled simply by a try / catch fallback on Firefox. It must have a more robust device agent checking solution that “fixes” Firefox's shortcomings. The good news is that Firefox's marketshare is dwindling, so this browser may not have to be supported for long.

Chrome

Chrome console when clicking an `<a>` with a `geo:` URI scheme
Chrome console when clicking an <a> with a geo: URI scheme

You might expect that Chrome would open a new tab or window to Google Maps with the specified latitude and longitude or physical address. Instead, the behavior is a silent console error with no message presented to the end-user.

Safari

Safari's behavior on both desktop is even more baffling, especially given that Safari only runs on Apple's OSes and Apple has their own, first-party mapping software!

Safari Desktop

Safari desktop alert when clicking an `<a>` with a `geo:` URI scheme
Safari desktop alert when clicking an <a> with a geo: URI scheme

On the desktop, at least Safari gives a browser alert in addition to throwing an error. But, as pointed out above, this makes absolutely no sense–why doesn't Apple at lest register geo: with Safari and either ask or attempt to open the location in Apple Maps?

Perhaps Apple has avoided doing this to avoid an anti-trust/anti-competition lawsuit. This seems fixable with a setting, but as we will see, even on mobile Apple hasn't properly solve this problem.

Safari Mobile

Safari desktop alert when clicking an `<a>` with a `geo:` URI scheme
Safari mobile alert when clicking an <a> with a geo: URI scheme

Tapping on a link that has a geo: URI scheme on iOS 18.5 on an iPhone 16 Pro doesn't try to open Apple Maps nor Google Maps, both of which are installed. Instead, mobile Safari is registered to open location links with Google Earth!

To add insult to injury, maps isn't a category that you can set a default app for, at least not in Default Apps:

List of defaults that can be changed under Default Apps in iOS 18.5
List of defaults that can be changed under Default Apps in iOS 18.5

Apple has, in times past, sometimes hidden default app settings in Apple's setting for that particular app. For example, you'd go to Safari's settings to change the default web browser. There is no such setting in the (Apple) Maps settings. (Note: I'm not showing the Maps settings here because it's several screens long and there is no default setting in the list of Maps settings.)

A Workaround

As promised, here is a workaround. It is a React component that detects browsers that do support loc: and replaces the anchor with a link to Google Maps if the browser doesn't support the loc: URI scheme. (Note: This code doesn't know about browser's capabilities; rather, it assumes the programmer knows which browsers do and don't support loc: URI schemes.)

const AddressLink = ({ street, city, state, zip, }: { street: string; city: string; state: string; zip: string; }) => { if (!street?.trim() || !city?.trim() || !state?.trim() || !zip?.trim()) { return <address>Invalid address</address>; } const address = `${street.trim().replace(/\.$/, "")}, ${city .trim() .replace(/\.$/, "")}, ${state.trim().replace(/\.$/, "")} ${zip.trim()}`; const encoded_address = encodeURIComponent(address).replace(/%20/g, "+"); const geoAddress = `geo:0,0?q=${encoded_address}`; const fallbackAddress = `https://www.google.com/maps/search/?api=1&query=${encoded_address}`; // this will need to be updated for any new mobile devices that exist. // it is a regex that tests the current agent against all the agents listed. function supportsGeoScheme() { return /Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test( navigator.userAgent ); } const handleClick = (e: React.MouseEvent) => { if (supportsGeoScheme()) { window.location.href = geoAddress; // Attempt geo: } else { e.preventDefault(); window.location.href = fallbackAddress; // Fallback to Google Maps } }; return ( <address> <a href={geoAddress} onClick={handleClick} rel="noopener noreferrer"> {address} </a> </address> ); }; export default AddressLink; 
Enter fullscreen mode Exit fullscreen mode

If this post was helpful, educational or entertaining, please consider converting that help, education or entertainment value into a number and returning it to us:



PayPal Donation Button


Buy Me a Coffee


Justin Morrow (github - LinkedIn - X) contributed to this blog post and will receive partial compensation from donations.

Top comments (0)