// ==UserScript== // @name RafBlocker // @namespace http://tampermonkey.net/ // @version 1.0 // @description Attempts to block various YouTube ads (pre-roll, mid-roll, banners) and automatically skip segments, while trying to prevent playlist skipping errors. // @author Raf // @match *://www.youtube.com/* // @grant none // @run-at document-idle // @license MIT // @downloadURL none // ==/UserScript== /* * MIT License * * Copyright (c) 2025 Raf (or your chosen name) * * 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. */ (function() { 'use strict'; // --- Configuration --- // The key selectors for ad elements on YouTube often change. // These are common selectors, but may become outdated. const AD_CONTAINER_SELECTOR = '.ad-container'; // Common pre/mid-roll ad container const VIDEO_AD_SELECTOR = '.video-ads, .ytp-ad-module'; // Video ad elements const SKIP_BUTTON_SELECTOR = '.ytp-ad-skip-button, .ytp-skip-ad-button'; // The skip ad button const AD_OVERLAY_SELECTOR = '.ytp-player-content-container .ytp-ce-element, .ytp-ad-overlay-container, .ytp-ad-image-overlay'; // Overlays and banners // Function to remove elements from the DOM function removeElement(selector) { document.querySelectorAll(selector).forEach(element => { if (element) { element.remove(); // console.log(`RafBlocker: Removed ad element: ${selector}`); } }); } // Function to skip the video ad function skipVideoAd() { const skipButton = document.querySelector(SKIP_BUTTON_SELECTOR); if (skipButton) { skipButton.click(); // console.log('RafBlocker: Clicked skip button.'); return true; } const videoPlayer = document.querySelector('video'); if (videoPlayer && document.querySelector('.ad-showing')) { // Attempt to force the video to the end if an ad is showing and no skip button is present // This is a common method for non-skippable ads. videoPlayer.currentTime = videoPlayer.duration; // console.log('RafBlocker: Forced video to end to skip non-skippable ad.'); return true; } return false; } // Main blocking logic function blockAds() { // 1. Remove video ad and banner containers removeElement(AD_CONTAINER_SELECTOR); removeElement(VIDEO_AD_SELECTOR); removeElement(AD_OVERLAY_SELECTOR); // 2. Try to click the skip ad button skipVideoAd(); // 3. (EXPERIMENTAL) Hide any remaining potential ad/sponsor elements using CSS // This is a fallback and can sometimes break the layout. const style = document.createElement('style'); style.type = 'text/css'; style.innerHTML = ` ${AD_CONTAINER_SELECTOR}, ${VIDEO_AD_SELECTOR}, ${AD_OVERLAY_SELECTOR}, ytd-promoted-sparkles-text-search-renderer, ytd-promoted-video-renderer, ytd-ad-slot-renderer, .ytp-ad-progress-bar-container, .ytp-ad-text { display: none !important; visibility: hidden !important; } `; document.head.appendChild(style); } // Use a MutationObserver to watch for changes in the DOM, like ads being loaded dynamically. const observer = new MutationObserver((mutations, obs) => { // Only run the blocking logic if YouTube is open and we're on a video page (optional optimization) if (window.location.pathname.startsWith('/watch')) { blockAds(); } }); // Start observing the body for configuration changes and subtree modifications observer.observe(document.body, { childList: true, subtree: true }); // Also run blockAds on an interval for a quick check, especially useful for initial load and overlays setInterval(blockAds, 500); // Check every 500 milliseconds })();