Skip to content

Instantly share code, notes, and snippets.

@KnoBuddy
Forked from TheOnlyWayUp/README.md
Last active March 14, 2025 22:18
Show Gist options
  • Save KnoBuddy/9498ec7fd6cf9a32f8bc530ef43cfb57 to your computer and use it in GitHub Desktop.
Save KnoBuddy/9498ec7fd6cf9a32f8bc530ef43cfb57 to your computer and use it in GitHub Desktop.
Like all songs in a Youtube Music Playlist

This script likes all the songs in a Youtube Music Playlist at once.

Use at own risk!

  • There has been at least one user that complained that their account was suspended because "YouTube thought I was doing "Fake Engagement" by automating likes."
  • I have successfully transferred over 700 song likes between accounts with this method, and have hundreds more to go. Will definitely update if I am suspended or have negative consequences.
  • It may be advisable to vary the length of time between likes randomly between 10-100 seconds, but that would inscrease the script time extravagantly, so this feature has not been implemented at this time.

Instructions:

If you navigate to the Liked playlist from the homepage of the Android app (I assume iOS has a similar functionality), you can long-press the liked playlist and select Save to playlist. Name the playlist and make sure Public is selected. (You have to create a channel for the public option to appear; it will prompt you if you don't already have one created).

Head over to your Library and click the three dots icon next to the playlist you just created of your likes, and share the link/copy it, however you can, to get to a Chrome browser. (I used the Google QuickShare app on Windows, but this should work the same on iOS assuming the app allows for creating playlists from liked music). You could simply email your new Google account the link as well.

Head over to music.youtube.com on your computer and make sure you are signed into the account you want to copy the playlist to. Enter the public playlist link you copied earlier, then click the three dots and save the playlist to your new Google account. (URL looks like: https://music.youtube.com/playlist?list=...)

How to use the script

  • If you have an extremely large playlist, you will need to use the scrollbar several times to get it to load as many songs as possible into the webpage. I've noticed a limit of about ~1000 tracks and if your playlist is larger you will have to run this script multiple times and follow the steps over and over until all songs are liked.
  • Press ctrl + shift + j. This opens the Developer Console.
  • Copy the script in this gist (That's in music.youtube.com-playlist-liker.js) at the bottom of this page. Or if you prefer a possibly safer and longer method you can try the music.youtube.com-playlist-liker-random-intervals.js script as well.
  • I suggest clicking the raw button at the top right, using CTRL + A to select all then copy.
  • Paste the code into the Developer Console you just opened on the music.youtube.com Tab, hit enter.
  • Great, now wait until the script runs.
  • If large numbers of songs are in the playlist expect to wait 10 seconds multiplied by the total of the songs in the playlist. This means hundreds or thousands of songs are going to take hours.
  • There is also a cap on the number of songs that can be displayed (~1000) in the window in music.youtube.com, so be prepared to repeat the process after doing lots of scrolling and then running the script and refreshing the window and scrolling and trying again if your playlist is longer than 1000 songs.

Changes I've Made:

  1. likeNext Function: This function is responsible for processing each song one by one.
  2. Conditionally Engage Wait: If a song is already liked (aria-pressed="true"), it skips the wait period and moves to the next song immediately.
  3. Wait Only for Unliked Songs: The wait period is only applied when a song is actually liked.
  4. Timer Initialization: The script initializes a startTime at the beginning of the script using Date.now().
  5. Elapsed Time Calculation: After each action (whether a song is liked or skipped), the script calculates the elapsed time by subtracting startTime from the current time and then converts it to seconds with two decimal precision.
  6. Output with Timer: The elapsed time is appended to each log output, providing a real-time view of how long the script has been running after each action.
  7. Updated Remaining Count for Skipped Songs: When a song is already liked, the script now subtracts one from the left count, updating the remaining number of songs.
  8. Log Message Update: The log message now reflects the updated number of songs left, regardless of whether the song was liked or skipped.
  9. Singular/Plural Form Handling: ex: Hours, minutes, and seconds are now correctly displayed in singular form if the elapsed time is 1 for any unit. For example, 1 hour, 1 minute, 1 second and 2 hours, 3 minutes, 5 seconds are displayed as expected.

For randomized timing script:

  1. Random Interval Generator: The getRandomInterval function generates a random time interval between 10 and 100 seconds.
  2. Randomized Wait Period: The script now waits for a randomly generated time (between 10 and 100 seconds) before moving to the next song.

Star ⭐ this gist if it was useful. Follows to my GitHub Profile are appreciated.

Follow Badge

Original Creator: (Make sure and give him a follow as well)

Follow Badge

// script originally made by https://github.com/TheOnlyWayUp, if it helped, drop a follow!
// source: https://gist.github.com/TheOnlyWayUp/4452b0a5c151740417c16f3518fb701e
// added features by https://github.com/KnoBuddy
// new source: https://gist.github.com/KnoBuddy/9498ec7fd6cf9a32f8bc530ef43cfb57
// Added features by KnoBuddy:
// 1. likeNext Function: This function is responsible for processing each song one by one.
// 2. Conditionally Engage Wait: If a song is already liked (aria-pressed="true"), it skips the wait period and moves to the next song immediately.
// 3. Wait Only for Unliked Songs: The wait period is only applied when a song is actually liked.
// 4. Timer Initialization: The script initializes a startTime at the beginning of the script using Date.now().
// 5. Elapsed Time Calculation: After each action (whether a song is liked or skipped), the script calculates the elapsed time by subtracting startTime from the current time and then converts it to seconds with two decimal precision.
// 6. Output with Timer: The elapsed time is appended to each log output, providing a real-time view of how long the script has been running after each action.
// 7. Updated Remaining Count for Skipped Songs: When a song is already liked, the script now subtracts one from the left count, updating the remaining number of songs.
// 8. Log Message Update: The log message now reflects the updated number of songs left, regardless of whether the song was liked or skipped.
// 9. Singular/Plural Form Handling: ex: Hours, minutes, and seconds are now correctly displayed in singular form if the elapsed time is 1 for any unit.
// For example, 1 hour, 1 minute, 1 second and 2 hours, 3 minutes, 5 seconds are displayed as expected.
// 10. Random Interval Generator: The getRandomInterval function generates a random time interval between 10 and 100 seconds.
// 11. Randomized Wait Period: The script now waits for a randomly generated time (between 10 and 100 seconds) before moving to the next song.
let total = 0;
let left = 0;
const minInterval = 10; // minimum wait time in seconds
const maxInterval = 100; // maximum wait time in seconds
const startTime = Date.now();
const ytmLog = msg => {
const elapsedTime = Date.now() - startTime;
const elapsedHours = Math.floor(elapsedTime / 3600000); // convert milliseconds to hours
const elapsedMinutes = Math.floor((elapsedTime % 3600000) / 60000); // convert remainder to minutes
const elapsedSeconds = Math.floor((elapsedTime % 60000) / 1000); // convert remainder to seconds
let formattedTime = '';
if (elapsedHours > 0) {
formattedTime += `${elapsedHours} hour${elapsedHours > 1 ? 's' : ''}, `;
}
if (elapsedMinutes > 0 || elapsedHours > 0) {
formattedTime += `${elapsedMinutes} minute${elapsedMinutes > 1 ? 's' : ''}, `;
}
formattedTime += `${elapsedSeconds} second${elapsedSeconds > 1 ? 's' : ''}`;
console.log(`[YTM Liker] ${msg} (Elapsed Time: ${formattedTime})`);
};
const getRandomInterval = () => {
return Math.floor(Math.random() * (maxInterval - minInterval + 1)) + minInterval;
};
function likeAll() {
let els = document.getElementById("contents").querySelectorAll(
"button[aria-pressed='false'][aria-label='Like']"
);
total = els.length;
left = els.length;
ytmLog(`Total Queue: ${total}`);
function likeNext(index) {
if (index >= els.length) {
ytmLog('All songs processed.');
return;
}
let el = els[index];
// Check if the song is unliked
if (el.getAttribute("aria-pressed") === "false") {
el.click();
left--;
ytmLog(`Liked a song. ${left} songs left out of ${total}.`);
// Wait a random time between 10 and 100 seconds before liking the next unliked song
let randomInterval = getRandomInterval();
ytmLog(`Waiting ${randomInterval} second${randomInterval > 1 ? 's' : ''} before next action.`);
setTimeout(() => likeNext(index + 1), randomInterval * 1000);
} else {
left--; // Subtract the skipped song from the remaining count
ytmLog(`Song already liked. Skipping. ${left} songs left out of ${total}.`);
likeNext(index + 1); // No wait, move to the next song
}
}
likeNext(0);
}
likeAll();
// script originally made by https://github.com/TheOnlyWayUp, if it helped, drop a follow!
// source: https://gist.github.com/TheOnlyWayUp/4452b0a5c151740417c16f3518fb701e
// added features by https://github.com/KnoBuddy
// new source: https://gist.github.com/KnoBuddy/9498ec7fd6cf9a32f8bc530ef43cfb57
// Added features by KnoBuddy:
// 1. likeNext Function: This function is responsible for processing each song one by one.
// 2. Conditionally Engage Wait: If a song is already liked (aria-pressed="true"), it skips the wait period and moves to the next song immediately.
// 3. Wait Only for Unliked Songs: The wait period is only applied when a song is actually liked.
// 4. Timer Initialization: The script initializes a startTime at the beginning of the script using Date.now().
// 5. Elapsed Time Calculation: After each action (whether a song is liked or skipped), the script calculates the elapsed time by subtracting startTime from the current time and then converts it to seconds with two decimal precision.
// 6. Output with Timer: The elapsed time is appended to each log output, providing a real-time view of how long the script has been running after each action.
// 7. Updated Remaining Count for Skipped Songs: When a song is already liked, the script now subtracts one from the left count, updating the remaining number of songs.
// 8. Log Message Update: The log message now reflects the updated number of songs left, regardless of whether the song was liked or skipped.
// 9. Singular/Plural Form Handling: ex: Hours, minutes, and seconds are now correctly displayed in singular form if the elapsed time is 1 for any unit.
// For example, 1 hour, 1 minute, 1 second and 2 hours, 3 minutes, 5 seconds are displayed as expected.
let total = 0;
let left = 0;
const interval = 10; // static wait time in seconds
const startTime = Date.now();
const ytmLog = msg => {
const elapsedTime = Date.now() - startTime;
const elapsedHours = Math.floor(elapsedTime / 3600000); // convert milliseconds to hours
const elapsedMinutes = Math.floor((elapsedTime % 3600000) / 60000); // convert remainder to minutes
const elapsedSeconds = Math.floor((elapsedTime % 60000) / 1000); // convert remainder to seconds
let formattedTime = '';
if (elapsedHours > 0) {
formattedTime += `${elapsedHours} hour${elapsedHours > 1 ? 's' : ''}, `;
}
if (elapsedMinutes > 0 || elapsedHours > 0) {
formattedTime += `${elapsedMinutes} minute${elapsedMinutes > 1 ? 's' : ''}, `;
}
formattedTime += `${elapsedSeconds} second${elapsedSeconds > 1 ? 's' : ''}`;
console.log(`[YTM Liker] ${msg} (Elapsed Time: ${formattedTime})`);
};
function likeAll() {
let els = document.getElementById("contents").querySelectorAll(
"button[aria-pressed='false'][aria-label='Like']"
);
total = els.length;
left = els.length;
ytmLog(`Total Queue: ${total}`);
function likeNext(index) {
if (index >= els.length) {
ytmLog('All songs processed.');
return;
}
let el = els[index];
// Check if the song is unliked
if (el.getAttribute("aria-pressed") === "false") {
el.click();
left--;
ytmLog(`Liked a song. ${left} songs left out of ${total}.`);
// Wait a static 10 seconds before liking the next unliked song
ytmLog(`Waiting ${interval} second${interval > 1 ? 's' : ''} before next action.`);
setTimeout(() => likeNext(index + 1), interval * 1000);
} else {
left--; // Subtract the skipped song from the remaining count
ytmLog(`Song already liked. Skipping. ${left} songs left out of ${total}.`);
likeNext(index + 1); // No wait, move to the next song
}
}
likeNext(0);
}
likeAll();
@NishchayKQ
Copy link

NishchayKQ commented Sep 12, 2024

hey liked songs playlist generates to show newest likes on the top, so i want to preserve the order of my playlist, for that the script must like the songs from down to top so is this alright?

// script originally made by https://github.com/TheOnlyWayUp, if it helped, drop a follow!
// source: https://gist.github.com/TheOnlyWayUp/4452b0a5c151740417c16f3518fb701e
// added features by https://github.com/KnoBuddy
// new source: https://gist.github.com/KnoBuddy/9498ec7fd6cf9a32f8bc530ef43cfb57
// Added features by KnoBuddy:
// 1. likeNext Function: This function is responsible for processing each song one by one.
// 2. Conditionally Engage Wait: If a song is already liked (aria-pressed="true"), it skips the wait period and moves to the next song immediately.
// 3. Wait Only for Unliked Songs: The wait period is only applied when a song is actually liked.
// 4. Timer Initialization: The script initializes a startTime at the beginning of the script using Date.now().
// 5. Elapsed Time Calculation: After each action (whether a song is liked or skipped), the script calculates the elapsed time by subtracting startTime from the current time and then converts it to seconds with two decimal precision.
// 6. Output with Timer: The elapsed time is appended to each log output, providing a real-time view of how long the script has been running after each action.
// 7. Updated Remaining Count for Skipped Songs: When a song is already liked, the script now subtracts one from the left count, updating the remaining number of songs.
// 8. Log Message Update: The log message now reflects the updated number of songs left, regardless of whether the song was liked or skipped.
// 9. Singular/Plural Form Handling: ex: Hours, minutes, and seconds are now correctly displayed in singular form if the elapsed time is 1 for any unit.
// For example, 1 hour, 1 minute, 1 second and 2 hours, 3 minutes, 5 seconds are displayed as expected.
let total = 0;
let left = 0;
const interval = 10;  // static wait time in seconds
const startTime = Date.now();

const ytmLog = msg => {
    const elapsedTime = Date.now() - startTime;
    const elapsedHours = Math.floor(elapsedTime / 3600000); // convert milliseconds to hours
    const elapsedMinutes = Math.floor((elapsedTime % 3600000) / 60000); // convert remainder to minutes
    const elapsedSeconds = Math.floor((elapsedTime % 60000) / 1000); // convert remainder to seconds

    let formattedTime = '';
    if (elapsedHours > 0) {
        formattedTime += `${elapsedHours} hour${elapsedHours > 1 ? 's' : ''}, `;
    }
    if (elapsedMinutes > 0 || elapsedHours > 0) {
        formattedTime += `${elapsedMinutes} minute${elapsedMinutes > 1 ? 's' : ''}, `;
    }
    formattedTime += `${elapsedSeconds} second${elapsedSeconds > 1 ? 's' : ''}`;

    console.log(`[YTM Liker] ${msg} (Elapsed Time: ${formattedTime})`);
};

function likeAll() {
    let els = document.getElementById("contents").querySelectorAll(
        "button[aria-pressed='false'][aria-label='Like']"
    );

    total = els.length; 
    left = els.length;
    ytmLog(`Total Queue: ${total}`);

    function likeNext(index) {
        if (index < 0) {
            ytmLog('All songs processed.');
            return;
        }

        let el = els[index];

        // Check if the song is unliked
        if (el.getAttribute("aria-pressed") === "false") {
            el.click();
            left--;
            ytmLog(`Liked a song. ${left} songs left out of ${total}.`);

            // Wait a static 10 seconds before liking the next unliked song
            ytmLog(`Waiting ${interval} second${interval > 1 ? 's' : ''} before next action.`);
            setTimeout(() => likeNext(index - 1), interval * 1000);
        } else {
            left--;  // Subtract the skipped song from the remaining count
            ytmLog(`Song already liked. Skipping. ${left} songs left out of ${total}.`);
            likeNext(index - 1);  // No wait, move to the next song
        }
    }

    likeNext(els.length - 1);
}

likeAll();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment