Music tagger for DJs. Point it at a folder, and it fills in artist, title, BPM, key, genre, label, release date and album art from 12 music platforms. Then you fix whatever it got wrong, by hand or with keyboard shortcuts. Written in Rust, Vue 3 and Quasar.
This is a fork of Marekkon5/onetagger, currently 49 commits ahead. The original project is abandoned in practice, so the fixes users were waiting for are applied here instead.
Works with mp3, flac, aif, aiff, m4a, mp4, wav, ogg, opus, spx and oga files.
OneTagger.mp4
Upstream went quiet while the app was broken. The state of it on 30 July 2026:
| Last release | 1.7.0, published 3 August 2023 |
Last commit on master |
13 February 2026, 167 days ago |
| Commits in the past 12 months | 9 |
| Open pull requests / issues | 6 / 146 |
Then the thing that actually hurt: Beatport removed the __NEXT_DATA__ script tag from its search pages, and OneTagger scraped that tag to find tracks. Beatport and Beatsource matching died. Two contributors sent working fixes in May 2026 (#523, #526). Both are still unmerged, while issue #486 fills up with users who cannot tag a single file. Asked about the three-year release gap, the maintainer answered "mostly personal reasons and lack of time".
The repository is not archived and the odd commit still lands, but nothing reaches users. So this fork takes the working patches, drops the broken ones, and fixes what the merges damaged.
| Change | Why |
|---|---|
| Beatport and Beatsource search on the official v4 catalog API | The old HTML scraper broke. This uses an OAuth client-credentials token against api.beatport.com/v4, no DOM parsing. |
| Stop button works during rate limit waits | Every platform slept out its rate limit and ignored the stop flag, up to 600 seconds for Spotify. Waits now wake in 100ms steps and abandon the retry. |
macOS ._* sidecar files skipped |
On exFAT and NTFS volumes macOS writes an AppleDouble file next to every track. They carry an audio extension and no audio, so each came back as a failed match. One test folder held 127. |
| Stopping a run says so | A stopped run showed the same "Tagging finished" dialog as a completed one, which made the stop button look dead when it was working fine. |
| Juno Download restored | One of the merged pull requests deleted the platform with no reason given, months after upstream had fixed its scraper. |
| Audio Features disabled in the UI | Spotify shut down the audio features endpoint, so audio_features() upstream is a stub that always errors. The tab is greyed out instead of failing on every file. |
| ID3 date frames, duplicate custom tags, album art files | Merged from #526: dates in a shape DJ software reads, no duplicated custom tags, cover files only written when you asked. |
wss:// behind an HTTPS proxy |
The client hardcoded ws://, which mixed-content-blocked the websocket. Merged from #521. |
| Docker image for headless use | Merged from #522, then fixed: it built the client with Node 18 and the updated client needs 20.19 or newer. |
Three upstream pull requests were rejected: #523 (narrower than #526, and it added an npm lockfile to a pnpm project), #517 (a rival Dockerfile), #476 (pure reformatting, conflicting since 2025).
No binaries are published for this fork, so build from source. Upstream's 1.7.0 download still has the broken Beatport scraper in it.
You need rustup, Node 20.19 or newer (22.12+ on the 22 line), and pnpm 8.
git clone https://github.com/sakej/onetagger.git
cd onetagger
sudo apt install -y lld autogen libasound2-dev pkg-config make libssl-dev gcc g++ curl wget git libwebkit2gtk-4.1-dev
cd client && pnpm i && pnpm run build && cd ..
cargo build --release
The GUI lands in target/release/onetagger, the CLI in target/release/onetagger-cli. Only the GUI crate needs libwebkit2gtk-4.1-dev, so for the CLI alone drop it and build cargo build --release -p onetagger-cli.
Same toolchain, plus the Visual Studio 2019 Build Tools:
cd client
pnpm i
pnpm run build
cd ..
cargo build --release
Output goes to target\release.
| Tab | What it does |
|---|---|
| Auto Tag | Matches your files against the platforms below and writes the tags. Shazam fingerprinting covers files with no usable tags or filename, by hashing a 12 second slice at 16 kHz. |
| Quick Tag | Keyboard-driven mood, genre, energy and note tagging for a whole folder. |
| Edit Tags | Manual tag editor with a file browser. |
| Auto Rename | Renames files from their tags using a template. |
| Audio Features | Disabled. Spotify removed the endpoint it depended on. |
Twelve platforms ship built in, in the order Auto Tag tries them: Beatport, Traxsource, Beatsource, Juno Download, Spotify, MusicBrainz, Discogs, iTunes, BPM Supreme, Bandcamp, Deezer, Musixmatch.
Nine talk to a real API. Three still parse HTML (Traxsource, Bandcamp, Juno Download), which is how the Beatport breakage happened. You can also drop third-party platforms in as native plugins (.dll, .so, .dylib), or install them from the platform repo, whose manifest URL is compiled into repo.rs and still points upstream.
- Not a rewrite. It tracks upstream and stays a clean superset of it, 49 commits on top of
master. - No published builds. GitHub Actions has never run here, so there are no artifacts to download.
- No Android build, even though the code carries an Android data-dir hook.
- Not a home for Audio Features. Spotify deleted the API; nothing on this side brings it back.
The image builds onetagger-cli only, with no GUI, webkit or gtk dependencies, and serves the embedded web UI over plain HTTP on port 36913. The client picks ws:// or wss:// from the page protocol, so one image works behind an HTTP or an HTTPS proxy.
docker compose build # or: docker build -t onetagger-local .
Three stages: node:22-bookworm-slim builds the Vue client (bookworm's own nodejs is 18, too old for Vite 8), rust:1-bookworm compiles the CLI, and debian:bookworm-slim runs it with only libasound2, libssl3 and ca-certificates installed. The result is a 243 MB image, about two minutes of cargo build on a warm cache.
mkdir -p data/config && sudo chown -R 1000:1000 data/config
docker compose up -d
docker compose logs -f
docker-compose.yml publishes to 127.0.0.1:36913 only, mounts ./data/config and ./music, and runs with read_only, tmpfs /tmp, cap_drop: ALL, no-new-privileges and user: 1000:1000.
Without compose:
docker run -d --name onetagger \
-p 127.0.0.1:36913:36913 \
-v "$(pwd)/data/config:/home/onetagger/.config/onetagger" \
-v /path/to/your/music:/music \
--user 1000:1000 --read-only --tmpfs /tmp \
--cap-drop ALL --security-opt no-new-privileges:true \
onetagger-local:latest
The port is a compile-time constant (onetagger_shared::PORT), so remap it on the host rather than looking for a flag: -p 127.0.0.1:8080:36913.
Config lives at /home/onetagger/.config/onetagger, the standard XDG path on Linux. Tokens, autotagger profiles and custom platform settings sit there, so keep that volume across rebuilds.
The image creates the onetagger user at UID and GID 1000. Pass --user $(id -u):$(id -g) to write tags as your host user; the numeric ID does not need to exist inside the container.
ENTRYPOINT is onetagger-cli and the default command is server --expose. The three flags server takes:
| Flag | Effect |
|---|---|
-e, --expose |
Binds 0.0.0.0:36913. Required in a container, since the default 127.0.0.1 bind is unreachable from the host. |
-p, --path <PATH> |
Initial path in the UI folder picker, for example --path /music. |
-b, --browser |
Opens a browser. Pointless in a container. |
Any other subcommand runs against the same image:
docker run --rm -v /path/to/music:/music onetagger-local:latest autotagger --path /music
autotagger, renamer and authorize-spotify all work this way. Print a starting config with onetagger-cli --autotagger-config.
The container speaks plain HTTP. Terminate TLS at Caddy, Nginx or Traefik, forward to 127.0.0.1:36913, and pass websocket upgrades on /ws through:
location / {
proxy_pass http://127.0.0.1:36913;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
Marek Kon (Marekkon5) wrote OneTagger. Bas Curtiz did the UI and the idea. Shazam support comes from SongRec.
Support the original author on PayPal or Patreon.
- onetagger.github.io for tutorials and tag docs. Written for 1.7.0, still accurate apart from Audio Features.
- CHANGELOG.md for the release history and what this fork changed.
- Marekkon5/onetagger is the upstream project. Pull request and issue links above point there because that is where they live.
Licensed GPL-3.0, same as upstream. See LICENSE.
