Created
November 21, 2025 04:10
-
-
Save manojkarthick/0cfb1d7a5cdc6b755dd6fb4a35822065 to your computer and use it in GitHub Desktop.
Run it on https://www.youtube.com/playlist?list=WL from the console. If you need to stop, run stopWatchLaterRemoval(). If 409s pile up and it stops making progress, wait a bit or reload and restart.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (() => { | |
| const wait = ms => new Promise(r => setTimeout(r, ms)); | |
| const jitter = (base = 500, spread = 700) => base + Math.random() * spread; | |
| let keepRunning = true; | |
| let removed = 0; | |
| async function removeAll() { | |
| console.log("Starting Watch Later cleanup…"); | |
| while (keepRunning) { | |
| // Prefer direct remove buttons if present | |
| const quick = document.querySelector( | |
| "ytd-playlist-video-renderer #button[aria-label^='Remove from Watch later']" | |
| ); | |
| if (quick) { | |
| quick.click(); | |
| removed++; | |
| if (removed % 10 === 0) window.scrollBy(0, window.innerHeight * 1.5); | |
| if (removed % 30 === 0) await wait(1500 + jitter()); // extra pause | |
| else await wait(jitter()); | |
| continue; | |
| } | |
| // Otherwise use menu path | |
| const menuBtn = document.querySelector( | |
| "ytd-playlist-video-renderer ytd-menu-renderer button[aria-label^='Action menu']" | |
| ); | |
| if (!menuBtn) { | |
| window.scrollBy(0, window.innerHeight * 2); | |
| await wait(900 + jitter()); | |
| continue; | |
| } | |
| menuBtn.click(); | |
| await wait(250 + Math.random() * 200); | |
| const removeItem = Array.from( | |
| document.querySelectorAll("tp-yt-paper-listbox ytd-menu-service-item-renderer") | |
| ).find(el => /Remove from Watch later/i.test(el.innerText)); | |
| if (!removeItem) { | |
| document.body.click(); | |
| await wait(300 + Math.random() * 200); | |
| continue; | |
| } | |
| removeItem.click(); | |
| removed++; | |
| if (removed % 10 === 0) window.scrollBy(0, window.innerHeight * 1.5); | |
| if (removed % 30 === 0) await wait(1500 + jitter()); | |
| else await wait(jitter()); | |
| } | |
| console.log(`Stopped. Removed about ${removed} videos.`); | |
| } | |
| removeAll(); | |
| window.stopWatchLaterRemoval = () => (keepRunning = false); | |
| })(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment