Default browser not used from within Snap?

KDE uses its own non-standard system for default web browser, while flatpak/snap applications use portals that use only XDG spec via glib. Here’s an XDG spec-friendly way to set default browser (with firefox as example):
xdg-mime default firefox.desktop x-scheme-handler/http
xdg-mime default firefox.desktop x-scheme-handler/https

Apparently, someone should talk to KDE folks that they should finally standardize their extensions or stop using them, that mime incompatiblity across DEs is really annoying.


I’m also seeing this behavior on Gnome 40.5.0. My default browser is set to Chrome, but our Electron-based classic confinement snap opens external links in Firefox. xdg-open <url> opens Chrome. All of the following return google-chrome.desktop:

xdg-settings get default-web-browser
xdg-settings get default-url-scheme-handler http
xdg-settings get default-url-scheme-handler https
xdg-mime query default x-scheme-handler/http
xdg-mime query default x-scheme-handler/https

The Electron app is opening the browser like this (which apparently delegates to xdg-open on Linux Electron builds):

import {shell} from 'electron';

Interestingly this only occurs when the app is built with classic confinement. When the app is built with strict confinement the same code opens Chrome (although for other reasons we unfortunately need to use classic). I’ve also seen this behavior across multiple distros including my Gentoo laptop and a Ubuntu VM. Any other ideas for workarounds?

Check gio mime x-scheme-handler/http, gio mime x-scheme-handler/https and gio open. It uses the same library portals are using to find default handler.


Thanks for the suggestions @ilya-fedin. I just checked the gio settings, and they all appear to be defaulting to Chrome as well, although Firefox is listed first under Recommended applications. Executing either gio open '' or gio open '' both launch Chrome.

$ gio mime x-scheme-handler/http
Default application for “x-scheme-handler/http”: google-chrome.desktop
Registered applications:
Recommended applications:

$ gio mime x-scheme-handler/https
Default application for “x-scheme-handler/https”: google-chrome.desktop
Registered applications:
Recommended applications:

Check whether flatpak permissions has desktop-used-apps for http/https, that would be preferred if xdg-desktop-portal version is less than 1.8.0

1 Like

OK I tried flatpak permissions, flatpak permission-list, and flatpak permission-list xdg-desktop-portal, but none of these returned any output (I’m not very familiar with flatpak though, so I might have gotten something wrong with the commands there).

As far as system packages, and I have xdg-desktop-portal v1.10.1 and xdg-desktop-portal-gtk v1.8.0

Oh, I re-read your post and found this. Apparently, these apps don’t use portals and don’t read your MIME associations due to some wrappers that redefine $HOME for them.

1 Like

I have the same issue on Kubuntu 20.04 with two different apps: Telegram and JetBrains WebStorm. They were installed one without --classic and another one with it. Now whenever I try to open an URL from them, they open Firefox, while the default browser is set to Chrome (in KDE System Settings and as well in xdg-open)

Only gio shows it’s Firefox, however I don’t get how Gnome might by related, as this is KDE.

So… after 2 years, does have any solution to this weird problem?

Portals are using glib, so snap apps will use whatever gio gives you

Ah, will they! Interesting. So the question now is how to update these settings. I.e. how to set the correct values to gio mime. I’m gonna google for it and post a feedback. And it’s gonna be the final answer, not yet provided.

gio is an implementation of the XDG standard, so you can use commands from Default browser not used from within Snap?.

1 Like

Oh, thank you!

So the answer to this question was given in that comment! And this worked for me:

xdg-mime default google-chrome.desktop x-scheme-handler/http
xdg-mime default google-chrome.desktop x-scheme-handler/https

But it’s a little strange as:

xdg-mime query default x-scheme-handler/http

returned google-chrome.desktop even before.

Anyways, I marked your comment with “heart” and it’s just the second one, while it’s actually THE answer and should be appreciated.


xdg-utils call DE’s executables for commands and KDE’s one check whether queried mimetype is x-scheme-handler/http(s) and returns the value from KDE’s non-standard config rather than real mimetype association according to the XDG spec. xdg-utils is a collection of heavy bugged shell scripts.


Thanks. Indeed it shows firefox for me. How do I change gio settings?

This helped. Thanks Ilya.

$ gio mime x-scheme-handler/https google-chrome.desktop
Set google-chrome.desktop as the default for x-scheme-handler/https
$ gio mime x-scheme-handler/http google-chrome.desktop
Set google-chrome.desktop as the default for x-scheme-handler/http

Cross posting my solution as I walked on this thread and others may find it useful:

From my investigation it looks like the Snap creates extra XDG “environment” and due to this default user configuration doesn’t work as expected. Also the browser is run with it’s own profile.

Apparently clearing two environment variables (XDG_DATA_HOME, XDG_CONFIG_HOME) before invoking xdg-open brings the expected behavior.

No idea what’s the correct fix for this as I’m too familiar with Snap ideology in relation to environment separation but the hacky solution works. The workaround script (build specifically for obsidian):



# fix for obsidian opening URLs in wrong browser
if [[ $SNAP_INSTANCE_NAME == "obsidian" && $1 =~ ^(https?://) ]]; then
        unset XDG_DATA_HOME
        unset XDG_CONFIG_HOME

exec /usr/bin/xdg-open "$@"

The ~/bin must be on PATH for it to work.

DISCLAIMER: There may be some unexpected downsides coming from this solution. It wasn’t tested very deeply. USE AT YOUR OWN RISK. Maybe there is better solution but this piece of “duct tape” solved my case :wink:

You can find more details here:


please make sure that the Electron app is properly configured xdg-open to open and manage the URLs.

The obsidian snap appears to be a classic confined snap, so issues with it are likely to be different to strict confined snaps as they run in very different environments (there is no sandboxing for classic).

Using environment variables to control behaviour of classic confined snaps is known to cause problems if it goes on to execute programs not belonging to the snap. This is one of the reasons for all the code in Snapcraft set up to help classic snaps use use DT_RPATH to find libraries rather than the LD_LIBRARY_PATH environment variable.

So the fix here would be for obsidian to figure out how to do what it needs to without overriding those XDG_* environment variables.

Things work differently for strict confined snaps, since they can’t directly execute programs outside of their sandbox: the /usr/bin/xdg-open they see is a proxy that asks a helper outside the sandbox to open the app on their behalf. There is no environment variable pollution problems in this situation.

1 Like

It could be worth making a custom xdg-open implementation, I have a quick hack for one of my snaps that works in strict because it falls back to letting snapd handle it if my naive hack isn’t needed. The snap would need to specifically call $SNAP/bin/xdg-open but being a snap you’re guaranteed to have it there. I can’t remember if there’s a way to override Electron to use it without modifying $PATH however.

I’d be happy to rewrite that with some actual standards that means it would work in classic though I’d probably not have the time in the next week since I’m currently in the mood of joyriding my new car so the computer stuff is taking a backseat (pun intended, but also not true, because being a new car I’m still applying firmware updates to the computer in it!).

You’d effectively be forcing the xdg-desktop-portals to be a mandatory part of the users host installation but we heavily encourage that people have those installed regardless for general snap use, so it might not be that problematic, and in theory you could have a fallback in the wrapper to use the real xdg-open if the portals fail, which if done properly, would mean modifying $PATH even in classic wouldn’t be too problematic; but potentially still fiddly to avoid ending up with infinite recursion of the wrapper calling itself.

Plus, the idea of Joplin helping Obsidian makes me laugh in a nerdy way ;).

1 Like

If you want to always call the portal API, libportal is another option to look at. That could be done either in-process or to implement a helper.