YouTube Music (Free) — A Custom Music Assistant Provider with Optional Library Sync

It is well established within the Music Assistant community that YouTube Music integration has presented a number of persistent challenges. The official provider requires Premium credentials and, following Google’s deprecation of OAuth authentication, relies on a somewhat fragile cookie-based setup that additionally necessitates a PO Token Generator add-on. Free-tier accounts remain unsupported entirely.

In light of these constraints, I would like to present an alternative provider — YouTube Music (Free) — which I have developed as an open-source contribution to the Home Assistant ecosystem. The provider is designed around two complementary principles: first, that basic music playback should function without any authentication whatsoever; and second, that users who do wish to access their personal library may optionally authenticate via browser cookies.

Core architecture. The provider leverages ytmusicapi for search and metadata operations alongside yt-dlp with the Android Music client for stream extraction. This particular client configuration does not require PO tokens, login sessions, or Premium subscriptions — the same technique employed by established open-source projects such as NewPipe and SimpMusic.

What works without authentication:

  • Search across tracks, albums, artists, and playlists
  • Audio streaming (128–256 kbps AAC/Opus)
  • Artist discographies and top tracks
  • Similar tracks / song radio
  • Playlist playback (with yt-dlp fallback for restricted playlists)

What authentication unlocks:

  • Library synchronization — liked songs, saved albums, playlists, and a combined view of subscribed and library artists
  • Personalized recommendations from the YouTube Music home feed
  • Library management — adding and removing items directly from Music Assistant
  • Brand account support for users whose YouTube Music libraries reside on a secondary Google account

The authentication mechanism warrants brief elaboration. The provider accepts a browser cookie and constructs a SAPISIDHASH-based authorization header, which ytmusicapi requires for browser-type authentication detection. The implementation ensures graceful degradation: should the cookie expire or prove invalid, the provider falls back to anonymous mode rather than failing outright.

Installation follows the standard pattern for custom MA providers — the files are copied into the Music Assistant container and a companion watcher add-on is provided to automate reinstallation across Home Assistant restarts.

The complete source, documentation, and watcher add-on configuration are available at: GitHub - sproft/music-assistant-ytmusic: Stream YouTube Music without a premium subscription via Music Assistant · GitHub

I welcome any feedback, bug reports, or contributions. It bears noting that this provider interacts with YouTube’s unofficial APIs in a manner that contravenes their Terms of Service, and users should be cognisant of this when choosing to deploy it.

Thanks for putting this together, @sproft. This is a solid piece of work. Works like a charm! :smiley:

Great job, thank you for sharing!
I was wondering whether it is possible to install it in HAOS (i.e. without the possibility to create an additional container)

Thanks for the kind words. I am not sure I understand your question correctly.

This should work in HAOS you don’t need to create a container yourself. The provider files are copied into the existing Music Assistant add-on container using docker cp, and the included watcher add-on automates that on every HA restart.

Everything runs inside the official MA container, no extra containers needed.

Setup is just:

  1. Drop the ytmusic_free folder into /config/custom_components/mass/providers/
  2. Install the watcher add-on from WATCHER_ADDON.md (runs as a standard local HAOS add-on)
  3. Disable Protection Mode on the watcher so it can access the Docker socket

Full instructions are in the README and WATCHER_ADDON.md.

I personally have it running in a VM that runs HAOS and it works perfectly.

Was this answer in any way helpful?

Thank you! Just a quick question are you using it with the authentication?

Because I wanted to get some feedback whether that part works for other people as well. I am using a brand account and didn’t have any issues, but I didn’t do any testing with other types of youtube music accounts.

Nice.
But the install sounds like a PITA.
There is no chance this will ever get adopted as an official Add-on right?
Do you plan to create a full installer script that automates the whole process? With 1 line of code?

P. s current Nightly Builds use Python 3.14!

I agree :slight_smile: I can't understand this installation process but - I have no experience with MA. I use LMS, and they have an "official" plugin for free youtube, which worked great, but became problematic after they switched to yt-dlp (sound distortion and HA instability on my thin PC with Proxmox). I'd gladly try MA and this one if only the installation seemed clearer.

2026-05-10 13:33:00.389 INFO (MainThread) [music_assistant.YouTube Music (Free)] Config updated, reloading provider ytmusic_free (instance_id=ytmusic_free)
2026-05-10 13:33:02.526 INFO (MainThread) [music_assistant.ytmusic_free] YouTube Music (Free) initialized with cookie authentication — library sync enabled
2026-05-10 13:33:02.526 INFO (MainThread) [music_assistant] Loaded music provider YouTube Music (Free)

That means it should work right?
Because the quick Picks are full of bullshit ^^

Edit: Lol okay, i'm actually on a "Brand" account...

Maybe you could enhance the Readme that the "ID" is in the Url on the google Account settings. And not in the Page anywhere.
https://myaccount.google.com/brandaccounts/THISISYOURIDRIGHTHERE/view

P.S Any plans on Updating the Icon so it looks similar to Youtube and not just like a Playlist?

Just add any svg named icon.svgto ytmusic_free folder..

<svg role="img" viewBox="0 0 512 512" fill="#FF0000" xmlns="http://www.w3.org/2000/svg">

  <title>YouTube Music</title>

<path

d="M256 0C114.688 0 0 114.688 0 256s114.688 256 256 256 256 -114.688 256 -256S397.312 0 256 0m0 407.552c-83.712 0 -151.552 -67.84 -151.552 -151.552S172.288 104.448 256 104.448s151.552 67.84 151.552 151.552 -67.84 151.552 -151.552 151.552m0 -284.416c-73.216 0 -132.864 59.648 -132.864 132.864S182.784 388.864 256 388.864s132.864 -59.648 132.864 -132.864S329.216 123.136 256 123.136M206.592 331.52V180.48L337.408 256z" />

</svg>

after using the "Start Radio" function on a Youtube song it works fine.
But few tunes later it looses all Media Info.
Instead of Title shows youtube ID when playing.


Heyo, thanks for the feedback.

Yeah the installation is a pain. I was doing this project for myself and was fine with installing everything manually.
Afterwards, i thought there might be other people that could use this and he we are.

I can try working on an automated install script, but could be difficult, because of the need to mess with docker. So I am not sure how to get around the requirement to open a command line with docker access. But I can try next week after I am back from vacation.

Now about making it an official integration. There are tons of Issues like the Music Assistant github

and their official stands seems to be: "If it doesn't play ads, we will not support it."

That was the reason I made this.

Thanks for this solution, I wasn't keen on adding any official youtube©™ icons into my repo. @Haldi If you can find one that is copyright free, I will gladly add it.

That is interesting. Can you open a github Issue with details of how long it takes to break and some logs after breakage? P.S. l made the readme clearer for the brand account stuff.

works amazingly well, thank you!

Is there a way to automatically renew the cookie when it expires?
Also, the playback is showing as Low Quality even though I ticked the Prefer Highest Quality

Side issues:

  • yt playlists don't show in MA Playlists. I have to go to Browse>Youtube Music (Free)>Playlists to see them
  • Once I add one of those playlists to Library, then go to Browse>Youtube Music (Free)>Playlists. The only Playlists that show up are the ones I added to Library
  • If I delete those playlists I had added to Library so I can still see them in Browse>Youtube Music (Free)>Playlists, then nothing shows in Browse anymore, not Artists, Playlists, Albums etc.
    I've tried reloading, re-enabling the YTM Free from Music Source. Re-Adding Cookie. Nothing works and I can't see what's in my personal account anymore

Thanks, for liking the project the detailed report.

I hope I can be of some help.

Cookie auto-renewal: Not currently. Browser cookies are tied to your Google session and there's no programmatic way to refresh them without re-authenticating in a browser. The good news: cookies are valid for ~2 years as long as you don't log out of YouTube Music. OAuth would handle this automatically, but Google deprecated OAuth for YouTube Music in late 2024.

Low Quality label: That "LQ" indicator in MA is based on what MA reports back from the stream metadata, not the actual bitrate. The android_music client we use returns 128–256 kbps AAC/Opus, which MA categorizes as "low quality" regardless of the toggle. The toggle controls yt-dlp's format selector (m4a/bestaudio/best vs worstaudio/worst), with it on, you're getting the best available audio. The label is just MA being strict about what counts as "high quality" (typically lossless / hi-res).

Side issues: likely related to library sync state. A few things to try:

  1. Playlists not showing in MA Playlists section: Go to Settings → Music sources → YouTube Music (Free) → Sync/import options and make sure "Sync Library Playlists" is enabled.

Here are the settings I use.

  1. Disappearing browse after deleting library items: This sounds like a state corruption issue. Could you check the MA add-on logs after triggering a library sync? Run:

    docker logs addon_d5369777_music_assistant 2>&1 | grep -i "ytmusic_free\|library sync\|youtube music" | tail -30
    

    Specifically I'd like to see if get_library_* methods are being called and what they return.

  2. As a reset: Try removing the provider entirely from MA, restarting MA (docker restart addon_d5369777_music_assistant), then re-adding it with your cookie. This forces a clean library state.

If the issue persists, please open a bug report in the github page with the logs and I'll dig in. Also worth confirming: is your YouTube Music library on a brand account? If so, double-check the Brand account ID field is filled correctly.

Hi, Hope I done this correctly.
It was actually ha addons logs d5369777_music_assistant | grep -i "ytmusic_free\|library sync\|youtube music" | tail -30 because I'm using terminal addon

I'm also getting this in MA log

026-05-13 02:26:03.033 INFO (MainThread) [music_assistant.streams.audio] Start Queue Flow stream for Queue JBL PartyBox @ BT_Bridge - crossfade: disabled 
<!DOCTYPE html>
<!--[if lt IE 7]> <html class="no-js ie6 oldie" lang="en-US"> <![endif]-->
<!--[if IE 7]>    <html class="no-js ie7 oldie" lang="en-US"> <![endif]-->
<!--[if IE 8]>    <html class="no-js ie8 oldie" lang="en-US"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en-US"> <!--<![endif]-->
<head>
<title>kfam.win | 524: A timeout occurred</title>
<meta charset="UTF-8" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
<meta name="robots" content="noindex, nofollow" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<link rel="stylesheet" id="cf_styles-css" href="/cdn-cgi/styles/main.css" />
</head>
<body>
<div id="cf-wrapper">
    <div id="cf-error-details" class="p-0">
        <header class="mx-auto pt-10 lg:pt-6 lg:px-8 w-240 lg:w-full mb-8">
            <h1 class="inline-block sm:block sm:mb-2 font-light text-60 lg:text-4xl text-black-dark leading-tight mr-2">
                <span class="inline-block">A timeout occurred</span>
                <span class="code-label">Error code 524</span>
            </h1>
            <div>
                Visit <a href="https://www.cloudflare.com/5xx-error-landing?utm_source=errorcode_524&utm_campaign=kfam.win" target="_blank" rel="noopener noreferrer">cloudflare.com</a> for more information.
            </div>
            <div class="mt-3">2026-05-12 16:30:13 UTC</div>
        </header>
        <div class="my-8 bg-gradient-gray">
            <div class="w-240 lg:w-full mx-auto">
                <div class="clearfix md:px-8">
                    <div id="cf-browser-status" class=" relative w-1/3 md:w-full py-15 md:p-0 md:py-8 md:text-left md:border-solid md:border-0 md:border-b md:border-gray-400 overflow-hidden float-left md:float-none text-center">
  <div class="relative mb-10 md:m-0">
    <span class="cf-icon-browser block md:hidden h-20 bg-center bg-no-repeat"></span>
    <span class="cf-icon-ok w-12 h-12 absolute left-1/2 md:left-auto md:right-0 md:top-0 -ml-6 -bottom-4"></span>
  </div>
  <span class="md:block w-full truncate">You</span>
  <h3 class="md:inline-block mt-3 md:mt-0 text-2xl text-gray-600 font-light leading-1.3">
    Browser
  </h3>
  <span class="leading-1.3 text-2xl text-green-success">Working</span>
</div>
                    <div id="cf-cloudflare-status" class=" relative w-1/3 md:w-full py-15 md:p-0 md:py-8 md:text-left md:border-solid md:border-0 md:border-b md:border-gray-400 overflow-hidden float-left md:float-none text-center">
  <div class="relative mb-10 md:m-0">
    <a href="https://www.cloudflare.com/5xx-error-landing?utm_source=errorcode_524&#38;utm_campaign=kfam.win" target="_blank" rel="noopener noreferrer">
    <span class="cf-icon-cloud block md:hidden h-20 bg-center bg-no-repeat"></span>
    <span class="cf-icon-ok w-12 h-12 absolute left-1/2 md:left-auto md:right-0 md:top-0 -ml-6 -bottom-4"></span>
    </a>
  </div>
  <span class="md:block w-full truncate">Sydney</span>
  <h3 class="md:inline-block mt-3 md:mt-0 text-2xl text-gray-600 font-light leading-1.3">
  <a href="https://www.cloudflare.com/5xx-error-landing?utm_source=errorcode_524&utm_campaign=kfam.win" target="_blank" rel="noopener noreferrer">
    Cloudflare
  </a>
  </h3>
  <span class="leading-1.3 text-2xl text-green-success">Working</span>
</div>
                    <div id="cf-host-status" class="cf-error-source relative w-1/3 md:w-full py-15 md:p-0 md:py-8 md:text-left md:border-solid md:border-0 md:border-b md:border-gray-400 overflow-hidden float-left md:float-none text-center">
  <div class="relative mb-10 md:m-0">
    <span class="cf-icon-server block md:hidden h-20 bg-center bg-no-repeat"></span>
    <span class="cf-icon-error w-12 h-12 absolute left-1/2 md:left-auto md:right-0 md:top-0 -ml-6 -bottom-4"></span>
  </div>
  <span class="md:block w-full truncate">kfam.win</span>
  <h3 class="md:inline-block mt-3 md:mt-0 text-2xl text-gray-600 font-light leading-1.3">
    Host
  </h3>
  <span class="leading-1.3 text-2xl text-red-error">Error</span>
</div>
                </div>
            </div>
        </div>
        <div class="w-240 lg:w-full mx-auto mb-8 lg:px-8">
            <div class="clearfix">
                <div class="w-1/2 md:w-full float-left pr-6 md:pb-10 md:pr-0 leading-relaxed">
                    <h2 class="text-3xl font-normal leading-1.3 mb-4">What happened?</h2>
                    <p class="mb-2">The origin web server timed out responding to this request.</p><p>The likely cause is an overloaded background task, database or application, stressing the resources on the host web server.</p>
                </div>
                <div class="w-1/2 md:w-full float-left leading-relaxed">
                    <h2 class="text-3xl font-normal leading-1.3 mb-4">What can I do?</h2>
              <h3 class="text-15 font-semibold mb-2">If you're a visitor of this website:</h3>
              <p class="mb-6">Please try again in a few minutes.</p>
              <h3 class="text-15 font-semibold mb-2">If you're the owner of this website:</h3>
              <p>Please refer to the <a rel="noopener noreferrer" href="https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-5xx-errors/error-524/">Error 524</a> article:</p>
              <ul class="ml-4">
                <li>Contact your hosting provider; check for long-running processes or an overloaded web server.</li>
                <li>Use status polling of large HTTP processes to avoid this error.</li>
                <li>Run the long-running scripts on a <a rel="noopener noreferrer" href="https://developers.cloudflare.com/dns/proxy-status/#dns-only-records">grey-clouded subdomain</a>.</li>
                <li>Enterprise customers can <a rel="noopener noreferrer" href="https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-5xx-errors/error-524/#resolution-on-cloudflare">increase the timeout setting</a> globally or for specific requests using Cache Rules.</li>
              </ul>
                </div>
            </div>
        </div>
        <div class="cf-error-footer cf-wrapper w-240 lg:w-full py-10 sm:py-4 sm:px-8 mx-auto text-center sm:text-left border-solid border-0 border-t border-gray-300">
    <p class="text-13">
      <span class="cf-footer-item sm:block sm:mb-1">Cloudflare Ray ID: <strong class="font-semibold">9faacb77b87b182f</strong></span>
      <span class="cf-footer-separator sm:hidden">&bull;</span>
      <span id="cf-footer-item-ip" class="cf-footer-item hidden sm:block sm:mb-1">
        Your IP:
        <button type="button" id="cf-footer-ip-reveal" class="cf-footer-ip-reveal-btn">Click to reveal</button>
        <span class="hidden" id="cf-footer-ip">202.172.97.223</span>
        <span class="cf-footer-separator sm:hidden">&bull;</span>
      </span>
      <span class="cf-footer-item sm:block sm:mb-1"><span>Performance &amp; security by</span> <a rel="noopener noreferrer" href="https://www.cloudflare.com/5xx-error-landing?utm_source=errorcode_524&#38;utm_campaign=kfam.win" id="brand_link" target="_blank">Cloudflare</a></span>
    </p>
    <script>(function(){function d(){var b=a.getElementById("cf-footer-item-ip"),c=a.getElementById("cf-footer-ip-reveal");b&&"classList"in b&&(b.classList.remove("hidden"),c.addEventListener("click",function(){c.classList.add("hidden");a.getElementById("cf-footer-ip").classList.remove("hidden")}))}var a=document;document.addEventListener&&a.addEventListener("DOMContentLoaded",d)})();</script>
  </div><!-- /.error-footer -->
    </div>
</div>
</body>
 Live

This could be a potential bug. Be fore I try to fix this. I have some follow up questions, but I don't want to bore the people here. We can continue the conversation there:

But the quick questions are:

  1. Did you enable the Sync Library Playlists in the options?

  2. Have you done a reinstall, before posting this error log?

Thanks for your help.

I'm not a pro on hat. But what I've seen from others wouldn't we simply need "curl www.Github.com/path/toinstall/script.sh" and then instantly run that said script. As a one liner to copy& past and run.
Inside that we download the repo with curl or wget into the current active folder, then use the copy into docker command. Maybe even docker PS with grep for music assistant before that.
Or something like that.

Okay, I was playing around and have now added an install script that should maybe work.

Let me know if something is off. Readme is also updated with new instructions.

You can try the new automated installer. Let me know if it works.