Skip to content

Instantly share code, notes, and snippets.

@lexisother
Last active January 24, 2026 00:15
Show Gist options
  • Select an option

  • Save lexisother/ba15b9f0a8182934a288e9f583e85047 to your computer and use it in GitHub Desktop.

Select an option

Save lexisother/ba15b9f0a8182934a288e9f583e85047 to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name mediasession fixer
// @version 2026-01-22
// @description fixes my everlasting "missing artist metadata" issue in spotify
// @author Alyxia
// @match https://open.spotify.com/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=spotify.com
// @grant none
// ==/UserScript==
const __FIXER__ = window.__FIXER__ = {};
const FULL_SELECTOR = 'ul[aria-label="Now playing"] [data-encore-id="listRowSubtitle"] > * > :has([href])';
const NOW_PLAYING_SELECTOR = 'ul[aria-label="Now playing"]';
const ARTIST_TEXT_SELECTOR = '[data-encore-id="listRowSubtitle"] > * > :has([href])';
(async function() {
'use strict';
console.log('fixer: init');
while (!(__FIXER__.target = document.querySelector(NOW_PLAYING_SELECTOR))) {
console.log('fixer: waiting');
await new Promise(resolve => setTimeout(resolve, 100));
}
console.log('fixer: done');
// target = document.querySelector('ul[aria-label="Now playing"]');
__FIXER__.observer = new MutationObserver((list) => {
// console.log('handling\n', list);
for (const rec of list) {
if (rec.type === 'childList') {
if (
// This is the previous track being removed
!!(Array.from(rec.removedNodes).length) ||
// This is a record for the addition of the new track before the old one was removed.
// The addedNodes entry here is not fully initialized
!!rec.previousSibling
) continue;
// This is the play/pause button being switched out in the now playing cover art
else if (!!(Array.from(rec.target.classList.values().filter(v => v.match('-button__'))).length)) {
console.log('fixer: handling presumed play/pause');
if (!(__FIXER__.currentArtist = document.querySelector(FULL_SELECTOR))) {
console.log('fixer: play/pause triggered but no current artist found?')
}
if (__FIXER__.currentArtist.innerText && !navigator.mediaSession.metadata.artist) {
navigator.mediaSession.metadata.artist = __FIXER__.currentArtist.innerText;
console.log('fixer: MEDIASESSION SET!', navigator.mediaSession.metadata);
}
return;
}
else {
console.log('fixer: handling presumed new song');
if (!(__FIXER__.newTrack = Array.from(rec.addedNodes)[0])) {
console.warn('fixer: new track started but no track node?')
}
let artistEl = __FIXER__.newTrack.querySelector('[data-encore-id="listRowSubtitle"] > * > :has([href])');
console.log('fixer: artistEl found', artistEl);
if (artistEl.innerText) {
navigator.mediaSession.metadata.artist = artistEl.innerText;
console.log('fixer: MEDIASESSION SET!', navigator.mediaSession.metadata);
}
return;
}
}
}
console.log('\n\n')
});
__FIXER__.observer.observe(__FIXER__.target, { childList: true, subtree: true });
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment