Juha-Matti Santala
Community Builder. Dreamer. Adventurer.

Morning Coffee Projects: Youtube extension

We are living at the mercy of recommendation algorithms everywhere online these days. Social media (like Facebook, Twitter and LinkedIn), video platforms (like Youtube and Netflix) and e-commerce (like Amazon) all provide you some sort of filtered feed based on what their system thinks you'd like.

I'm a heavy user of Youtube but over time, their algorithms have started to feel like they work really bad. I get the same content recommended over and over again and they even recommend me videos I just saw the same or the previous day. Another thing I'm not a fan of is how much they recommend old videos (often ones I've already seen).

So a while ago I started to tinker a bit to build a Chrome extension for my own use to help me get less distracted about the old videos. You can find the code in my GitHub repository: https://github.com/Hamatti/blur-old-youtube-videos.

const blurVideos = () => {
  const videoItems = Object.values(
  ).filter((node) => node.classList.contains("ytd-rich-item-renderer"));
  videoItems.forEach((videoNode) => {
    const metaBlock = videoNode.querySelector("#metadata-line");
    const dateBlock = metaBlock?.children[1];
    if (dateBlock?.innerText?.includes("year")) {
      videoNode.style.filter = "grayscale(1) blur(7.4px)";

The core of the program is function hideVideos above. The video thumbnails in Youtube's front page (at least at the time of writing) are inside elements with ids of content and the ones with a class ytd-rich-item-renderer are actual video items.

We then find all the ones with the text "year" in them (meaning, I want to hide recommended videos that are older than 12 months) and I add inline styling with grayscale and blur to make them unreadable enough so I won't accidentally get excited about them.

In addition to the main functionality, I found a way (from Stack Overflow) to monitor the DOM for any new nodes so as the latest addition, I added the code to be triggered every time that happens. This way, when you scroll down the never-ending scroll, the extension will automatically blur all the old videos from the new recommendations.

const observeDOM = (function () {
  const MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
  return function (obj, callback) {
    if (!obj || !obj.nodeType === 1) return; // validation
    if (MutationObserver) {
      // define a new observer
      const obs = new MutationObserver(function (mutations, observer) {
      // have the observer observe foo for changes in children
      obs.observe(obj, { childList: true, subtree: true });
    } else if (window.addEventListener) {
        obj.addEventListener("DOMNodeInserted", callback, false);
        obj.addEventListener("DOMNodeRemoved", callback, false);

This extension needs to be manually activated by clicking the extension button. Maybe later I'll add a way to toggle this on/off, right now the page needs a hard refresh. The way Chrome extensions does that is by adding a listener to chrome.runtime.onMessage and checking for request.message === "clicked_browser_action".

After building this, I've been very happy browsing Youtube. I'm also shocked by how many of the videos Youtube recommends to me are older than one year (especially given that hundreds of hours of content is uploaded every day). Every now and then, over 75% of the videos in my feed are old and ones I have already seen. With the amount of videos I watch, I would have guessed it could have been quite easy to show similar videos rather than the same videos.

If you want to install and test it out, you can download the code from its GitHub repository and Load unpacked extension in chrome://extensions/. The extension is open source and comes with no guarantees so feel free to play around. Let me know in Twitter if you have any feedback for it or fork the project in GitHub and make a pull request with any improvements!

Syntax Error

Sign up for Syntax Error, a monthly newsletter that helps developers turn a stressful debugging situation into a joyful exploration.