Takes a screenshot from a YouTube video in current quality, saves to the clipboard (Ctrl+Alt+Shift+Q) or a file (Ctrl+Alt+Shift+W).
// ==UserScript==
// @name YouTube Screenshotter
// @namespace https://www.youtube.com
// @version 2025-09-06
// @description Takes a screenshot from a YouTube video in current quality, saves to the clipboard (Ctrl+Alt+Shift+Q) or a file (Ctrl+Alt+Shift+W).
// @author CJMAXiK
// @license MIT
// @match https://www.youtube.com/watch*
// @icon https://icons.duckduckgo.com/ip2/youtube.com.ico
// @website https://gist.github.com/cjmaxik/6211f5381c98fbd55267623de4650032
// @grant none
// ==/UserScript==
// SETTINGS
const slugifyTitle = false;
const screenshotTitle = "channelName"; // channelName (default), videoTitle, videoId
/**
* @see https://byby.dev/js-slugify-string
* @param {string} str
*/
function slugify(str) {
if (!slugifyTitle) return str;
return String(str)
.normalize("NFKD")
.replace(/[\u0300-\u036f]/g, "")
.trim()
.toLowerCase()
.replace(/[^a-z0-9 -]/g, "")
.replace(/\s+/g, "-")
.replace(/-+/g, "-");
}
/**
* @param {Blob} blob
*/
const saveToClipboard = (blob) => {
try {
navigator.clipboard.write([
new ClipboardItem({
"image/png": blob,
}),
]);
console.log("Screenshot copied to the clipboard!");
} catch (err) {
console.error("Clipboard is not accessible, saving to file instead", err);
saveToFile(blob);
}
};
/**
* @param {Blob} blob
*/
const saveToFile = (blob) => {
try {
const data = {
videoTitle: document
.querySelector("ytd-watch-metadata #title > h1 > yt-formatted-string")
.getAttribute("title"),
videoId: new URL(window.location.href).searchParams.get("v"),
channelName: document.querySelector("ytd-channel-name #text > a")
.textContent,
};
const now = new Date();
const currentTime = `${now.toDateString()} ${now.toLocaleTimeString()}`;
const titlePrefix = data[screenshotTitle] ?? "Screenshot";
const link = document.createElement("a");
link.href = URL.createObjectURL(blob);
link.download = slugify(`${titlePrefix} - ${currentTime}`) + ".png";
link.click();
URL.revokeObjectURL(link.href);
console.log("Screenshot saved as a file!");
} catch (err) {
console.error("Save to file was unsuccessful", err);
}
};
/**
* @param {boolean} shouldDownload
*/
const screenshot = (shouldDownload) => {
const video = document.querySelector("video");
if (!video) throw new Error("Cannot find the video element, aborting...");
const canvas = document.createElement("canvas");
const context = canvas.getContext("2d");
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
context.drawImage(video, 0, 0, canvas.width, canvas.height);
canvas.toBlob((blob) => {
if (!blob) throw new Error("The blob is empty, aborting...");
shouldDownload ? saveToFile(blob) : saveToClipboard(blob);
});
canvas.remove();
};
document.addEventListener("keydown", (e) => {
// The shortcuts are:
// - Ctrl+Alt+Shift+Q for clipboard
// - Ctrl+Alt+Shift+W for file
if (!e.ctrlKey || !e.altKey || !e.shiftKey) return;
if (e.code !== "KeyQ" && e.code !== "KeyW") return;
screenshot(e.code === "KeyW");
});