$linuxjunkies
>

XDG Desktop Portals Explained

Learn what XDG Desktop Portals do, how to install the right backend for GNOME, KDE, or wlroots, and how to fix common screen sharing and file picker failures.

IntermediateUbuntuDebianFedoraArch9 min readUpdated June 7, 2026

Before you start

  • A working Wayland or X11 desktop session
  • sudo or root access to install packages
  • PipeWire installed and running (required for screen sharing)
  • Flatpak installed if you want to test with PortalTest

XDG Desktop Portals are the standardized bridge between sandboxed applications—primarily Flatpaks, but also Snaps and any app that opts in—and privileged desktop services like screen capture, file selection, and power management. Without them, a Flatpak running inside its sandbox cannot open a native file chooser, share your screen, or prevent your screensaver from activating. Portals expose a D-Bus API that apps call, and a backend implementation translates that call into whatever your desktop environment actually provides. Get the wrong backend installed, and things silently break in confusing ways.

How Portals Work

The portal architecture has two layers. The front-end is xdg-desktop-portal, a D-Bus service at org.freedesktop.portal.* that any app can call regardless of sandbox. The back-end is a separate package specific to your desktop environment—it receives the request from the front-end and does the real work using native DE APIs. The front-end and back-end communicate over a private D-Bus interface.

When a Flatpak calls the FileChooser portal, the sequence is:

  1. App sends a D-Bus request to org.freedesktop.portal.FileChooser.
  2. xdg-desktop-portal picks the correct backend based on the current desktop.
  3. The backend (e.g., xdg-desktop-portal-gnome) opens a native GTK file chooser.
  4. The user picks a file; the portal hands back only that file's path to the sandbox.

The app never gains broad filesystem access—it only gets what the user explicitly granted through the portal dialog.

Choosing the Right Backend

Each major desktop environment ships its own backend. Using the wrong one causes missing dialogs, broken screen sharing, or silent failures.

DesktopPackageNotes
GNOMExdg-desktop-portal-gnomeRequired for GNOME 43+; replaces the older gtk backend
KDE Plasmaxdg-desktop-portal-kdeProvides native KDE dialogs; required for KWin screen sharing
wlroots compositors (Sway, Hyprland, Wayfire)xdg-desktop-portal-wlrHandles screen sharing via wlroots wlr-screencopy protocol
XFCE / LXDE / genericxdg-desktop-portal-gtkGood fallback; uses GTK dialogs
Budgie, Cinnamon, MATExdg-desktop-portal-gtkNo dedicated backend; gtk works well
LXQtxdg-desktop-portal-lxqtAvailable in most repos since 2023

You can have multiple backends installed simultaneously. The front-end chooses based on the DESKTOP_SESSION or XDG_CURRENT_DESKTOP environment variable, and you can override the selection with a config file (covered below).

Installing Portals

Debian / Ubuntu

sudo apt install xdg-desktop-portal xdg-desktop-portal-gnome
# KDE instead
sudo apt install xdg-desktop-portal xdg-desktop-portal-kde
# wlroots compositors
sudo apt install xdg-desktop-portal xdg-desktop-portal-wlr

Fedora / RHEL / Rocky

sudo dnf install xdg-desktop-portal xdg-desktop-portal-gnome
# KDE
sudo dnf install xdg-desktop-portal xdg-desktop-portal-kde
# wlroots
sudo dnf install xdg-desktop-portal xdg-desktop-portal-wlr

Arch Linux

sudo pacman -S xdg-desktop-portal xdg-desktop-portal-gnome
# KDE
sudo pacman -S xdg-desktop-portal xdg-desktop-portal-kde
# wlroots (Sway, Hyprland)
sudo pacman -S xdg-desktop-portal xdg-desktop-portal-wlr

Key Portal Interfaces

FileChooser

The most commonly encountered portal. When a sandboxed app needs to open or save a file, it calls org.freedesktop.portal.FileChooser. The backend opens your desktop's native picker, and only the chosen path is returned to the app. No backend running means the app either crashes, shows a blank dialog, or—worse—silently fails to open any file at all.

ScreenCast and RemoteDesktop

Screen sharing in apps like Firefox, Chromium, OBS, and Teams on Wayland works entirely through org.freedesktop.portal.ScreenCast. On Wayland there is no global screen grabbing API, so portals are the only sanctioned path. The flow is:

  1. App requests a ScreenCast session via the portal.
  2. A picker dialog lets you choose a window or entire screen.
  3. The compositor hands back a PipeWire stream node ID.
  4. The app reads video frames from PipeWire—never directly from the display server.

This requires PipeWire to be running. On modern GNOME and KDE installations it runs by default. On wlroots compositors you may need to start it manually or via your session manager.

# Verify PipeWire is active
systemctl --user status pipewire pipewire-pulse

Inhibit

org.freedesktop.portal.Inhibit lets apps request that the system not suspend, dim, or lock the screen. A video player preventing screen blanking during playback is the canonical use-case. This portal has no visible UI—it either works silently or the screensaver kicks in anyway.

Notification

org.freedesktop.portal.Notification allows sandboxed apps to post desktop notifications through the native notification daemon. If Flatpak notifications are missing, a missing or misconfigured backend is the first thing to check.

Configuring Backend Selection

From xdg-desktop-portal 1.15+ you can explicitly map portal interfaces to specific backends using a config file. This is especially useful on wlroots compositors that don't set XDG_CURRENT_DESKTOP to a recognized value, or when you have multiple backends and want fine-grained control.

Create the config at ~/.config/xdg-desktop-portal/portals.conf:

mkdir -p ~/.config/xdg-desktop-portal
nano ~/.config/xdg-desktop-portal/portals.conf

A typical config for Sway (wlroots screen sharing, GTK file picker):

[preferred]
default=gtk
org.freedesktop.portal.ScreenCast=wlr
org.freedesktop.portal.RemoteDesktop=wlr

For Hyprland, which sets XDG_CURRENT_DESKTOP=Hyprland, the same approach works but you may want xdg-desktop-portal-hyprland (available in the AUR and some distro repos) which is a maintained fork of xdg-desktop-portal-wlr with Hyprland-specific fixes.

After editing, restart the portal service:

systemctl --user restart xdg-desktop-portal

Verifying Portals Are Working

The flatpak-portal-test tool from the Flatpak team is the clearest way to confirm portals are functional:

flatpak install flathub org.freedesktop.PortalTest
flatpak run org.freedesktop.PortalTest

Each button in the PortalTest UI exercises one portal interface. A successful FileChooser test opens your native file picker; a successful ScreenCast test starts a PipeWire stream.

You can also inspect what's running on D-Bus directly:

busctl --user list | grep freedesktop.portal

Expected output shows entries for org.freedesktop.portal.Desktop and at least one backend. If you see nothing, the service is not running—check the next section.

Troubleshooting

Portal service not starting

The front-end service is socket-activated via systemd user units. Check its status and logs:

systemctl --user status xdg-desktop-portal
journalctl --user -u xdg-desktop-portal -n 50

A common cause is a stale socket from a prior session. Kill the service and restart it:

systemctl --user stop xdg-desktop-portal
systemctl --user start xdg-desktop-portal

Screen sharing is a black screen or fails to start

On Wayland, confirm PipeWire is running and that XDG_CURRENT_DESKTOP is set correctly in your session. For wlroots compositors, this variable is often not set automatically—add it to your compositor's config or session startup file:

# For Sway: add to ~/.config/sway/config
exec dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP=sway

Wrong backend is being used

If both xdg-desktop-portal-gnome and xdg-desktop-portal-gtk are installed, the front-end may pick the wrong one on non-GNOME desktops. Use the portals.conf method above to pin the backend explicitly, or remove the conflicting package.

Flatpak app ignores the portal file picker

Some older Flatpaks use a bundled GTK filechooser rather than the portal API. Check whether the app respects the --talk-name=org.freedesktop.portal.FileChooser Flatpak permission. If not, this is an upstream app bug—file a report with the app maintainer.

tested on:Ubuntu 24.04Fedora 40Arch rollingDebian 12

Frequently asked questions

Do portals only matter for Flatpaks?
Primarily yes, but any app that opts into the portal API benefits from them. Electron apps, Snaps, and even some native apps use portals for Wayland screen sharing and notifications.
Why does screen sharing work in X11 but break on Wayland?
X11 allows any process to read the entire display directly. Wayland forbids this by design, so screen sharing must go through the ScreenCast portal backed by PipeWire. If the portal or PipeWire is misconfigured, sharing fails entirely.
Can I use xdg-desktop-portal-gtk on GNOME as a fallback?
It was the standard backend before GNOME 43, but on modern GNOME you should use xdg-desktop-portal-gnome. The gtk backend lacks support for newer portal interfaces like dynamic launchers and account information.
How do I tell which backend is actually handling a portal call?
Run 'journalctl --user -u xdg-desktop-portal -f' while triggering the portal action. The log shows which backend was selected and any errors that occurred during the call.
My compositor is not listed anywhere—what backend should I use?
Install xdg-desktop-portal-gtk as a generic fallback for file picker, notifications, and inhibit. For screen sharing on any wlroots-based compositor, add xdg-desktop-portal-wlr and map the ScreenCast interface to it in portals.conf.

Related guides