Desktop booru browser. Browse, search, and save images from Danbooru, Gelbooru, e621, and more. Qt6 GUI, cross-platform, fully themeable, zero telemetry. https://git.pax.moe/pax/booru-viewer/releases
Go to file
pax 553e31075d Privacy screen: resume video on un-hide, popout uses in-place overlay
Two related improvements to the Ctrl+P privacy screen flow.

1. Resume video on un-hide

Pre-fix: Ctrl+P paused any playing video in the embedded preview and
the popout, but the second Ctrl+P only hid the privacy overlay — the
videos stayed paused. The user had to manually click Play to resume.

Fix: in _toggle_privacy's privacy-off branch, mirror the privacy-on
pause logic with resume() calls on the embedded preview's video player
and the popout's video. Unconditional resume — if the user manually
paused before Ctrl+P, the auto-resume on un-hide is a tiny annoyance,
but the common case (privacy hides → user comes back → video should
be playing again) wins.

2. Popout privacy uses an in-place overlay instead of hide()

Pre-fix attempt: privacy-on called self._fullscreen_window.hide() and
privacy-off called .show(). On Wayland (Hyprland) the hide→show round
trip drops the window's position because the compositor unmaps the
window on hide and remaps it at the default tile position on show.
A first attempt at restoring the position via a deferred
hyprctl_resize_and_move dispatch in privacy_show didn't take — by
the time the dispatch landed, the window had already been re-tiled
and the move was gated by `if not win.get("floating"): return`.

Cleaner fix: don't hide the popout window at all. FullscreenPreview
gains its own _privacy_overlay (a black QWidget child of central,
parallel to the existing toolbar / controls bar children) that
privacy_hide raises over the media stack. The popout window stays
mapped, position is preserved automatically because nothing moves,
and the overlay covers the content visually.

privacy_hide / privacy_show methods live in FullscreenPreview, not
in main_window — popout-internal state belongs to the popout module.
_toggle_privacy in main_window just calls them. This also makes
adding more popout-side privacy state later (e.g. fullscreen save)
a one-method change inside the popout class.

Also added a _popout_was_visible flag in BooruApp._toggle_privacy so
privacy-off only restores the popout if it was actually visible at
privacy-on time. Without the gate, privacy-off would inappropriately
re-show a popout the user had closed before triggering privacy.

Verified manually:
  - popout open + drag to non-default pos + Ctrl+P + Ctrl+P → popout
    still at the dragged position, content visible again
  - popout open + video playing + Ctrl+P + Ctrl+P → video resumes
  - popout closed + Ctrl+P + Ctrl+P → popout stays closed
  - embedded preview video + Ctrl+P + Ctrl+P → resumes
  - Ctrl+P with no video on screen → no errors
2026-04-08 16:30:37 -05:00
booru_viewer Privacy screen: resume video on un-hide, popout uses in-place overlay 2026-04-08 16:30:37 -05:00
screenshots Update Linux screenshot for 0.2.0 2026-04-06 14:46:59 -05:00
themes Popout: fix first-fit aspect lock race, fill images to window, tighten combo/button padding across all themes 2026-04-07 20:48:09 -05:00
.gitattributes Treat .qss files as CSS for syntax highlighting 2026-04-05 00:51:35 -05:00
.gitignore Ignore *.dll (Windows build artifacts) 2026-04-07 08:51:05 -05:00
CHANGELOG.md Scroll tilt navigates one cell/post in grid, preview, and popout 2026-04-07 08:50:13 -05:00
LICENSE Initial release — booru image viewer with Qt6 GUI and Textual TUI 2026-04-04 06:00:50 -05:00
README.md README: positioning rewrite, Why section, split Bookmarks/Library, theming + backup notes 2026-04-07 18:58:35 -05:00
booru-viewer.spec Fix Windows mpv DLL name: libmpv-2.dll 2026-04-06 13:56:46 -05:00
icon.ico Initial release — booru image viewer with Qt6 GUI and Textual TUI 2026-04-04 06:00:50 -05:00
icon.png Initial release — booru image viewer with Qt6 GUI and Textual TUI 2026-04-04 06:00:50 -05:00
installer.iss Bump version to 0.2.2 2026-04-07 20:00:43 -05:00
pyproject.toml Bump version to 0.2.2 2026-04-07 20:00:43 -05:00

README.md

booru-viewer

A booru client for people who keep what they save and rice what they run.

Qt6 desktop app for Linux and Windows. Browse, search, and archive Danbooru, e621, Gelbooru, and Moebooru. Fully themeable.

If you find this useful, consider buying me a coffee:

Ko-fi

Screenshots

Windows 11 — Light Theme

Windows 11 — Light Theme

Windows 11 — Dark Theme (auto-detected)

Windows 11 — Dark Theme

Windows 10 — Light Theme

Windows 10 — Light Theme

Windows 10 — Dark Theme (auto-detected)

Windows 10 — Dark Theme

Linux — Styled via system Qt6 theme

Linux — System Qt6 theme

Supports custom styling via custom.qss — see Theming.

Why booru-viewer

There are a few other desktop booru clients worth knowing about. ahoviewer is the most mature one. Grabber is the most popular. Hydrus is a full local-first media tagging system that happens to import from boorus, which puts it in a different category entirely.

ahoviewer is the closest to what this is, but its "save" opens a file dialog and dumps the file into a folder you organize yourself. Most ricers who want a daily-driver booru client end up wrestling with Hydrus, scripting Grabber from the CLI, or just keeping browser tabs open.

Two things are different here:

You bookmark and save like you do in a web browser. Bookmark is a pointer. Save actually writes the file. Library items live as 12345.jpg in ~/.local/share/booru-viewer/saved/ and you can open them in Thunar or whatever you use. The difference from ahoviewer is that the tags, source, score, and folder all live in SQLite next to the files. You don't have to invent filenames or build a folder hierarchy. Search by tag, find what you saved. Your images are normal files on disk. If the database breaks, your saves don't go with it.

It's built for tiling Wayland. Hyprland integration with opt-out env vars if you want your own window rules. Wayland app_id set so windowrule = float, class:^(booru-viewer)$ works. The whole UI is themeable through a @palette preprocessor. Six bundled themes ship: Catppuccin, Nord, Gruvbox, Tokyo Night, Everforest, Solarized. Each comes in rounded and square. No other client in the space cares whether you're on GNOME or Hyprland.

Features

booru-viewer has three tabs that map to three commitment levels: Browse for live search against booru APIs, Bookmarks for posts you've starred for later, Library for files you've actually saved to disk.

Browsing

  • Supports Danbooru, e621, Gelbooru, and Moebooru
  • Auto-detect site API type — just paste the URL
  • Tag search with autocomplete, history dropdown, and saved searches
  • Rating and score filtering (server-side score:>=N)
  • Media type filter — dropdown: All / Animated / Video / GIF / Audio
  • Blacklisted tags and posts (client-side filtering with backfill)
  • Thumbnail grid with keyboard navigation, multi-select (Ctrl/Shift+Click, Ctrl+A), bulk context menus, and drag thumbnails out as files
  • Infinite scroll — optional, auto-loads more posts at bottom
  • Start from page — jump to any page number on search
  • Page cache — prev/next loads from memory, no duplicates
  • Copy File to Clipboard — Ctrl+C, works for images and videos

Preview

  • Image viewer with zoom (scroll wheel), pan (drag), and reset (middle click)
  • GIF animation, Pixiv ugoira auto-conversion (zip to animated GIF)
  • Animated PNG/WebP auto-conversion to GIF
  • Video playback via mpv (MP4, WebM, MKV) with play/pause, seek, volume, mute, and seamless looping
  • Info panel with post details, date, clickable tags, and filetype
  • Preview toolbar — Bookmark, Save, BL Tag, BL Post, and Popout buttons above the preview panel

Popout Viewer

  • Right-click preview → "Popout" or click the Popout button in the preview toolbar
  • Arrow keys / h/j/k/l navigate posts (including during video playback)
  • , / . seek 3 seconds in videos, Space toggles play/pause
  • Floating overlay UI — toolbar and video controls auto-hide after 2 seconds, reappear on mouse move
  • F11 toggles fullscreen/windowed, Ctrl+H hides all UI, Ctrl+P privacy screen
  • Window auto-sizes to content aspect ratio; state persisted across sessions
  • Hyprland: keep_aspect_ratio prop locks window to content proportions
  • Bidirectional sync — clicking posts in the main grid updates the popout
  • Video position and player state synced between preview and popout

Bookmarks

  • Bookmark posts you might want later — lightweight pointers in the database, like clicking the star in your browser
  • Group bookmarks into folders, separate from Library's folders
  • Search bookmarks by tag
  • Bulk save, unbookmark, or remove from the multi-select context menu
  • Import/export bookmarks as JSON
  • Unbookmark from grid, preview, or popout

Library

  • Save posts you want to keep — real files on disk in saved/, named by post ID, browsable in any file manager
  • One-click promotion from bookmark to library when you decide to commit
  • Tag search across saved metadata — type to filter by indexed tags, no filename conventions required
  • On-disk folder organization with configurable library directory and folder sidebar — save unsorted or to a named subfolder
  • Sort by date, name, or size
  • Video thumbnail generation (ffmpeg if available, placeholder fallback)
  • Unsave from grid, preview, and popout (only shown when post is saved)
  • Unreachable directory detection
  • Inline history dropdown inside the search bar
  • Saved searches with management dialog
  • Click empty search bar to open history
  • Session cache mode clears history on exit (keeps saved searches)

Install

Windows

Download booru-viewer-setup.exe from Releases and run the installer. It installs to AppData with Start Menu and optional desktop shortcuts. To update, just run the new installer over the old one — your data in %APPDATA%\booru-viewer\ is preserved.

Windows 10 dark mode is automatically detected and applied.

Linux

Requires Python 3.11+ and pip. Most distros ship Python but you may need to install pip and the Qt6 system libraries.

Arch / CachyOS:

sudo pacman -S python python-pip qt6-base mpv ffmpeg

Ubuntu / Debian (24.04+):

sudo apt install python3 python3-pip python3-venv mpv libmpv-dev ffmpeg

Fedora:

sudo dnf install python3 python3-pip qt6-qtbase mpv mpv-libs-devel ffmpeg

Then clone and install:

git clone https://git.pax.moe/pax/booru-viewer.git
cd booru-viewer
python3 -m venv .venv
source .venv/bin/activate
pip install -e .

Run it:

booru-viewer

Or without installing: python3 -m booru_viewer.main_gui

Desktop entry: To add booru-viewer to your app launcher, create ~/.local/share/applications/booru-viewer.desktop:

[Desktop Entry]
Name=booru-viewer
Exec=/path/to/booru-viewer/.venv/bin/booru-viewer
Icon=/path/to/booru-viewer/icon.png
Type=Application
Categories=Graphics;

Hyprland integration

I daily-drive booru-viewer on Hyprland and I've baked in my own opinions on how the app should behave there. By default, a handful of hyprctl dispatches run at runtime to:

  • Restore the main window's last floating mode + dimensions on launch
  • Restore the popout's position, center-pin it around its content during navigation, and suppress F11 / fullscreen-transition flicker
  • "Prime" Hyprland's per-window floating cache at startup so a mid-session toggle to floating uses your saved dimensions
  • Lock the popout's aspect ratio to its content so you can't accidentally stretch mpv playback by dragging the popout corner

If you're a ricer with your own windowrules targeting class:^(booru-viewer)$ and you'd rather the app keep its hands off your setup, there are two independent opt-out env vars:

  • BOORU_VIEWER_NO_HYPR_RULES=1 — disables every in-code hyprctl dispatch except the popout's keep_aspect_ratio lock. Use this if you want app-side window management out of the way but you still want the popout to size itself to its content.
  • BOORU_VIEWER_NO_POPOUT_ASPECT_LOCK=1 — independently disables the popout's aspect ratio enforcement. Useful if you want to drag the popout to whatever shape you like (square, panoramic, monitor-aspect, whatever) and accept that mpv playback will letterbox or stretch to match.

For the full hands-off experience, set both:

[Desktop Entry]
Name=booru-viewer
Exec=env BOORU_VIEWER_NO_HYPR_RULES=1 BOORU_VIEWER_NO_POPOUT_ASPECT_LOCK=1 /path/to/booru-viewer/.venv/bin/booru-viewer
Icon=/path/to/booru-viewer/icon.png
Type=Application
Categories=Graphics;

Or for one-off launches from a shell:

BOORU_VIEWER_NO_HYPR_RULES=1 booru-viewer

Dependencies

  • Python 3.11+
  • PySide6 (Qt6)
  • httpx
  • Pillow
  • python-mpv
  • mpv (system package on Linux, bundled DLL on Windows)

Keybinds

Grid

Key Action
Arrow keys / h/j/k/l Navigate grid
Ctrl+A Select all
Ctrl+Click / Shift+Click Multi-select
Home / End Jump to first / last
Scroll tilt left / right Previous / next thumbnail (one cell)
Ctrl+C Copy file to clipboard
Right click Context menu

Preview

Key Action
Scroll wheel Zoom (image) / volume (video)
Scroll tilt left / right Previous / next post
Middle click / 0 Reset view
Arrow keys / h/j/k/l Navigate posts
, / . Seek 3s back / forward (video)
Space Play / pause (video, hover to activate)
Right click Context menu (bookmark, save, popout)

Popout

Key Action
Arrow keys / h/j/k/l Navigate posts
Scroll tilt left / right Previous / next post
, / . Seek 3s (video)
Space Play / pause (video)
Scroll wheel Volume up / down (video)
F11 Toggle fullscreen / windowed
Ctrl+H Hide / show UI
Ctrl+P Privacy screen
Escape / Q Close popout

Global

Key Action
Ctrl+P Privacy screen
F11 Toggle fullscreen

Adding Sites

File > Manage Sites. Enter a URL, click Auto-Detect, and save.

API credentials are optional — needed for Gelbooru and rate-limited sites.

Tested Sites

  • danbooru.donmai.us
  • gelbooru.com
  • rule34.xxx
  • safebooru.donmai.us
  • safebooru.org
  • e621.net

Theming

The app uses your OS native theme by default. To customize, copy a .qss file from the themes/ folder to your data directory as custom.qss:

  • Linux: ~/.local/share/booru-viewer/custom.qss
  • Windows: %APPDATA%\booru-viewer\custom.qss

A template is also available in Settings > Theme > Create from Template.

Included Themes

Each theme ships in two variants: *-rounded.qss (4px corner radius) and *-square.qss (no corner radius except radio buttons). Same colors, different geometry.

Nord Catppuccin Mocha

Gruvbox Solarized Dark

Tokyo Night Everforest

Settings

  • General — page size, thumbnail size, default site, default rating/score, prefetch mode (Off / Nearby / Aggressive), infinite scroll, popout monitor, file dialog platform
  • Cache — max cache size, max thumbnail cache, auto-evict, clear cache on exit (session-only mode)
  • Blacklist — tag blacklist with toggle, post URL blacklist
  • Paths — data directory, cache, database, configurable library directory
  • Theme — custom.qss editor, template generator, CSS guide
  • Network — connection log showing all hosts contacted this session

Data Locations

Linux Windows
Database ~/.local/share/booru-viewer/booru.db %APPDATA%\booru-viewer\booru.db
Cache ~/.local/share/booru-viewer/cache/ %APPDATA%\booru-viewer\cache\
Library ~/.local/share/booru-viewer/saved/ %APPDATA%\booru-viewer\saved\
Theme ~/.local/share/booru-viewer/custom.qss %APPDATA%\booru-viewer\custom.qss

To back up everything: copy saved/ for the files themselves and booru.db for bookmarks, folders, and tag metadata. The two are independent — restoring one without the other still works. The saved/ folder is browsable on its own in any file manager, and the database can be re-populated from the booru sites for any post IDs you still have on disk.

Privacy

booru-viewer makes no connections except to the booru sites you configure. There is no telemetry, analytics, update checking, or phoning home. All data stays local on your machine.

Every outgoing request is logged in Settings > Network so you can verify this yourself — you will only see requests to the booru API endpoints and CDNs you chose to connect to.

License

MIT