listenbrainz-scrobbler
Automatically submit Apple Music listens on macOS to ListenBrainz, including streamed songs outside your library.
Setup
On macOS, install uv, then install the PyPI package with Python 3.13:
uv tool install --python 3.13 listenbrainz-scrobbler
lb-scrobbler install --dry-run
lb-scrobbler status
If uv reports that its executable directory is missing from PATH, run uv tool update-shell and restart your shell. For a declaratively managed service, use Nix / Home Manager.
Play a song and allow the background Python process to control Music when macOS asks. Check status for fresh observations and an advancing playback position. If access is denied, enable it in System Settings → Privacy & Security → Automation, then reinstall the agent. A successful foreground probe may still require a separate permission for the background service.
After the dry run works, quit other scrobblers to avoid duplicate submissions. Save your ListenBrainz token in the login Keychain:
lb-scrobbler auth
lb-scrobbler install
For an existing SmashTunes setup, lb-scrobbler auth --from-smashtunes explicitly transfers its stored ListenBrainz token into this service's Keychain entry after validating it. Neither command prints the token. Do not put tokens in command arguments, project files, or Git.
install starts the service immediately and at future logins. Keep the uv tool installation in place: the service depends on its Python environment. Avoid installing the service through temporary uvx environments. Python upgrades may require fresh macOS Automation or Keychain consent.
To upgrade, restart the agent against the updated tool environment:
lb-scrobbler stop
uv tool upgrade listenbrainz-scrobbler
lb-scrobbler install
Operation
lb-scrobbler probe # Read Music without submitting
lb-scrobbler status # Last observation and submission queue
lb-scrobbler stop # Stop until reinstalled or the next login
lb-scrobbler uninstall # Remove the launch agent
lb-scrobbler retry # Retry retained failures after fixing their cause
lb-scrobbler run --dry-run runs in the foreground. Stop the LaunchAgent first, since only one process may own the playback tracker.
State and logs live in ~/Library/Application Support/listenbrainz-scrobbler/. Queued listens are stored there with user-only permissions. The submission token is held separately in login Keychain under xyz.hakula.listenbrainz-scrobbler. Uninstalling the agent preserves both the queue and Keychain entry.
The current song appears on ListenBrainz as soon as playback is observed. Pausing or stopping playback clears this service's playing-now notification. These temporary updates are not saved as listening history and are discarded when playback changes. If the service is stopped or offline, an existing notification remains until ListenBrainz expires it.
A listen is submitted after observing half a track or four minutes of playback, whichever comes first, following ListenBrainz's submission rule. Pauses, seeks, and observation gaps longer than ten seconds do not contribute listening time. Starting the service halfway through a song does not credit playback it did not observe.
Failed submissions stay queued with their original timestamps. Network and server errors are retried automatically. Inspect other failures with status, fix their cause, then run retry. After changing the token, restart the agent. For a manual installation, run lb-scrobbler install. A crash during submission can occasionally cause a duplicate listen.
Dry runs never submit listens.
Limits
Only playback observed on this Mac is captured. There is no history import or iPhone synchronization.
Polling cannot distinguish a natural repeat from manually seeking from the very end to the very beginning. It also cannot identify different recordings with identical title, artist, and album metadata. Track-start timestamps are estimated from the observed position, so seeking before the first observation can skew that estimate. Missing metadata is skipped.
Nix / Home Manager
Add a versioned flake input such as github:hakula139/listenbrainz-scrobbler/v0.2.0, then import the module in your Home Manager configuration:
imports = [ inputs.listenbrainz-scrobbler.homeManagerModules.default ];
services.listenbrainz-scrobbler.enable = true;
Home Manager replaces the manual installer's LaunchAgent under the same label while preserving the queue and Keychain token. Activate Home Manager, then check lb-scrobbler status to confirm the agent loaded and observations are fresh. The package path changes, so macOS may request Automation or Keychain access again. Use lb-scrobbler auth if no token is stored yet.
The LaunchAgent starts at user login after a reboot, when Music and the login Keychain are available. Home Manager owns its lifecycle after migration, so use it for configuration changes instead of the manual install and uninstall commands. After changing the token, restart the loaded agent with launchctl kickstart -k "gui/$(id -u)/xyz.hakula.listenbrainz-scrobbler". Disable the module and reactivate Home Manager to remove it. The existing Keychain entry keeps credentials outside the Nix store.
See the changelog for release changes. GitHub releases also provide wheels, source archives, and checksums.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file listenbrainz_scrobbler-0.2.0.tar.gz.
File metadata
- Download URL: listenbrainz_scrobbler-0.2.0.tar.gz
- Upload date:
- Size: 66.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.12.13 {"installer":{"name":"uv","version":"0.12.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2d56aa39d1fa3f150e3ba1b95cd2989d3335d882dc1bbd223cc0e85a2fbe9ac3
|
|
| MD5 |
11b9b9c4b1f7dd9ddb50c9c3c9120301
|
|
| BLAKE2b-256 |
2dcee3ad256131ea6d94ea0d70db71a359bf9f12ad480c6acec23708d8470294
|
File details
Details for the file listenbrainz_scrobbler-0.2.0-py3-none-any.whl.
File metadata
- Download URL: listenbrainz_scrobbler-0.2.0-py3-none-any.whl
- Upload date:
- Size: 16.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.12.13 {"installer":{"name":"uv","version":"0.12.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e504fd157754ca60123ea9b0cff982e0127bf1121264d38617dcfe67211bb373
|
|
| MD5 |
1c7dc0b47e01444d9173b9bf1b8360ba
|
|
| BLAKE2b-256 |
6402a8695f21624f98dc3883e76d77675661d34008d40d26b67135684da9cdf1
|