Skip to content

Manifest protocol_handlers: registering a PWA for custom URL schemes

Published

In one line: the manifest’s protocol_handlers member registers an installed PWA as the OS’s handler for a URL scheme (like mailto: or a custom web+-prefixed one), so clicking a matching link — from a browser tab, another app, or the OS — launches your app with that URL instead of just navigating a page.

Per MDN, protocol_handlers is an array of objects, each with a required protocol (the scheme to handle, e.g. mailto, ms-word, or web+jngl) and a required url (an HTTPS URL within the app’s scope where the %s token is replaced with the full clicked URL). Registering the association with the OS usually happens at install time, though per MDN it can also be made afterward for an already-installed app.

  • Legend
  • Yes
  • Partial
  • Flag
  • No
  • Unknown
Browser / PlatformSupportVersionsConfidenceSourceNotes
Chrome (Android)No—mediumsource1
Chrome (Desktop)Yes96mediumsource—
Edge (Desktop)Yes96mediumsource—
Safari (iOS)No—mediumsource2
Safari (macOS)No—mediumsource3
Firefox (Desktop)No—mediumsource4
Samsung InternetNo—mediumsource5
  1. Desktop-only registration.
  2. Safari does not implement the `protocol_handlers` manifest member (MDN compatibility table, checked 2026-10-03).
  3. Safari does not implement the `protocol_handlers` manifest member (MDN compatibility table, checked 2026-10-03).
  4. Desktop Firefox does not install web apps from the manifest and does not implement `protocol_handlers` (MDN compatibility table, checked 2026-10-03).
  5. Chromium ships manifest protocol handlers for desktop installs only; Samsung Internet lists no support (MDN compatibility table, checked 2026-10-03).

Source data: /compatibility/protocol-handlers.json · Global usage: 37 % (StatCounter 2026-05)

Source: spec · MDN · Last verified 2026-06-24 · Confidence: medium (computed from sources)

Manifest-based protocol_handlers registration is desktop-only across the browsers that implement it; there is also the separate, older navigator.registerProtocolHandler() API for registering a handler imperatively from a page, which does not require installation.

Declare the protocol and the URL template in the manifest:

{
"protocol_handlers": [
{
"protocol": "web+coffee",
"url": "/coffee?type=%s"
}
]
}

Separately, MDN documents a naming rule for the related, older navigator.registerProtocolHandler() API: its scheme argument must begin with web+ followed by one or more lower-case ASCII letters (e.g. web+coffee), or be one of a fixed safelist such as mailto, bitcoin, or magnet. The manifest’s protocol_handlers page itself does not document a naming restriction on its protocol field.

Once installed and registered, the %s placeholder in the handler URL is replaced by the URL that starts with the handler’s scheme.

Per MDN, associating a protocol with an installed app is usually done during installation, though the association can also be made afterward for an already-installed app. What a page can detect is whether the separate, imperative registerProtocolHandler() method exists, for sites that want to offer registration outside of installation:

if ('registerProtocolHandler' in navigator) {
navigator.registerProtocolHandler('web+coffee', '/coffee?type=%s');
} else {
// No imperative registration API — rely on the manifest-declared
// protocol_handlers association completed at install time instead.
}
  • Manifest-based protocol_handlers registration only takes effect once the app is installed — it does not register anything for a page opened in a plain browser tab.
  • MDN’s documented web+-prefix / safelist naming rule applies to the older registerProtocolHandler() API’s scheme argument — its manifest protocol_handlers page does not itself state that protocol values are restricted the same way.
  • The url member must be within the app’s manifest scope and use HTTPS, per MDN — it cannot point off-origin.
  • The %s placeholder is replaced with the entire clicked URL, not just a parsed payload — parse out the part after the scheme yourself in the handler route.
  • manifest: file_handlers support — another manifest member that registers an installed PWA with the OS, for file types instead of URL schemes.
  • Handle files — a related guide to registering an installed PWA for OS-level file associations.