microsoft-edge: Application Protocol
Microsoft Edge implements an Application Protocol with the scheme
microsoft-edge: that is designed to launch Microsoft Edge and pass along a web-schemed URL and/or additional arguments. A basic invocation might be as simple as:
However, as is often the case with things I choose to write about, there’s a bit of hidden complexity that may not be immediately obvious.
The purpose of this URL scheme is to enable Windows and cooperating applications to invoke particular user-experiences in the Edge browser.
This scheme is not considered “public” — there’s no official documentation of the scheme, and the Edge team makes no guarantees about its behavior. We can (and do) add or modify functionality as needed to achieve desired behaviors.
Over the last few years, we’ve added a variety of functionality to the scheme, including the ability to invoke UX features, launch into a specific user profile, and implement other integration scenarios. By way of example, Windows might advertise the Edge Surf game and, if the user chooses to play, the game is launched by ShellExecuting the URL
Because of the non-public and inherently unstable (not backward-compatible) nature of this URL scheme, it is not an extensibility point and it is not supported to configure the handler to be anything other than Microsoft Edge.
Under the hood: handling of this scheme can be found in Edge’s non-public version of the StartupBrowserCreator::ProcessCmdLineImpl function I wrote about recently as a part of my post on Chromium Startup.
One (perhaps surprising) restriction on the
microsoft-edge scheme is that it cannot be launched from inside Edge itself. If a user inside Edge clicks a link to the
microsoft-edge: scheme, nothing visibly happens. Only if they open the F12 Console will they see an error message:
microsoft-edge protocol is blocked inside Edge itself to avoid “navigation laundering” problems, whereby going through the external handler path would result in loss of context. Losing the context of a navigation can introduce vulnerabilities in both security and abuse. For example, a popup blocker bypass existed on Android when Android Chrome failed to block the Chrome version of this protocol. The Edge WebView2 control also blocks navigation to the protocol, although I expect that an application which wants to allow it can probably do so with the appropriate event handlers.
Another tricky bit concerns the fact that a user may have multiple different channels of Edge (Stable, Beta, Dev, Canary) installed, but the
microsoft-edge protocol can only be claimed by one of them. This can be potentially confusing if a user has different channels selected to handle
…because some links will open in Edge Canary while others will open in Edge Beta.
edge: Built-In Scheme
Beyond the aforementioned application protocol, Microsoft Edge also supports a Built-In Scheme named
edge: and in contrast to the
microsoft-edge: application protocol, this scheme is only available within the browser. You can not invoke an
edge: URL elsewhere in Windows, or pass it to Edge as a command-line argument.
edge: scheme is simply an alias for the
about schemes used in Chromium to support internal pages like
about:settings, and similar (see
edge:about for a list).
For security reasons, regular webpages cannot navigate to or load subresources from the
edge/chrome schemes. Years ago, a common exploit pattern was to navigate to
chrome:downloads and then abuse its privileged WebUI bindings to escape the browser sandbox. There are also special debug urls like
about:inducebrowsercrashforrealz that will do exactly as they say.
2 thoughts on “Edge URL Schemes”
“… there’s a bit of hidden complexity …” None of this would be necessary if Microsoft just honored the user’s default browser choice in all contexts. If I want to launch Edge, then I’ll specifically launch Edge.
Indeed, this is a common criticism. The challenge is that not all browsers offer the same features (e.g. launching into particular profiles, prefetches, etc) and thus it’s not possible to just hand any given invocation to an arbitrary browser with the confidence that the right things will happen. This is, in some ways, similar to a problem I’ve written about previously: There’s no standard way for a native app to POST data via the user’s default browser https://textslashplain.com/2020/02/05/app-to-web-communication-launching-web-apps/