[READ-ONLY] Mirror of https://github.com/FoxxMD/multi-scrobbler. Scrobble plays from multiple sources to multiple clients docs.multi-scrobbler.app
deezer docker jellyfin koito lastfm listenbrainz maloja mopidy mpris music music-assistant plex scrobble self-hosted spotify subsonic tautulli youtube-music
0

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request #506 from FoxxMD/musicAssistant

Music assistant

authored by

Matt Foxx and committed by
GitHub
(Mar 29, 2026, 7:30 PM EDT) 3f19abb8 e716de21

+80 -18
+66 -17
docsite/docs/configuration/sources/listenbrainz-endpoint.mdx
··· 9 9 import CodeBlock from '@theme/CodeBlock'; 10 10 import ListenbrainzEndpointConfig from '!!raw-loader!@site/../config/endpointlz.json.example'; 11 11 12 - This Source enables multi-scrobbler to accept scrobbles from outside applications as if it was a Listenbrainz server. 12 + This Source enables multi-scrobbler to accept scrobbles from outside applications **as if it was a Listenbrainz server.** 13 + 14 + If your service/player has a "Scrobble to Listenbrainz" feature and there is an option to set the Listenbrainz URL then multi-scrobbler can accept scrobbles from that service/player by imitating a real Listenbrainz server. 13 15 14 16 :::tip[Other Uses] 15 17 ··· 17 19 * To monitor and re-scrobble activity from your Listenbrainz account, create a [Listenbrainz (Source)](/configuration/sources/listenbrainz-source) 18 20 19 21 ::: 22 + 23 + ## Setup 20 24 21 25 ### URL 22 26 23 - If a **slug** is **not** provided in configuration then multi-scrobbler will accept Listenbrainz scrobbles at 27 + In general, you should use one of the following as the **base URL** when configuring your application to scrobble to multi-scrobbler: 28 + 29 + * `http://myMultiScrobblerIP:9078` 30 + * `http://myMultiScrobblerIP:9078/1/` 31 + 32 + <DetailsAdmo type="tip" summary="Default Scrobble Submit URL"> 33 + 34 + If you are not using a [slug for multiple endpoints](#multiple-endpoints) then multi-scrobbler will accept Listenbrainz scrobbles at 24 35 25 36 ``` 26 37 http://myMultiScrobblerIP:9078/1/submit-listens 27 38 ``` 28 39 29 - which is the "standard" Listenbrainz server path for scrobbling. 40 + which is the **standard** Listenbrainz server path for scrobbling. 41 + 42 + </DetailsAdmo> 30 43 31 - In general, you should use `http://myMultiScrobblerIP:9078/1/` as the **base path** when configuring your application to scrobble to multi-scrobbler. 44 + <DetailsAdmo type="note" summary="Some Services Require HTTPS"> 45 + 46 + Some services that can scrobble to a custom Listenbrainz URL may require the URL to have a real domain (`example.com`) and/or use SSL (`https://`). In this case you should setup multi-scrobbler behind a reverse proxy to support this functionality. It is out of the scope of this project to do this solely within multi-scrobbler. 47 + 48 + </DetailsAdmo> 49 + 50 + ### Token 51 + 52 + Most Listenbrainz clients require a token (Authentication Token) to be provided during setup. This value can be anything you want, just make sure to use the same value for `token` in your multi-scrobbler configuration for the endpoint. 53 + 54 + ### Multiple Endpoints 55 + 56 + If you are setting up multiple [Listenbrainz (Endpoint) Sources](/configuration/sources/listenbrainz-endpoint) MS can differentiate scrobbles based on [Token](#token) so that you can use the same endpoint for many users. 57 + 58 + However, if you cannot configure multiple tokens for your scenario you may also use a URL **Slug** to tell MS which Source belongs to a specific user. 32 59 33 60 <details> 34 61 35 - <summary>URL Setup for Popular Apps</summary> 62 + <summary>Using a Slug</summary> 63 + 64 + When a **slug** is defined in ENV/File config MS will listen for listenbrainz routes using the slug as a the route path. Example: 65 + 66 + ``` 67 + LZE_SLUG=foobar 68 + ``` 69 + 70 + MS will accept calls to 71 + 72 + ``` 73 + http://myMultiScrobblerIP:9078/api/listenbrainz/foobar 74 + ``` 75 + 76 + for scrobble submission. 77 + 78 + </details> 79 + 80 + ## Setup for Popular Apps 36 81 37 - ##### Navidrome 82 + ### Navidrome 83 + 84 + <details> 38 85 39 86 Set the [**ListenBrainz.BaseURL**](https://www.navidrome.org/docs/usage/configuration-options/#advanced-configuration) (env `ND_LISTENBRAINZ_BASEURL`) to `http://myMultiScrobblerIP:9078/1/` 40 87 41 88 </details> 42 89 43 - Use a slug only if you need to setup multiple Listenbrainz Endpoint sources and cannot use different tokens. 90 + ### Music Assistant 44 91 45 - If a slug is used then the URL will be: 92 + <details> 46 93 47 - ``` 48 - http://myMultiScrobblerIP:9078/api/listenbrainz/mySlug 49 - ``` 50 - 51 - :::note 52 - Some Listenbrainz applications may require custom Listenbrainz URLs to be a real domain (`example.com`) and/or use SSL (`https://`). In this case you should setup multi-scrobbler behind a reverse proxy to support this functionality. It is out of the scope of this project to do this solely within multi-scrobbler. 53 - ::: 94 + [Music Assistant Docs](https://www.music-assistant.io/plugins/listenbrainz_scrobble/) 54 95 55 - ### Token 96 + * In your Music Assistant UI navigate to **Settings** -> **Plugins** 97 + * Click **Add a plugin** 98 + * Add **ListenBrainz Scrobbler** 99 + * In the ListenBrainz Scrobbler configuration screen: 100 + * User Token is the [Token](#token) you configured 101 + * Toggle **Show advanced settings** 102 + * Base URL is the [URL](#url) you can configured, or the equivalent of `http://myMultiScrobblerIP:9078` for your MS instance 103 + * Save the configuration and you are ready to scrobble 56 104 57 - Most Listenbrainz clients require a token (Authentication Token) to be provided during setup. This value can be anything you want, just make sure to use the same value for `token` in your multi-scrobbler configuration for the endpoint. 105 + To troubleshoot any errors, and assuming you are using Home Assistant, view the Logs in the Music Assistant Add-ons. Please include these logs in any reported issue. 58 106 107 + </details> 59 108 60 109 ## Configuration 61 110
+1
docsite/docs/index.mdx
··· 31 31 * [MPD (Music Player Daemon)](/configuration/sources/mpd) 32 32 * [MPRIS (Linux Desktop)](/configuration/sources/mpris) 33 33 * [Musikcube](/configuration/sources/musikcube) 34 + * [Music Assistant](/configuration/sources/listenbrainz-endpoint#setup-for-popular-apps) 34 35 * [Plex](/configuration/sources/plex) 35 36 * [Rocksky](/configuration/sources/rocksky-source) 36 37 * [Sonos](/configuration/sources/sonos)
+13 -1
src/backend/server/endpointListenbrainzRoutes.ts
··· 8 8 import { nonEmptyBody } from "./middleware.js"; 9 9 import { isDebugMode } from "../utils.js"; 10 10 11 + const TEXT_WILDCARD_REGEX = new RegExp(/text\/.+/); 12 + 11 13 export const setupLZEndpointRoutes = (app: ExpressWithAsync, parentLogger: Logger, scrobbleSources: ScrobbleSources) => { 12 14 13 15 const logger = childLogger(parentLogger, ['Ingress', 'Listenbrainz']); 14 16 15 17 const lzJsonParser = bodyParser.json({ 16 - type: ['text/*', 'application/json'], 18 + type: (req) => { 19 + // either Music Assistant, or the library it uses (libmusicbrainz), 20 + // does not send a content-type header so we need to YOLO these requests 21 + if(req.headers["content-type"] === undefined) { 22 + return true; 23 + } 24 + if(TEXT_WILDCARD_REGEX.test(req.headers["content-type"]) || req.headers["content-type"].includes('application/json')) { 25 + return true; 26 + } 27 + return false; 28 + }, 17 29 }); 18 30 const nonEmptyCheck = nonEmptyBody(logger, 'LZ Endpoint'); 19 31