Script to delete “Watch Later” youtube videos

I found out today that you can’t delete all your “watch later” videos on youtube with a single click. Why? There is an option “delete watched videos”, but that only removed 5% of my 5000 videos.

And there is a 5000 videos limit. So instead of deleting one by one, good ol’ AI gave me this snippet you can use too.

Quick feature list:

  • Tested on Jan, 2026. If DOM changes, it might break.
  • Stores the title and URL of the deleted video.
  • Clicks on “remove video” from the playlist.
  • Takes two params: Count (to delete) and wait in ms (between deletions).
  • Saves the deleted videos info in a CSV and auto-downloads it in case you want to store it somewhere.
  • Updates the tab title with the progress and estimate.

You can keep it running while you do something else, but the script will halt if it’s not on view. So make a lunch while you’re deleting.

Important

DO NOT COPY-PASTE CODE BLINDLY.

I did not purposfully write / generate malicious code, but you should never just copy-paste code from the web in your console and run it if you don’t understand what it does.

This is valid for this too! Please, make it a habit to read it first.

/**
 * Deletes videos, updates tab title with ETA, and exports a CSV log.
 * @param {number} totalToDelete - Number of videos to remove.
 * @param {number} delay - Delay between deletions (default 1200ms).
 */
async function deleteVideos(totalToDelete, delay = 1200) {
    const originalTitle = document.title;
    const startTime = Date.now();
    const deletedLog = [];
    
    for (let i = 0; i < totalToDelete; i++) {
        const currentCount = i + 1;
        let etaText = "Calculating...";

        // 1. Capture Data before deletion
        const videoRow = document.querySelector('ytd-playlist-video-renderer');
        if (!videoRow) {
            console.log("No more videos found.");
            break;
        }

        const titleElement = videoRow.querySelector('#video-title');
        const videoTitle = titleElement?.innerText.trim() || "Unknown Title";
        const videoUrl = titleElement?.href ? titleElement.href.split('&')[0] : "Unknown URL";

        // Add to our internal log
        deletedLog.push({ title: videoTitle, url: videoUrl });

        // 2. Update ETA in Tab Title
        if (currentCount > 1) {
            const elapsedMs = Date.now() - startTime;
            const avgMsPerVideo = elapsedMs / i;
            const remainingMs = (totalToDelete - i) * avgMsPerVideo;
            const mins = Math.floor(remainingMs / 60000);
            const secs = Math.floor((remainingMs % 60000) / 1000);
            etaText = `~${mins}m ${secs}s left`;
        }

        document.title = `[${currentCount}/${totalToDelete}] ${etaText}`;
        console.log(`Processing: "${videoTitle}" (${currentCount}/${totalToDelete})`);

        // 3. Perform Deletion
        const menuBtn = videoRow.querySelector('[aria-label="Action menu"]');
        if (menuBtn) {
            menuBtn.click();
            await new Promise(r => setTimeout(r, 450));

            const menuItems = document.querySelectorAll('tp-yt-paper-item');
            const removeBtn = Array.from(menuItems).find(item => 
                item.textContent.includes('Remove from')
            );

            if (removeBtn) {
                removeBtn.click();
            } else {
                document.body.click();
            }
        }

        await new Promise(r => setTimeout(r, delay));
    }
    
    // 4. Finalize and Export
    document.title = `DONE - ${originalTitle}`;
    console.log("Process complete. Generating CSV...");
    exportToCSV(deletedLog);
}

/**
 * Converts the log array into a CSV file and triggers a download.
 */
function exportToCSV(data) {
    if (data.length === 0) return;

    // Header and rows
    const csvContent = [
        ["Title", "URL"], 
        ...data.map(item => [`"${item.title.replace(/"/g, '""')}"`, item.url])
    ].map(e => e.join(",")).join("\n");

    const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
    const link = document.createElement("a");
    const url = URL.createObjectURL(blob);
    
    link.setAttribute("href", url);
    link.setAttribute("download", `youtube_removed_videos_${new Date().getTime()}.csv`);
    link.style.visibility = 'hidden';
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
}

You can run the above on any playlist page actually.