I'm trying to write a Violentmonkey userscript to save youtube thumbnails on my harddrive, but can't get it to work. I think the fact that I'm trying to save images from ytimg.com while being on youtube.com complicates things.
Here is the code I wrote so far, copypaste this into your Web Developer Tools Javascript console, and then click the "TEST" button in the top right corner, here is the YouTube channel I test this on https://www.youtube.com/@user-qm6hx2ud3r/videos. With Firefox it saves the thumbnail, but also opens thumbnail, and I want to stay on the page I am. With Chromium it just throws an error, "has been blocked by CORS policy". Change download2 to download inside forElement to see the different approach.
// ==UserScript==
// @name        Grab channel info - youtube.com
// @namespace   Violentmonkey Scripts
// @match       https://www.youtube.com/*
// @grant       none
// @version     1.0
// @author      -
// @description -
// ==/UserScript==
"mode strict";
function save(url, name) {
  const link = document.createElement('a')
  link.href = url
  link.download = name
  link.style.display = 'none';
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
}
function download2(url, name) {
  if (!url) return
  if (!name) return
  var xhr = new XMLHttpRequest();
  xhr.onload = function() {
    var reader = new FileReader();
    reader.onloadend = function() {
      //console.log(reader.result);
      save(reader.result, name)
    }
    reader.readAsDataURL(xhr.response);
  };
  xhr.open('GET', url);
  xhr.responseType = 'blob';
  xhr.send();
}
async function download(url, name) {
  if (!url) return
  if (!name) return
  const image = await fetch(url)
  const imageBlog = await image.blob()
  const imageURL = URL.createObjectURL(imageBlog)
  const link = document.createElement('a')
  link.href = imageURL
  //link.download = name
  link.style.display = 'none';
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
}
function forElement(el) {
  let thumb = el.querySelector('ytd-thumbnail img').src
  console.log(thumb)
  download2(thumb, "downloaded-thumbnail.webp")
}
function start() {
  let testbutton = document.querySelector("button#test")
  if (!testbutton) {
    document.querySelector('ytd-masthead div#container div#end').insertAdjacentHTML('afterbegin', '<button id="test">TEST</button>')
    testbutton = document.querySelector("button#test")
  }
  testbutton.onclick = function() {
    forElement(document.querySelectorAll("div#content.ytd-rich-item-renderer")[0])
  }
}
start()
I'm trying to do saving right from the browser because I hope to save a bit of traffic this way, browser already downloaded those thumbnails and I don't want to save an already downloaded thumbnails. I can try making a WebExtensions if a simple userscript isn't enough for this task.
Related resources: https://dev.to/sbodi10/download-images-using-javascript-51a9 Force browser to download image files on click How can I convert an image into Base64 string using JavaScript?
 
     
    