JavaScript Navigator unregisterProtocolHandler() Method

Beginner
⏱️ 11 min read
📚 Updated: Jul 2026
🎯 5 Examples
🚀 5 Try-it labs
🔒 Secure context
Limited availability

What You’ll Learn

navigator.unregisterProtocolHandler() removes a protocol handler your site registered earlier. Learn the matching scheme + %s URL rules, HTTPS same-origin requirements, five examples, and how it pairs with registerProtocolHandler().

01

Kind

Method

02

Returns

undefined

03

Status

Limited (not Baseline)

04

Context

Secure (HTTPS)

05

Pair with

registerProtocolHandler

06

Must match

Same scheme + URL

Introduction

After a site calls registerProtocolHandler(), the browser may open mailto:, tel:, or custom web+ links in that web app. When the user turns the feature off — or your settings page offers “Stop handling these links” — call unregisterProtocolHandler().

Pass the same scheme and the same handler URL template (including %s) that were used at registration time. The method returns undefined and may throw if the scheme or URL rules fail.

💡
No Dep / Exp / Non-standard banner

MDN marks Limited availability and a secure context, but not Deprecated, Experimental, or Non-standard. Learn registration first: registerProtocolHandler().

Understanding the unregisterProtocolHandler() Method

  • Two argumentsscheme and handler url (must include %s).
  • Exact match — URL should match what was registered.
  • HTTPS + same origin — call from a secure page whose origin matches the handler URL.
  • Allowed schemes — same list as registration (mailto, sms, web+…, …).
  • Blocked schemes — browser-owned schemes like https / about cannot be unregistered this way.
  • Return valueundefined (side-effect API).

📝 Syntax

General form of the method:

JavaScript
navigator.unregisterProtocolHandler(scheme, url)

Parameters

  • scheme — protocol to unregister (for example "sms" or "web+burger").
  • url — handler template URL that includes %s and matches registration.

Return value

  • undefined.

Common exceptions

  • SecurityError — invalid / blocked scheme, wrong origin, non-HTTPS handler, or insecure context.
  • SyntaxError — missing %s in the handler URL.

MDN-style custom scheme example

JavaScript
// Must run on https://burgers.example.com (same origin as the handler URL)
navigator.unregisterProtocolHandler(
  "web+burger",
  "https://burgers.example.com/?burger=%s"
);

⚡ Quick Reference

GoalCode
Feature detecttypeof navigator.unregisterProtocolHandler === "function"
Unregister mailtonavigator.unregisterProtocolHandler("mailto", "https://…/?to=%s")
Custom schemenavigator.unregisterProtocolHandler("web+app", "https://…/?q=%s")
Secure context?window.isSecureContext
Template checkurl.includes("%s")
Register firstnavigator.registerProtocolHandler(scheme, url)

🔍 At a Glance

Four facts to remember about navigator.unregisterProtocolHandler().

Args
scheme, url

Must include %s

Status
Limited

Not Baseline

Context
HTTPS

Same origin

Inverse of
register…

Same template

📋 register vs unregister

registerProtocolHandler()unregisterProtocolHandler()
PurposeAdd a web handlerRemove that handler
Argumentsscheme, url with %sSame pair (exact match)
User promptOften on register / first useUsually quieter; still secure-context rules
Typical UI“Use this site for mailto links”“Stop handling these links”

Examples Gallery

Demos detect support, validate templates, and catch errors. Full unregister only works on HTTPS with a same-origin handler URL that previously matched a registration. Try It Yourself labs are safe to run — they may report missing API or SecurityError in the editor origin.

📚 Getting Started

Detect both APIs and see the MDN unregister pattern.

Example 1 — Feature Detection

Check register / unregister methods and secure context together.

JavaScript
const lines = [
  "registerProtocolHandler: " +
    (typeof navigator.registerProtocolHandler === "function"
      ? "available"
      : "missing"),
  "unregisterProtocolHandler: " +
    (typeof navigator.unregisterProtocolHandler === "function"
      ? "available"
      : "missing"),
  "isSecureContext: " + window.isSecureContext,
  "origin: " + location.origin
];
console.log(lines.join("\n"));
Try It Yourself

How It Works

If unregister is missing, hide the “Stop handling links” button in your settings UI.

Example 2 — Unregister web+burger (MDN)

Custom scheme pattern from MDN. In production, use your real origin.

JavaScript
function unregisterBurgerHandler() {
  if (typeof navigator.unregisterProtocolHandler !== "function") {
    return "API not supported";
  }
  if (!window.isSecureContext) {
    return "Needs HTTPS / localhost";
  }
  try {
    // Demo: build a same-origin template (must match what you registered)
    const handler = location.origin + "/?burger=%s";
    navigator.unregisterProtocolHandler("web+burger", handler);
    return "Unregister requested for web+burger → " + handler;
  } catch (err) {
    return "Error: " + err.name + " — " + err.message;
  }
}

console.log(unregisterBurgerHandler());
Try It Yourself

How It Works

Custom schemes need the web+ prefix and lowercase ASCII letters after it.

📈 Practical Patterns

Mailto cleanup, template validation, and a safe settings helper.

Example 3 — Unregister mailto

Settings-page pattern: remove the webmail handler you registered earlier.

JavaScript
function unregisterMailtoHandler() {
  if (typeof navigator.unregisterProtocolHandler !== "function") {
    return "API not supported";
  }
  const handler = location.origin + "/mail/compose?to=%s";
  try {
    navigator.unregisterProtocolHandler("mailto", handler);
    return "Unregister requested for mailto → " + handler;
  } catch (err) {
    return "Error: " + err.name;
  }
}

console.log(unregisterMailtoHandler());
Try It Yourself

How It Works

Store the exact handler string you used at register time so unregister can match it.

Example 4 — Validate Before Calling

Catch missing %s early instead of relying only on SyntaxError.

JavaScript
function canUnregister(scheme, url) {
  if (typeof navigator.unregisterProtocolHandler !== "function") {
    return { ok: false, reason: "missing-api" };
  }
  if (!window.isSecureContext) {
    return { ok: false, reason: "insecure-context" };
  }
  if (!url.includes("%s")) {
    return { ok: false, reason: "missing-%s" };
  }
  if (/^(https|http|about|file|javascript)$/i.test(scheme)) {
    return { ok: false, reason: "blocked-scheme" };
  }
  return { ok: true, reason: "ready" };
}

console.log(JSON.stringify(canUnregister("mailto", location.origin + "/?to=%s")));
console.log(JSON.stringify(canUnregister("mailto", location.origin + "/?to=")));
console.log(JSON.stringify(canUnregister("https", location.origin + "/?u=%s")));
Try It Yourself

How It Works

Beginner-friendly guards reduce confusing browser exceptions in settings UIs.

Example 5 — Safe Settings Helper

One helper for “Stop handling these links” buttons with clear status codes.

JavaScript
function unregisterHandlerSafe(scheme, url) {
  if (typeof navigator.unregisterProtocolHandler !== "function") {
    return { ok: false, reason: "missing-api" };
  }
  if (!window.isSecureContext) {
    return { ok: false, reason: "insecure-context" };
  }
  if (!url.includes("%s")) {
    return { ok: false, reason: "missing-%s" };
  }
  try {
    navigator.unregisterProtocolHandler(scheme, url);
    return { ok: true, reason: "unregistered-requested" };
  } catch (err) {
    return { ok: false, reason: err.name };
  }
}

const handler = location.origin + "/handler?url=%s";
console.log(JSON.stringify(unregisterHandlerSafe("web+demo", handler)));
Try It Yourself

How It Works

Map reason to user-facing copy: success toast vs “not supported in this browser.”

🚀 Common Use Cases

  • Settings toggles — let users stop opening mailto / tel links in your web app.
  • Account logout / uninstall flow — clean up handlers when the app is no longer preferred.
  • Handler URL changes — unregister the old template before registering a new path.
  • Custom web+ schemes — remove product-specific deep-link handlers.
  • Support docs — show beginners how to reverse registerProtocolHandler().

🧠 How unregisterProtocolHandler() Works

1

User opts out

Settings UI calls unregister with the saved scheme + URL.

Gesture
2

Browser validates

Checks scheme allow-list, %s, HTTPS, and same origin.

Rules
3

Handler removed

Matching registration is cleared when rules pass.

Remove
4

Links fall back

mailto / tel / web+ links return to OS or other handlers.

📝 Notes

Limited Browser Support

navigator.unregisterProtocolHandler() is not Baseline. Support tracks the protocol-handler feature set (strongest in Chromium-based browsers). Always feature-detect, use HTTPS, and keep a clear fallback when the API is missing.

Limited · Not Baseline

Navigator.unregisterProtocolHandler()

Remove a previously registered scheme handler (same URL template).

Limited Not Baseline
Google Chrome Protocol handlers where supported
Limited
Microsoft Edge Follow Chromium support
Limited
Opera Follow Chromium where available
Limited
Mozilla Firefox Check current protocol-handler support
Limited
Apple Safari Typically unavailable — feature-detect
Unavailable
Internet Explorer No modern protocol-handler API
Unavailable
unregisterProtocolHandler() Limited

Bottom line: Detect the method, pass the exact scheme + %s URL used at registration, call from HTTPS same-origin pages, and wrap calls in try/catch.

Conclusion

navigator.unregisterProtocolHandler() is how a web app stops handling a URL scheme. Use the same scheme and %s template you registered, call it on HTTPS from the same origin, and always feature-detect.

Continue with vibrate(), registerProtocolHandler(), or the JavaScript hub.

💡 Best Practices

✅ Do

  • Feature-detect before unregistering
  • Reuse the exact registered URL template
  • Call from HTTPS / same origin
  • Validate %s before calling
  • Offer a clear settings toggle for users

❌ Don’t

  • Assume every browser supports it
  • Change the path and expect the old registration to clear
  • Try to unregister https / about
  • Skip try/catch for SecurityError / SyntaxError
  • Forget to teach registerProtocolHandler()

Key Takeaways

Knowledge Unlocked

Five things to remember about unregisterProtocolHandler()

Limited inverse of registerProtocolHandler — same scheme and %s URL.

5
Core concepts
📊 02

Support

Limited

Not Baseline
🔒 03

Needs

HTTPS

+ same origin
🔗 04

Match

exact URL

Includes %s
05

Errors

Security / Syntax

try/catch

❓ Frequently Asked Questions

It removes a previously registered protocol handler for a given scheme and handler URL template. It is the inverse of navigator.registerProtocolHandler().
No. MDN does not mark it Deprecated, Experimental, or Non-standard. It is Limited availability (not Baseline) and requires a secure context. No status banner is required.
Yes. Pass the same scheme and the same handler URL (including %s) that were used with registerProtocolHandler(). Mismatches will not remove the handler.
Yes. The API is a secure-context feature. The handler URL must also be http/https and same-origin as the page calling unregister.
SecurityError when the scheme is blocked, the origin/https rules fail, or the context is insecure. SyntaxError when %s is missing from the handler URL.
The same permitted list as registration: schemes like mailto, tel, sms, bitcoin, and custom web+… names that follow the lowercase ASCII rules.
Did you know?

Unregistering does not invent a new URL format — browsers look for the same scheme + template pair you registered. Keep that string in one shared constant so register and unregister never drift apart.

Explore vibrate() Next

Add short haptic feedback with the Vibration API.

vibrate() →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

8 people found this page helpful