Like Watch Later, YouTube's Liked videos playlist (internal ID LL)
has no official "Unlike all" button — only per-video removal via each row's three-dot menu.
This page documents a browser-console script that walks the Liked Videos playlist and unlikes
every video automatically, with retry, stall-detection, and lazy-load handling built in for
large libraries.
YouTube's help documentation for playlists covers removing a single video at a time: open the video's ⋮ menu → Remove from Liked videos. For a library of any real size that is impractical by hand. The script below drives the identical UI action — it never touches a private API — just automatically and with the safety checks a manual pass would skip, like confirming each removal actually took effect before moving to the next row.
Verified working. Run it with the Liked videos playlist open
(youtube.com/playlist?list=LL) — the script checks the list=LL
query parameter itself and refuses to run anywhere else.
(async () => {
const playlistId = new URL(location.href).searchParams.get("list");
if (playlistId !== "LL") {
console.error("Open the YouTube Liked videos playlist first.");
return;
}
if (window.__youtubeUnlikeAll?.running) {
console.warn("The unlike script is already running.");
return;
}
const state = {
running: true,
removed: 0,
failures: 0
};
window.__youtubeUnlikeAll = state;
window.stopUnlikeAll = () => {
state.running = false;
console.log("Stopping after the current video.");
};
const sleep = (milliseconds) =>
new Promise((resolve) => setTimeout(resolve, milliseconds));
const isDisplayed = (element) =>
Boolean(
element &&
element.isConnected &&
(element.offsetWidth ||
element.offsetHeight ||
element.getClientRects().length)
);
async function waitFor(test, timeout = 7000, interval = 100) {
const start = Date.now();
while (Date.now() - start < timeout) {
const result = test();
if (result) {
return result;
}
await sleep(interval);
}
return null;
}
function getRows() {
return [
...document.querySelectorAll("ytd-playlist-video-renderer")
].filter(isDisplayed);
}
function getVideoIdentity(row) {
const link = row.querySelector(
"a#video-title, a#thumbnail, a[href*='/watch']"
);
return link?.href || row.textContent?.trim() || "";
}
function closeOpenMenu() {
const event = new KeyboardEvent("keydown", {
key: "Escape",
code: "Escape",
keyCode: 27,
which: 27,
bubbles: true
});
document.activeElement?.dispatchEvent(event);
document.dispatchEvent(event);
}
async function scrollToBottomAndLoad() {
const beforeCount = getRows().length;
const beforeHeight = document.documentElement.scrollHeight;
window.scrollTo({
top: document.documentElement.scrollHeight,
behavior: "auto"
});
await sleep(1400);
// A small upward/downward movement helps trigger YouTube's lazy loader.
window.scrollBy({
top: -300,
behavior: "auto"
});
await sleep(200);
window.scrollTo({
top: document.documentElement.scrollHeight,
behavior: "auto"
});
await sleep(1400);
const afterCount = getRows().length;
const afterHeight = document.documentElement.scrollHeight;
return afterCount > beforeCount || afterHeight > beforeHeight;
}
async function removeLikedVideo(row) {
if (!row?.isConnected) {
return false;
}
const oldIdentity = getVideoIdentity(row);
const oldRowCount = getRows().length;
row.scrollIntoView({
behavior: "auto",
block: "center"
});
await sleep(350);
const menuButton =
row.querySelector("button[aria-label='Action menu']") ||
row.querySelector("button[aria-label*='More actions']") ||
row.querySelector("ytd-menu-renderer yt-icon-button button") ||
row.querySelector("#menu yt-icon-button button") ||
row.querySelector("#menu button");
if (!menuButton) {
console.warn("Could not find the three-dot menu.");
return false;
}
menuButton.click();
const removeOption = await waitFor(() => {
const candidates = [
...document.querySelectorAll(
[
"ytd-popup-container ytd-menu-service-item-renderer",
"tp-yt-iron-dropdown ytd-menu-service-item-renderer",
"ytd-menu-service-item-renderer",
"[role='menuitem']"
].join(",")
)
].filter(isDisplayed);
return candidates.find((item) =>
/remove\s+from\s+liked\s+videos/i.test(
item.innerText || item.textContent || ""
)
);
});
if (!removeOption) {
closeOpenMenu();
console.warn('Could not find "Remove from Liked videos."');
return false;
}
removeOption.click();
const removedSuccessfully = await waitFor(() => {
if (!row.isConnected) {
return true;
}
const newIdentity = getVideoIdentity(row);
const newRowCount = getRows().length;
return (
newIdentity !== oldIdentity ||
newRowCount < oldRowCount ||
row.hasAttribute("is-dismissed")
);
}, 9000);
if (!removedSuccessfully) {
closeOpenMenu();
console.warn("YouTube did not confirm removal. Retrying.");
return false;
}
return true;
}
console.log(
"Started removing liked videos. " +
"To stop, enter: stopUnlikeAll()"
);
let emptyRounds = 0;
while (state.running) {
let rows = getRows();
if (rows.length === 0) {
const loadedMore = await scrollToBottomAndLoad();
rows = getRows();
if (rows.length === 0 && !loadedMore) {
emptyRounds++;
console.log(
`Waiting for more videos: ${emptyRounds}/12`
);
if (emptyRounds >= 12) {
break;
}
await sleep(1500);
continue;
}
}
emptyRounds = 0;
// Process from the bottom so YouTube continues loading later pages.
const row = rows[rows.length - 1];
const success = await removeLikedVideo(row);
if (success) {
state.removed++;
state.failures = 0;
console.log(
`Removed ${state.removed} liked video(s).`
);
await scrollToBottomAndLoad();
// Occasional pause to reduce interface and rate-limit errors.
if (state.removed % 25 === 0) {
console.log("Pausing briefly...");
await sleep(4000);
} else {
await sleep(700 + Math.random() * 500);
}
} else {
state.failures++;
console.warn(
`Removal failure ${state.failures}/15. Retrying...`
);
closeOpenMenu();
await scrollToBottomAndLoad();
await sleep(1500);
if (state.failures >= 15) {
console.error(
"Stopped after 15 consecutive failures. " +
"Reload the page and run the script again."
);
break;
}
}
}
state.running = false;
console.log(
`Finished. Removed ${state.removed} liked video(s).`
);
})();
⌘ + Option + K (Mac) or Ctrl + Shift + K (Windows/Linux); Chrome: ⌘ + Option + J (Mac) or Ctrl + Shift + J (Windows/Linux).allow pasting and press Enter before pasting the script.Removed N liked video(s).; the run ends with Finished. Removed N liked video(s).stopUnlikeAll() in the console and press Enter. The script finishes the video it is currently removing, then exits cleanly.failure/15 counter.is-dismissed attribute, rather than assuming the click succeeded.aria-label='Action menu', aria-label*='More actions', structural fallbacks) before giving up on a row.ytd-playlist-video-renderer, ytd-menu-service-item-renderer, the "Remove from Liked videos" menu-item text). A future YouTube redesign can break the selectors.