Skip to content

Instantly share code, notes, and snippets.

@miketromba
Last active April 13, 2024 18:02
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save miketromba/334282421c4784d7d9a191ca25095c09 to your computer and use it in GitHub Desktop.
Save miketromba/334282421c4784d7d9a191ca25095c09 to your computer and use it in GitHub Desktop.
Delete YouTube watch history with filter
const ENABLED = false // Keep this false while testing to verify that it's working correctly
const DELETE_INTERVAL = 1000 // Amount of time in MS to wait between deletion (more likely to fail with a small number)
// This filter should return a boolean (true == delete video, false == keep video)
const MIN_DURATION_MS = 1000 * 60 * 1.5 // 1:30 mins
const SHOULD_DELETE = videoElement => {
try {
// Get the duration string
const durationString = videoElement.querySelector('[aria-label="Video duration"]').textContent.trim()
if(durationString.split(':').length > 2){ return false } // The video is > 1hr long
const [mins, secs] = durationString.split(':').map(stringNum => parseInt(stringNum, 10))
const durationMS = (mins * 60 * 1000) + (secs * 1000)
// Return true if video is less than MIN_DURATION_MS in length
return durationMS < MIN_DURATION_MS
} catch(e){
return false
}
}
// This will start up the script
let DELETE_OFFSET = 0 // Offset to keep track of skipped (non-deleted) videos
deleteNext(SHOULD_DELETE) // Pass in the shouldDelete filter function
// Delete the next bad item and wait [DELETE_INTERVAL]ms before proceeding
// This is recursive and never-ending
async function deleteNext(shouldDelete){
// Extract next item from page
const nextItem = await getNextItem(DELETE_OFFSET)
// If video does not pass filter, skip it, increment the offset
if(!shouldDelete(nextItem)){
DELETE_OFFSET += 1
return deleteNext(shouldDelete)
}
// Find name and author of video & log it to console
try {
const [videoName, channelName] = [...nextItem.getElementsByTagName('a')].map(anchor => anchor.textContent.trim())
console.log(`DELETE: ${videoName} by ${channelName}...`)
} catch(e){}
// Find the next menu button for the item & click it
const nextButton = nextItem.getElementsByTagName('button')[0]
nextButton.click()
// Wait [DELETE_INTERVAL] ms
setTimeout(() => {
// Get the next delete button on the page & click it
const nextMenu = nextItem.querySelector('[aria-label="Activity options menu"]')
const nextDeleteButton = nextMenu.querySelector('[aria-label="Delete activity item"]')
// If enabled, click delete button, else just increment offset
if(ENABLED) nextDeleteButton.click()
else DELETE_OFFSET += 1
// Recurse
deleteNext(shouldDelete)
}, DELETE_INTERVAL)
}
async function getNextItem(offset){
while(true){
const nextItem = document.querySelectorAll('div[role="listitem"]')[offset]
if(nextItem) return nextItem
await sleep(200)
}
}
async function sleep(ms){
return new Promise(resolve => {
setTimeout(resolve, ms)
})
}
@miketromba
Copy link
Author

miketromba commented Jan 7, 2021

Has your YouTube feed gotten out of control with bad recommendations?

This script will enable you to programmatically delete videos from your YouTube watch history based on some filter you define.

  1. Edit inside the try block of the "SHOULD_DELETE" function to return true or false based on your desired condition (by default it is configured to delete all videos less than 1:30 in length)
  2. Paste the script into your console on this page: https://myactivity.google.com/product/youtube

Note: You must set ENABLED to true for the script to actually delete the videos. If not, they will just be logged to the console.

Tip: Run the script in disabled mode first to review which videos will be deleted and tune your filter before actually letting it delete stuff.

My feed was getting clogged with tons of <1 minute long videos which were mostly just quick, funny TikTok-style videos. Naturally, the more the videos got recommended, the more I clicked on them... which led to more similar recommendations, and so on. My feed used to be filled with tons of great educational programming videos, and this script has helped me to restore it.

@Uddhav07
Copy link

it is deleting only one video at a time
how to loop this

@miketromba
Copy link
Author

@Uddhav07 It has been a while since I wrote this so I don’t remember exactly how it works, but I think if you don’t want to clear your entire history, the google history UI makes you remove items one-by-one. (Not sure) I also notice that at the top of the script is a DELETE_INTERVAL variable which you can try reducing to speed up the process, but it might cause errors if you make it too fast.

@benzntech
Copy link

@miguelmota Create a templeMonkey script so it can be add and update easy. tutorial

@DinoChiesa
Copy link

DinoChiesa commented Apr 13, 2024

It's surprising that there's so much interest in this gist in the past few days, 3 years after it was created.

I too had the experience that it was deleting only one video at a time.
So I modified it a little and this seems to work for me. I had to introduce a longer delay between cycles, but.. it works. It will delete only short videos that are in the 100 most recent videos watched - because the 100 most recent is what is displayed on the screen. So eventually the script will run out of things to delete. You can scroll the page down in the browser to "load more" and it will keep deleting.

https://gist.github.com/DinoChiesa/f3f2aa34d7d581782a0b8572fad99278

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