// ==UserScript==
// @name Focused YouTube
// @version 2025-06-29.25
// @author Richard B
// @namespace https://www.365devnet.eu/focusedyoutube
// @description Remove ads, shorts, and algorithmic suggestions on YouTube (EN/NL/DE/FR)
// @match *://*.youtube.com/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=youtube.com
// @run-at document-start
// @grant GM_setValue
// @grant GM_getValue
// @license MIT
// ==/UserScript==
// Credits:
// Originally based on Focused YouTube by Kervyn
// https://github.com/KervynH/Focused-YouTube
//
// Additional credits: https://github.com/lawrencehook/remove-youtube-suggestions
/*
MIT License
Copyright (c) 2025 Richard B
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
'use strict';
// Config custom settings here
const DEFAULT_SETTINGS = {
/// homepage redirect ///
redirectHomepage: false, // Options: 'wl', 'subs', 'lib', false
hideHomepageButton: false,
/// homepage suggestions ///
hideAllSuggestions: false,
hideAllButOneRow: false,
hideInfiniteScroll: false,
/// video player ///
skipAds: true,
hideLiveChat: true,
hideRelatedVideos: true,
hideMiniPlayerButton: true,
hidePlayNextButton: true,
forceCinemaMode: true,
/// shorts ///
hideShorts: true,
redirectShortsPlayer: true,
/// misc ///
hideSearchButton: false,
cleanSearchResults: true,
hideSponsoredContent: true,
hideFilterBar: true,
forceAudioTrack: true,
preferredAudioLanguage: 'en', // Options: 'en', 'nl', 'de', 'fr', 'es', 'it', 'pt', 'ja', 'ko', 'zh', etc.
};
const SETTINGS = DEFAULT_SETTINGS;
// Mark settings in HTML
const HTML = document.documentElement;
Object.keys(SETTINGS).forEach(key => {
HTML.setAttribute(key, SETTINGS[key]);
});
// Add css to remove unnecessary elements
const DESKTOP_BLOCK_LIST = [
// Ads
'#masthead-ad',
'ytd-mealbar-promo-renderer',
'ytd-carousel-ad-renderer',
'.ytd-display-ad-renderer',
'ytd-ad-slot-renderer',
'div.ytp-ad-overlay-image',
'.iv-branding.annotation-type-custom.annotation',
// Shorts
'html[hideShorts="true"] ytd-rich-section-renderer',
'html[hideShorts="true"] ytd-reel-shelf-renderer',
'html[hideShorts="true"] ytd-shelf-renderer',
// Left Bar Navigation
'a[href="/feed/trending"]',
'a[href="/feed/explore"]',
'html[hideShorts="true"] ytd-guide-section-renderer a[title="Shorts"]',
'html[hideShorts="true"] ytd-mini-guide-entry-renderer[aria-label="Shorts"]',
'ytd-guide-section-renderer.ytd-guide-renderer.style-scope:nth-of-type(4)',
'ytd-guide-section-renderer.ytd-guide-renderer.style-scope:nth-of-type(3)',
// Homepage
'html[hideHomepageButton="true"] a:not(#logo)[href="/"]',
'html[hideAllSuggestions="true"] ytd-browse[page-subtype="home"]',
'html[hideAllButOneRow="true"] ytd-browse[page-subtype="home"] #header',
'html[hideAllButOneRow="true"] ytd-browse[page-subtype="home"] ytd-rich-grid-renderer>#contents>ytd-rich-grid-row:nth-child(n+2)',
'html[hideInfiniteScroll="true"] ytd-browse[page-subtype="home"] ytd-rich-grid-renderer>#contents>ytd-continuation-item-renderer',
// Video Player
'html[hideRelatedVideos="true"] #secondary>div.circle',
'html[hideRelatedVideos="true"] #related',
'html[hideRelatedVideos="true"] .html5-endscreen',
'html[hidePlayNextButton="true"] a.ytp-next-button.ytp-button',
'html[hidePlayNextButton="true"] a.ytp-prev-button.ytp-button',
'html[hideChat="true"] #chat',
'html[hideMiniPlayerButton="true"] .ytp-button.ytp-miniplayer-button',
// '#movie_player button.ytp-button.ytp-share-button',
// '#movie_player button.ytp-button.ytp-watch-later-button',
'.ytd-download-button-renderer.style-scope',
// Search
'div.sbdd_a',
'#container.ytd-search ytd-search-pyv-renderer',
'html[hideSearchButton="true"] div.ytd-masthead>ytd-searchbox',
'html[hideSearchButton="true"] div.ytd-masthead>#voice-search-button',
// Filter Bar (Chips)
'html[hideFilterBar="true"] ytd-feed-filter-chip-bar-renderer',
'html[hideFilterBar="true"] #chips-wrapper',
];
const MOBILE_BLOCK_LIST = [
// Ads
'ytm-companion-ad-renderer',
'ytm-promoted-sparkles-web-renderer',
// Homepage
'html[hideHomepageButton="true"] div[tab-identifier="FEwhat_to_watch"]',
'html[hideSearchButton="true"] #header-bar > header > div > button',
'html[hideSearchButton="true"] #center.style-scope.ytd-masthead',
// Shorts in search results
'html[hideShorts="true"] ytm-reel-shelf-renderer.item',
// Video Player
'html[hideRelatedVideos="true"] ytm-item-section-renderer[section-identifier="related-items"]>lazy-list',
'html[hidePlayNextButton="true"] .player-controls-middle-core-buttons > div:nth-child(1)',
'html[hidePlayNextButton="true"] .player-controls-middle-core-buttons > div:nth-child(5)',
// Navigation Bar
'html[hideHomepageButton="true"] ytm-pivot-bar-item-renderer:nth-child(1)',
'html[hideShorts="true"] ytm-pivot-bar-item-renderer:nth-child(2)',
'ytm-chip-cloud-chip-renderer[chip-style="STYLE_EXPLORE_LAUNCHER_CHIP"]',
// Filter Bar (Chips) - Mobile
'html[hideFilterBar="true"] ytm-feed-filter-chip-bar-renderer',
];
function addStyle(css) {
const style = document.createElement('style');
style.textContent = css;
document.head.appendChild(style);
}
// Add spacing fix for when filter bar is hidden
function addFilterBarSpacingFix() {
const spacingCSS = `
/* Fix spacing when filter bar is hidden - Multiple selectors for better compatibility */
html[hideFilterBar="true"] ytd-browse[page-subtype="home"] #primary #contents,
html[hideFilterBar="true"] ytd-browse[page-subtype="home"] ytd-rich-grid-renderer,
html[hideFilterBar="true"] ytd-browse[page-subtype="home"] #contents.ytd-rich-grid-renderer {
padding-top: 32px !important;
margin-top: 16px !important;
}
/* Target the first video row specifically */
html[hideFilterBar="true"] ytd-browse[page-subtype="home"] ytd-rich-grid-row:first-child {
margin-top: 24px !important;
padding-top: 16px !important;
}
/* Target the rich grid container */
html[hideFilterBar="true"] ytd-browse[page-subtype="home"] #primary > #contents {
padding-top: 32px !important;
}
/* Mobile spacing fix - multiple selectors */
html[hideFilterBar="true"] ytm-browse[page-subtype="home"] #contents,
html[hideFilterBar="true"] ytm-rich-grid-renderer #contents {
padding-top: 24px !important;
margin-top: 12px !important;
}
/* Subscriptions page spacing */
html[hideFilterBar="true"] ytd-browse[page-subtype="subscriptions"] #primary #contents {
padding-top: 32px !important;
}
`;
addStyle(spacingCSS);
}
if (location.hostname.startsWith('www.')) {
const styles = DESKTOP_BLOCK_LIST.map(e => `${e} {display: none !important}`).join('\n');
addStyle(styles);
addFilterBarSpacingFix();
}
if (location.hostname.startsWith('m.')) {
const styles = MOBILE_BLOCK_LIST.map(e => `${e} {display: none !important}`).join('\n');
addStyle(styles);
addFilterBarSpacingFix();
}
// Start running dynamic settings
runDynamicSettings();
/***** Functions *****/
function runDynamicSettings() {
if (SETTINGS.redirectHomepage) redirectHomepage();
if (SETTINGS.redirectShortsPlayer) redirectShortsPlayer();
// if (SETTINGS.hideShorts) hideShortsVideos();
if (SETTINGS.cleanSearchResults) cleanSearchResults();
if (SETTINGS.skipAds) skipVideoAds();
if (SETTINGS.hideRelatedVideos) disableRelatedAutoPlay();
if (SETTINGS.forceCinemaMode) forceCinemaMode();
if (SETTINGS.forceAudioTrack) forceAudioTrack();
setTimeout(runDynamicSettings, 500);
}
function redirectHomepage() {
if (location.pathname == '/') {
if (SETTINGS.redirectHomepage == 'wl') {
location.replace('/playlist/?list=WL');
}
if (SETTINGS.redirectHomepage == 'subs') {
location.replace('/feed/subscriptions');
}
if (SETTINGS.redirectHomepage == 'lib') {
location.replace('/feed/library');
}
}
}
function redirectShortsPlayer() {
if (location.pathname.startsWith('/shorts')) {
const redirPath = location.pathname.replace('shorts', 'watch');
location.replace(redirPath);
}
}
function disableRelatedAutoPlay() {
// turn off auto play button
const autoplayButton = document.querySelectorAll('.ytp-autonav-toggle-button[aria-checked=true]');
autoplayButton?.forEach(e => {
if (e && e.offsetParent) {
e.click();
}
});
// turn off auto play button on mobile
const mAutoplayButton = document.querySelectorAll('.ytm-autonav-toggle-button-container[aria-pressed=true]');
mAutoplayButton?.forEach(e => {
if (e && e.offsetParent) {
e.click();
}
});
}
function forceAudioTrack() {
if (location.pathname.startsWith('/watch')) {
const video = document.querySelector('.html5-main-video');
if (video && video.audioTracks && video.audioTracks.length > 1) {
// Look for preferred language audio track
const preferredLang = SETTINGS.preferredAudioLanguage.toLowerCase();
for (let i = 0; i < video.audioTracks.length; i++) {
const track = video.audioTracks[i];
const trackLang = track.language.toLowerCase();
// Check for exact match or partial match (e.g., 'en-US' matches 'en')
if (trackLang === preferredLang || trackLang.startsWith(preferredLang + '-')) {
if (!track.enabled) {
// Disable all other tracks
for (let j = 0; j < video.audioTracks.length; j++) {
video.audioTracks[j].enabled = false;
}
// Enable preferred track
track.enabled = true;
console.log(`Focused YouTube: Switched to ${track.language} audio track`);
break;
}
}
}
}
// Alternative method for YouTube's custom audio track selector
const audioButton = document.querySelector('.ytp-button.ytp-settings-button');
if (audioButton && audioButton.offsetParent) {
// This is a more complex implementation that would require clicking through YouTube's settings menu
// For now, we'll rely on the HTML5 audio tracks API above
}
}
}
function forceCinemaMode() {
if (location.pathname.startsWith('/watch')) {
// Check if we're not already in cinema mode
const pageManager = document.querySelector('ytd-watch-flexy');
if (pageManager && !pageManager.hasAttribute('theater')) {
// Find and click the cinema mode button
const cinemaButton = document.querySelector('.ytp-size-button');
if (cinemaButton && cinemaButton.offsetParent) {
cinemaButton.click();
}
// Alternative method: try to find the theater mode button
const theaterButton = document.querySelector('button[aria-keyshortcuts="t"]');
if (theaterButton && theaterButton.offsetParent) {
theaterButton.click();
}
// Another alternative: look for the specific theater mode button
const theaterModeBtn = document.querySelector('.ytp-button[data-tooltip-target-id*="theater"]');
if (theaterModeBtn && theaterModeBtn.offsetParent) {
theaterModeBtn.click();
}
}
}
}
function hideShortsVideos() {
const shortsLinks = document.querySelectorAll('a[href^="/shorts"]');
if (location.pathname == '/feed/subscriptions') {
shortsLinks.forEach(link => {
// For desktop
link.closest('ytd-rich-item-renderer')?.remove();
// For mobile
link.closest('ytm-item-section-renderer')?.remove();
});
}
// Hide shorts on search result pages
if (location.pathname.startsWith('/results')) {
shortsLinks.forEach(link => {
// For desktop
link.closest('ytd-video-renderer')?.remove();
// For mobile
link.closest('ytm-video-with-context-renderer')?.remove();
});
}
// Hide the "shorts" tab on channel page
if (location.pathname.startsWith('/@')) {
document.querySelectorAll('div.tab-content')?.forEach(tab => {
if (tab.innerText == "SHORTS") tab.parentElement.remove(); // desktop
});
document.querySelectorAll('a[role="tab"]')?.forEach(tab => {
if (tab.innerText == 'SHORTS') tab.remove(); // mobile
});
}
}
function skipVideoAds() {
if (location.pathname.startsWith('/watch')) {
// click "skip ad" button if it exists
// during the first 5s, th button is not clickable in UI, but it's clickable in console
const adSkipButton = document.querySelector(".ytp-ad-skip-button-slot button,.ytp-ad-overlay-close-button");
adSkipButton?.click();
// skip ad video
const adVideo = document.querySelector('.ad-showing');
if (adVideo) {
const video = document.querySelector('.html5-main-video');
if (video && !isNaN(video?.duration)) {
video.play();
video.currentTime = video?.duration;
}
}
}
}
function cleanSearchResults() {
if (location.pathname.startsWith('/results')) {
// Mobile
const badges = document.querySelectorAll('ytm-badge');
badges.forEach(badge => {
// Only support Chinese and English now
if (badge.innerText == '相關影片' || badge.innerText == '相关视频' || badge.innerText == 'Related') {
badge.closest('ytm-video-with-context-renderer')?.remove();
}
});
}
}