Skip to content

Instantly share code, notes, and snippets.

@romanzipp
Last active December 9, 2025 10:22
Show Gist options
  • Select an option

  • Save romanzipp/4225a5d81be72a59c06c11e2ff0c0495 to your computer and use it in GitHub Desktop.

Select an option

Save romanzipp/4225a5d81be72a59c06c11e2ff0c0495 to your computer and use it in GitHub Desktop.
Tampermonkey: YouTube always select Highest Quality
// ==UserScript==
// @name YouTube always select Highest Quality
// @namespace http://tampermonkey.net/
// @version 0.2.0
// @description Automatically select the best available quality for YouTube videos
// @author Roman Zipp <[email protected]>
// @match https://www.youtube.com/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=youtube.com
// @grant none
// ==/UserScript==
(function() {
'use strict';
const log = (...args) => console.log('[TM-YT-Premium-Quality]', ...args);
log('loaded');
function selectQuality(qualityButton) {
qualityButton.click();
const menuItems = document.querySelectorAll('.ytp-settings-menu .ytp-panel .ytp-menuitem');
menuItems.forEach(item => {
if (!item.innerText.includes('Quality')) {
return;
}
log('found quality button. clicking')
item.click();
const qualities = [...document.querySelectorAll('.ytp-settings-menu .ytp-panel.ytp-quality-menu .ytp-menuitem')];
// use max 1440p if available
const fourteenFourtyPeePee = qualities.find(q => q.innerText.includes('1440p'))
if (fourteenFourtyPeePee) {
fourteenFourtyPeePee.click();
log('chose 1440p');
return;
}
// just use the best one aye
const bestQuality = qualities[0];
bestQuality.click();
log('couldnt find any preferred quality...');
log(qualities.map(q => q.innerText));
})
}
function init() {
log('init');
const qualityButton = document.querySelector('.ytp-settings-button');
if ((qualityButton !== null) && (qualityButton !== undefined)) {
log('found quality button without watching for mutations, excellent news.');
selectQuality(qualityButton);
return;
}
const observer = new MutationObserver((mutations) => {
for (const { addedNodes } of mutations) {
for (const node of addedNodes) {
if (!node.tagName) {
continue; // not an element
}
if (node.classList.contains('ytp-settings-button')) {
selectQuality(node);
log('found quality button in node, disconnecting observer')
observer.disconnect();
continue;
}
const qualityButtons = node.getElementsByClassName('ytp-settings-button');
if (qualityButtons[0] === undefined) {
contine;
}
selectQuality(qualityButtons[0]);
log('found quality button in children, disconnecting observer');
observer.disconnect();
}
}
});
observer.observe(document, {
childList: true,
subtree: true,
});
}
init();
document.body.addEventListener("yt-navigate-finish", function(event) {
init();
});
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment