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.
Metadata
Release files for listenbrainz-scrobbler 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| listenbrainz_scrobbler-0.2.0.tar.gz | 66.3 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| listenbrainz_scrobbler-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 83.0 kB
Release files / listenbrainz_scrobbler-0.2.0.tar.gz
| Download URL | listenbrainz_scrobbler-0.2.0.tar.gz |
|---|---|
| Size | 66.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2d56aa39d1fa3f150e3ba1b95cd2989d3335d882dc1bbd223cc0e85a2fbe9ac3
|
|
BLAKE2b-256 checksum How to use checksums |
2dcee3ad256131ea6d94ea0d70db71a359bf9f12ad480c6acec23708d8470294
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is 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}
|
Release files / listenbrainz_scrobbler-0.2.0-py3-none-any.whl
| Download URL | listenbrainz_scrobbler-0.2.0-py3-none-any.whl |
|---|---|
| Size | 16.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e504fd157754ca60123ea9b0cff982e0127bf1121264d38617dcfe67211bb373
|
|
BLAKE2b-256 checksum How to use checksums |
6402a8695f21624f98dc3883e76d77675661d34008d40d26b67135684da9cdf1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is 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}
|
Security for listenbrainz-scrobbler 0.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.