Forces Twitch streams to always start at the highest quality available.
// ==UserScript==
// @name Twitch Force Max Quality
// @name:de Twitch Maximale Qualität Erzwingen
// @name:fr Twitch Forcer la Qualité Maximale
// @name:es Twitch Forzar máxima calidad
// @name:it Twitch Forza la massima qualità
// @name:zh-CN Twitch 强制最高画质
// @description Forces Twitch streams to always start at the highest quality available.
// @description:de Erzwingt, dass Twitch-Streams immer in der höchstmöglichen Qualität starten.
// @description:fr Force les flux Twitch à toujours démarrer mit der höchsten verfügbaren Qualität.
// @description:es Fuerza a que los streams de Twitch comiencen siempre con la máxima calidad disponible.
// @description:it Forza gli streaming di Twitch ad avviarsi sempre con la massima qualità disponibile.
// @description:zh-CN 强制 Twitch 流始终以最高可用画质开始。
// @version 0.0.4
// @author Wack.3gp (https://greasyfork.org/users/4792)
// @copyright 2026+, Wack.3gp
// @namespace https://greasyfork.org/users/4792
// @license CC BY-NC-SA-4.0; https://creativecommons.org/licenses/by-nc-sa/4.0/
// @icon https://assets.twitch.tv/assets/favicon-32-e29e246c157142c94346.png
// @match https://www.twitch.tv/*
// @exclude https://www.twitch.tv/settings*
// @exclude https://www.twitch.tv/wallet*
// @exclude https://www.twitch.tv/inventory*
// @exclude https://www.twitch.tv/dashboard*
// @grant none
// @run-at document-end
// @supportURL https://greasyfork.org/scripts/577775/feedback
// @contributionURL https://www.paypal.com/donate/?hosted_button_id=BYW9D395KJWZ2
// @contributionAmount €1.00
// ==/UserScript==
/* jshint esversion: 11 */
(function() {
'use strict';
async function setHighestQualitySilent(playerContainer) {
const settingsBtn = playerContainer.querySelector('[data-a-target="player-settings-button"]');
if (!settingsBtn) return;
const style = document.createElement('style');
style.id = 'silent-quality-fix';
style.innerHTML = `
[data-a-target="player-settings-menu"],
.video-player__settings-menu {
display: none !important;
visibility: hidden !important;
opacity: 0 !important;
pointer-events: none !important;
}
`;
document.head.appendChild(style);
try {
settingsBtn.click();
await new Promise(r => setTimeout(r, 200));
const qualityMenu = Array.from(document.querySelectorAll('button'))
.find(el => {
const text = el.textContent.toLowerCase();
return text.includes('qualit') || text.includes('画质') || text.includes('calidad');
});
if (qualityMenu) {
qualityMenu.click();
await new Promise(r => setTimeout(r, 200));
const options = Array.from(document.querySelectorAll('[role="menuitemradio"]'));
const bestOption = options
.map(el => {
const text = el.textContent.trim();
const compStyle = window.getComputedStyle(el);
const isAuto = text.toLowerCase().includes('auto') || text.includes('自动');
const isDisabled = el.getAttribute('aria-disabled') === 'true' || parseFloat(compStyle.opacity) < 0.6;
const res = parseInt(text.match(/(\d+)p/)?.[1] || "0");
return { el, text, isAuto, isDisabled, res };
})
.filter(o => !o.isAuto && !o.isDisabled && o.res > 0)
.sort((a, b) => b.res - a.res)[0];
if (bestOption) {
const isChecked = bestOption.el.querySelector('[data-a-target="tw-core-svg"]');
if (!isChecked) {
bestOption.el.click();
console.log("[Twitch-Fix] Successfully switched to " + bestOption.text);
}
}
}
} catch (e) {
console.error("[Twitch-Fix] Error switching quality:", e);
} finally {
await new Promise(r => setTimeout(r, 150));
style.remove();
if (document.querySelector('[data-a-target="player-settings-menu"]')) {
settingsBtn.click();
}
}
}
let lastUrl = "";
setInterval(() => {
const currentUrl = window.location.href;
const players = document.querySelectorAll('.video-player, .featured-content-carousel__video-player');
players.forEach(player => {
if (currentUrl !== lastUrl || !player.dataset.qualityChecked) {
lastUrl = currentUrl;
player.dataset.qualityChecked = "true";
setTimeout(() => setHighestQualitySilent(player), 3000);
}
});
}, 4000);
})();