Skip to content

Instantly share code, notes, and snippets.

@cprima
Last active April 30, 2024 20:47
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save cprima/2f7ea8e353c18a666506021c85e9773d to your computer and use it in GitHub Desktop.
Save cprima/2f7ea8e353c18a666506021c85e9773d to your computer and use it in GitHub Desktop.
Google MyActivity YouTube Comment Delete Script πŸ’¬βŒ

CommentCleanser for YouTube πŸ’¬βŒ

Description

Looking to take control of your digital history? CommentCleanser for YouTube lets you efficiently delete old YouTube comments from Google's MyActivity. Prioritize the removal of older comments, ensuring a leaner digital footprint and a conscious cleanup of your online history.

The script has been designed for users who have a significant number of YouTube comments and wish to delete them in bulk from Google's MyActivity page. By leveraging JavaScript, it provides a means to automate the process of deleting individual comments, offering the user control over how many comments to delete at once.

In today's rapidly changing social landscape, the words and sentiments we once casually expressed can come back to haunt us. What might have been a mere fleeting thought or a commonly held belief a few years ago, can now be viewed as socially unacceptable, casting shadows over one's character. The danger isn't just virtual; these old comments can pose genuine threats to employment opportunities, social standing, and overall well-being. The digital footprint we've left over the years is more than just a record; it's an open book, judged by today's standards, with real consequences in our day-to-day lives.

Compatibility

The script has been tested on 2023-09-02 and found compatible with the following browsers:

  • Edge version 116.0.1938.62 (Official build) (64-bit)
  • Chrome version 116.0.5845.141 (Official Build) (64-bit)
  • Firefox version 117.0 (64-bit)

Features

  • Selective Deletion: You can choose to delete a specific number of comments or all of them.
  • Bottom-Up Approach: Deletes comments starting from the oldest.
  • Highlight Before Deletion: For clarity, the script highlights a comment right before deletion.
  • User Control: You have the choice to specify the exact number of comments you wish to delete or can decide to delete all comments. The script will prompt you at each step.

Usage

  1. Navigate to MyActivity YouTube Comments page. Use exactly this link, as it will ensure that the script is able to find the comments.
  2. Open your browser's developer console.
  3. Copy-paste the provided script.
  4. Follow the on-screen prompts to execute deletions.

Safety and Control

If you wish to halt the script:

  • Click 'cancel' when prompted.
  • Or simply close the browser tab.

However, always be cautious: once a comment is deleted, it is irreversible.

Reporting Issues

If you encounter any issues or have suggestions for improvement, please report them as a comment to the gist.

License

This project is licensed under the MIT License.

Author

Christian Prior-Mamulyan

Source

The script can be found at this gist.


Note: Please use this script responsibly and understand that any deletion is permanent.


Basement filled with balloons representing YouTube comments

In the shadowy basement of digital history, balloons symbolizing long-forgotten YouTube comments drift aimlessly. As rays of sunlight try to pierce through the solitary window, hinting at the possibility of a cleaner digital slate, a watchful teddy bear stands guard. Yet, lurking in the dark corners, unseen entities await, ready to pounce upon any overlooked comment, emphasizing the peril of neglecting our online past.
/**
* Google MyActivity YouTube Comment Deletion Script
*
* Script to assist in bulk deletion of YouTube comments from Google's MyActivity.
*
* Usage:
* - Navigate to MyActivity YouTube Comments page.
* - Open browser's developer console.
* - Copy-paste this script, and follow on-screen prompts.
*
* Features:
* - Deletes comments from bottom (oldest first).
* - User control: specify number to delete, or cancel anytime.
*
* Safety:
* - Halting: 'cancel' during prompt or close tab.
*
* Author: Christian Prior-Mamulyan
* License: MIT
* Source: https://gist.github.com/cprima/2f7ea8e353c18a666506021c85e9773d
*
* Use cautiously. Deletion is irreversible.
*/
function navigateToCommentActivityPage() {
const desiredURL = "https://myactivity.google.com/page?hl=en&utm_medium=web&utm_source=youtube&page=youtube_comments";
console.warn("The function 'navigateToCommentActivityPage' is deprecated. Please use ensureOnCorrectActivityPage().");
if (window.location.href !== desiredURL) {
window.location.href = desiredURL;
return false;
}
return true;
}
function ensureOnCorrectActivityPage() {
const elementsData = [
{
url: "https://myactivity.google.com/page?hl=en&utm_medium=web&utm_source=youtube&page=youtube_comments",
content: "Your YouTube comments"
},
{
url: "https://myactivity.google.com/page?hl=en&utm_medium=web&utm_source=youtube&page=youtube_live_chat",
content: "Your YouTube live chat messages"
},
{
url: "https://myactivity.google.com/page?hl=en&utm_medium=web&utm_source=youtube&page=youtube_comment_likes",
content: "Your Likes and Dislikes on YouTube Comments"
}
];
const currentUrl = window.location.href;
const elementsWithClass = Array.from(document.querySelectorAll('.jPCT6'));
for (let elementData of elementsData) {
if (currentUrl.startsWith(elementData.url)) {
if (elementsWithClass.some(el => el.textContent.toLowerCase().includes(elementData.content.toLowerCase()))) {
console.log(`Matched URL: ${elementData.url} with content: "${elementData.content}"`);
return true; // Matched desired URL with corresponding content.
}
}
}
console.log(`You are not on a recognized page. Please navigate to: ${elementsData[0].url}`);
return false;
}
async function scrollToBottom() {
while (!document.evaluate('//div[contains(text(), "Looks like you\'ve reached the end")]', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue) {
window.scrollTo(0, document.body.scrollHeight);
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
function highlightElement(el) {
el.style.backgroundColor = '#ffcccb'; // Light red
setTimeout(() => {
el.style.backgroundColor = ''; // Reset background color after 1s
}, 1000);
}
function determineBestSelector() {
const SELECTORS = [
'.VfPpkd-Bz112c-LgbsSe.yHy1rc.eT1oJ.mN1ivc',
'[aria-label^="Delete activity item"]',
'[jscontroller="soHxf"]'
];
// Get the selector that matches the least amount of elements (more specific)
SELECTORS.sort((a, b) => document.querySelectorAll(a).length - document.querySelectorAll(b).length);
return SELECTORS[0];
}
let deleteButtons = [];
async function deleteComments(deleteBatchSize) {
const bestSelector = determineBestSelector();
if (!deleteButtons.length) {
deleteButtons = [...document.querySelectorAll(bestSelector)]; //.reverse();
}
let count = 0;
while (deleteButtons.length && (count < deleteBatchSize || deleteBatchSize === Infinity)) {
const btn = deleteButtons.pop();
// Scroll to the button to make it visible before deletion
btn.scrollIntoView({
behavior: 'smooth',
block: 'center'
});
await new Promise(resolve => setTimeout(resolve, 1000)); // Give a moment for the scroll to finish
highlightElement(btn);
await new Promise(resolve => setTimeout(resolve, 2000)); // Wait for 2s for the highlight to be visible
btn.click();
count++;
await new Promise(resolve => setTimeout(resolve, 1500));
}
return deleteButtons.length; // Return the number of remaining comments
}
async function initiateCommentDeletion() {
// if (!navigateToCommentActivityPage()) {
// return;
// }
if (!ensureOnCorrectActivityPage()) {
return;
}
await scrollToBottom();
const bestSelector = determineBestSelector();
const totalComments = document.querySelectorAll(bestSelector).length;
if (!totalComments) {
console.log("No comments found for deletion.");
return;
}
let userInput = prompt(`Found ${totalComments} comments. Enter 'a' to delete all comments or input a number to delete that many comments. Press 'Cancel' at any time to stop the script:`);
while (userInput !== null) {
if (userInput.toLowerCase() === 'a') {
await deleteComments(Infinity);
console.log("All comments deleted.");
return;
} else if (!isNaN(parseInt(userInput))) {
const deleteBatchSize = parseInt(userInput);
const remainingComments = await deleteComments(deleteBatchSize);
if (!remainingComments) {
console.log("All comments deleted.");
return;
}
userInput = prompt(`${remainingComments} comments remaining. Enter 'a' to delete all remaining comments or input a number to delete that many comments. Press 'Cancel' at any time to stop the script:`);
} else {
userInput = prompt("Invalid input. Please enter 'a' or a number:");
}
}
console.log("Operation canceled. No further comments will be deleted.");
}
initiateCommentDeletion();
@cprima
Copy link
Author

cprima commented Aug 23, 2023

DEVOPS_NOTES: CommentsCleaner

Project Roadmap

  • Get Feedback

Upcoming Releases

v1.1.0 - Q4 2023

New Features
  • Live Chat and Comment Likes Deletion: Users will be able to delete comments from other "interactions".
Improvements
  • diagnostic output in error situations

Backlog and Future Considerations

  • add screencast / video
  • make robust against URL rewrites
  • evaluate which other interactions are candidates for inclusion. YouTube lists these: - Video interactions, Video likes and dislikes, Comment likes and dislikes, Comments and - replies, Live chat messages, Channel subscriptions, Community posts, Purchase activity, - Gift settings. This script is named "CommentCleanser" though.
  • continue R&D to pack this into an extension
  • …

Changelog

Latest Updates

v1.0.1 - 2023-09-02

  • Refactored Navigation Method: Replaced navigateToCommentActivityPage with the more robust isOnDesiredPageAndElementExists method.
    • This update improves reliability in checking if users are on the right activity page and if the required element is present.
    • Enhanced compatibility across browsers: Edge, Chrome, and Firefox.
    • Improved handling of element content matching, with case-insensitive checks.
  • Deprecated: navigateToCommentActivityPage has been deprecated.

Changelog Archive

v1.0.0 - 2023-08-26

  • Initial Release:
    • Efficient bulk deletion of old YouTube comments from Google's MyActivity.
    • Provides control to users over deletion quantities.
    • Deletes comments from the oldest, ensuring a leaner digital footprint.
    • Highlights comments right before deletion.
    • Complete user control with prompts at each step.
    • Added safety measures to halt script operation.

@fonic
Copy link

fonic commented Sep 2, 2023

Very nice script. A few observations:

  1. Works on Firefox with minor modifications:

    function navigateToCommentActivityPage() {
        const desiredURL = "https://myactivity.google.com/page?hl=en&utm_medium=web&utm_source=youtube&page=youtube_comments";
        if (window.location.href !== desiredURL) {
            //window.location.href = desiredURL;
            console.log(`Please navigate to URL '${desiredURL}' and run the script again`);
            return false;
        }
        return true;
    }
    

    It would seem that navigating to the correct URL automatically using window.location.href = desiredURL purges the script as the console reloads (not entirely sure though).

  2. URL might be different when using add-ons like uBlock/ClearURLs (URL is reduced to https://myactivity.google.com/page?hl=en&page=youtube_subscriptions), thus a regex-based approach might be better suited

  3. Script seems to work as-is for subscriptions as well (URL ...&page=youtube_subscriptions)

@cprima
Copy link
Author

cprima commented Sep 2, 2023

Very nice script. A few observations:
…

Many thanks for the feedback, @fonic !

a) what an oversight of me to not test properly on Firefox. Noted. Thanks for pointing out my blind spot, much appreciated.
b) Reworked this function, What I really intend to achieve is that the script only clicks "wildly" on page(s) that is was tested on. Implemented an "ensureOnCorrectActivityPage" function. Sideeffect is that this gets rid of the (unavoidable and confusing) fresh console upon a redirect.
c) Hah! Comments, live chat comments and maybe even likes are coming into scope! Niiiice! Good pointer.
d) I need to test the uBlock/ClearURLs myself, that is currently not fixed. Besides RegEx string manipulation with split could also work well on the structured data that URLs are.

I updated this gist accordingly (2023-09-02).

For the moment I leave it as a easter egg that the script works on

In case you want to test the script yourself with other "interactions" just comment out in async function initiateCommentDeletion() the 3 lines of "if not ensureOnCorrectActivityPage()".

I am exploring (with low priority) to turn this into an extension, where such optional features can be presented to the user. The developer console is not a good place for that, methinks.

@fonic
Copy link

fonic commented Sep 2, 2023

Many thanks for the feedback, @fonic !

You're welcome :)

d) I need to test the uBlock/ClearURLs myself, that is currently not fixed.

I'd migrate to regex matching, just simpler and more versatile. Something like ^https://myactivity\.google\.com/page[?&].*page=youtube_comments.*$ (but of course using JavaScript notation which I'm not overly familiar with).

For the moment I leave it as a easter egg that the script works on
* https://myactivity.google.com/page?hl=en&utm_medium=web&utm_source=youtube&page=youtube_comments
* https://myactivity.google.com/page?hl=en&utm_medium=web&utm_source=youtube&page=youtube_live_chat
* https://myactivity.google.com/page?hl=en&utm_medium=web&utm_source=youtube&page=youtube_comment_likes
and possibly more.

... and subscriptions (as stated in my previous comment). Just replace 'comment(s)' in your script with 'item(s)' and you are good to go for all use cases.

I am exploring (with low priority) to turn this into an extension, where such optional features can be presented to the user. The developer console is not a good place for that, methinks.

This might be a good starting point: https://github.com/alexyorke/youtube-subscriptions-exporter (a very simple extension that generates a list of subscriptions and copies the result to the clipboard). Could be used as a template for turning your script into an extension + subscription export is also a nifty feature that could be added.

@cprima
Copy link
Author

cprima commented Sep 2, 2023

Learned today:
These "interactions" (too technical of a term for 'branding') are accessible in "My Activity" for management / deletion:

  • Video interactions
  • Video likes and dislikes
  • Comment likes and dislikes
  • Comments and replies
  • Live chat messages
  • Channel subscriptions
  • Community posts
  • Purchase activity
  • Gift settings

I will work through all of them (and on all major browsers), and decide which one to put in scope.
For those in scope of this script I will then make a decision how "comfortable" they may be deleted.


There are more, here some of the most common interactions on YouTube and what they are (listing them here for my future reference):

Likes and Dislikes: These are straightforward metrics that allow viewers to express whether they liked or disliked a video.

Comments: When users leave comments on a video, they are interacting with the content and potentially with other members of the community.

Shares: If a viewer shares a video on social media or other platforms, it's considered an interaction.

Subscriptions: Gaining a subscriber from a video means the viewer liked the content enough to want more from the channel.

Clicking on Cards and End Screens: Creators can add cards and end screens to their videos to promote other content, merchandise, websites, etc. When viewers click on these, it's another form of interaction.

Video Playback: Starting a video, pausing, rewinding, or adjusting the playback speed can also be considered as interactions.

Saves to Playlists: When a viewer adds a video to one of their playlists, including the "Watch Later" playlist.

Bell Notifications: Clicking the bell icon to get notified about new content from a channel.

Super Chat and Super Stickers: These are paid interactions available during live streams where viewers can pay money to highlight their messages.

Community Posts: Interacting with polls, images, or text updates that a creator posts on the "Community" tab of their channel.


There are also redirects happening when a new login is performed, &pli=1 appears at the end of the URL. Needs investigation; there might be more URL redirects going on.


Already have a bunch of "promotional material" where I need to be sure I reflect name changes, and it shall "fit the story".
Deleting subscriptions might remain a (documented) out-of-scope feature. Have the gut feeling that the requirement to "skip" certain entries will be a must-have feature: As of now if a "CommentCleanser" nuked all my beloved channels I curated over more than a decade that would be major "breach of contract". ;)


And in parallel I wrote me a "comment writer", because I want controlled comments for a screencast-video. Used RPA, specifically UiPath Studio for that task. Seems that YouTube does think 100 comments per day are enough and discards the rest ;)

@DealsBeam
Copy link

This is amazing, thank you for the hard work!

@cprima
Copy link
Author

cprima commented Sep 20, 2023

This is amazing, thank you for the hard work!

Thanks for the comment!
I will release an update in the next weeks, I am currently in the last tests.

@MediaMaquina
Copy link

MediaMaquina commented Oct 7, 2023

Seems it doesn't work for brand accounts:
https://myactivity.google.com/u/1/b/**BRAND ID**/page?hl=en&utm_medium=web&utm_source=youtube&page=youtube_comments

Error:
You are not on a recognized page. Please navigate to: https://myactivity.google.com/page?hl=en&utm_medium=web&utm_source=youtube&page=youtube_comments

But the comments for brand accounts are not there.

Fixed by hardcoding my own url.

EDIT: After a few hours of deleting, it seems to work but if you refresh the page the comments are all still there. I found same outcome with other scripts.

@cprima
Copy link
Author

cprima commented Oct 9, 2023

Seems it doesn't work for brand accounts: …

EDIT: After a few hours of deleting, it seems to work but if you refresh the page the comments are all still there. I found same outcome with other scripts.

Hi @MediaMaquina !
Thanks for reporting, I will investigate this. Currently "busy with life", but there is an update planned this quarter anyways.
IF YouTube does not presistently delete a record then I will try to inform/warn/… the user from the beginning: It's not good to "waste" hours of processor cycles for nothing.

@DealsBeam
Copy link

DealsBeam commented Oct 24, 2023

Hello cprima,

The URLs for YouTube brand accounts are different than the one which the script needs to recognize to be able to run, for example, these are my URLs -

live chat messages: https://myactivity.google.com/u/1/b/108733090519709954844/page?hl=en&page=youtube_live_chat
youtube comments: https://myactivity.google.com/u/1/b/108733090519709954844/page?hl=en&page=youtube_comments

@yycgoods
Copy link

yycgoods commented Dec 6, 2023

Great work! Any way to delete old Youtube livechat comments as well? Thanks again!

@fonic
Copy link

fonic commented Dec 21, 2023

I forged this into an easy-to-use TamperMonkey userscript: Youtube Comment Cleaner (YCC)

(applied some modifications, kept your comments, kept your license and credited you in both the README and the userscript itself)

@cprima
Copy link
Author

cprima commented Dec 22, 2023

I forged this into an easy-to-use TamperMonkey userscript: Youtube Comment Cleaner (YCC)

(applied some modifications, kept your comments, kept your license and credited you in both the README and the userscript itself)

Oh, that is great! Like a christmas gift: The initial code was helpful for re-packaging (by you @fonic )! Highly appreciate the visible credits (wouldn't mind if over time they "just" remained in code file).

I hope to find some time end of December for some slight improvements to this script, but was incredibly busy and focused on other IT hobby projects.

@fonic
Copy link

fonic commented Dec 22, 2023

Oh, that is great! Like a christmas gift: The initial code was helpful for re-packaging (by you @fonic )! Highly appreciate the visible credits (wouldn't mind if over time they "just" remained in code file).

Credit where credit is due - you came up with the idea. I just tried to think of an easy way to use the code without having to copy&paste into the console each time, TamperMonkey seemed like a perfect fit for this.

I hope to find some time end of December for some slight improvements to this script, but was incredibly busy and focused on other IT hobby projects.

Looking forward to that. Happy holidays!

@Derpitron
Copy link

Upon running the script, seems to say "Unable to Load more". Clicking the retry option loads for a second, then shows the same error. No comment entries are loading after this.
image

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