This is a very hacky solution to copy Liked songs to a playlist since YTM still doesn't have the functionality. I'm using this to copy songs out of YTM to another service, then unsubscribing. Thus, I won't be maintaining it (or ever using it again). It will only work while the YTM interface is the same as it is today (3/6/21) and will break once they make updates.
Steps to use:
- Create a new playlist
- Go to your Likes page (in chrome, on a desktop or laptop). Scroll to the bottom so all songs are loaded
- Open Chrome's dev tools (F12 on windows), go to the console
- Paste the script below. Edit the first line, replace "YOUR_PLAYLIST_NAME" with your playlist's name
- Press enter
If it's working, you will see it log out the song titles and (1 of x).
let TARGET_PLAYLIST = "YOUR_PLAYLIST_NAME";
let songElements = document.querySelectorAll(
"#contents > .ytmusic-playlist-shelf-renderer"
);
let addToPlaylistXpath = "//yt-formatted-string[text()='Add to playlist']";
let playlistXpath = `//yt-formatted-string[text()='${TARGET_PLAYLIST}']`;
function isHidden(element) {
return element.offsetParent === null;
}
function waitForElementToDisplay(xpath, callback) {
const timeout = 5000
const checkFrequency = 30
var startTimeInMs = Date.now();
(function loopSearch() {
const element = document.evaluate(
xpath,
document,
null,
XPathResult.FIRST_ORDERED_NODE_TYPE,
null
).singleNodeValue;
if (element && !isHidden(element)) {
callback(element);
return;
} else {
setTimeout(function () {
if (timeout && Date.now() - startTimeInMs > timeout) return;
loopSearch();
}, checkFrequency);
}
})();
}
function copySong(songElement, index) {
const dotsElement = songElement.querySelector("#button");
const songTitle = songElement.querySelector(".yt-simple-endpoint").textContent;
console.log(`Copying: ${songTitle} (${index} of ${songElements.length})`);
// click dot action menu
dotsElement.click();
waitForElementToDisplay(addToPlaylistXpath, (addToPlaylistElement) => {
// click "Add to playlist"
addToPlaylistElement.click();
waitForElementToDisplay(playlistXpath, (playlistElement) => {
// click target playlist
playlistElement.click();
document.body.click();
// call function again
if (index <= songElements.length) {
const nextIndex = index + 1;
copySong(songElements[nextIndex], nextIndex);
}
});
});
}
copySong(songElements[0], 0)
Hey @ChrisPrefect! I made this for YouTube Music, not YouTube. I would not expect this to work on YouTube since the script looks for specific HTML to interact with and that would vary between the apps (I'm not even sure if it is working for YTM anymore).
Sorry this won't work for what you need, good luck!