Bye Bye YouTube Ads

Automatically block/skip YouTube video ads on www.youtube.com (desktop only)

当前为 2025-05-07 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Bye Bye YouTube Ads
  3. // @version 1.0
  4. // @description Automatically block/skip YouTube video ads on www.youtube.com (desktop only)
  5. // @author DishantX
  6. // @match *://www.youtube.com/*
  7. // @exclude *://www.youtube.com/*/music*
  8. // @exclude *://music.youtube.com/*
  9. // @exclude *://m.youtube.com/*
  10. // @grant none
  11. // @namespace https://greasyfork.org/users/1467023
  12. // ==/UserScript==
  13.  
  14. (function() {
  15. 'use strict';
  16.  
  17. // Click the YouTube "Skip Ad" button if present.
  18. function clickSkipButton() {
  19. const skipBtn = document.querySelector('button.ytp-ad-skip-button, button.ytp-ad-skip-button-modern');
  20. if (skipBtn) {
  21. skipBtn.click();
  22. return true;
  23. }
  24. return false;
  25. }
  26.  
  27. // Skip an unskippable ad by jumping to the video's end.
  28. function skipUnskippableAd() {
  29. const video = document.querySelector('video');
  30. if (video && video.duration && isFinite(video.duration)) {
  31. video.currentTime = video.duration;
  32. }
  33. }
  34.  
  35. // Dismiss YouTube's adblock/premium popups if they appear.
  36. function handleAdBlockPopup() {
  37. // "No thanks" button on the upsell dialog.
  38. const noThanks = document.querySelector('yt-upsell-dialog-renderer tp-yt-paper-button[aria-label="No thanks"]');
  39. if (noThanks) {
  40. noThanks.click();
  41. return;
  42. }
  43. // "I understand and wish to proceed" button on another dialog.
  44. const proceed = document.querySelector('yt-button-renderer tp-yt-paper-button[aria-label="I understand and wish to proceed"]');
  45. if (proceed) {
  46. proceed.click();
  47. return;
  48. }
  49. // If a popup container is open with no close button, hide it.
  50. const popup = document.querySelector('ytd-popup-container');
  51. if (popup && popup.style.display !== 'none') {
  52. popup.style.display = 'none';
  53. }
  54. }
  55.  
  56. // Set up a MutationObserver to watch for ad-related DOM changes.
  57. const observer = new MutationObserver((mutationsList, obs) => {
  58. // If an ad is playing (player has 'ad-showing' class) then try to skip it.
  59. const player = document.getElementById('movie_player');
  60. if (player && player.classList.contains('ad-showing')) {
  61. // First try clicking the skip button if it exists.
  62. if (!clickSkipButton()) {
  63. // If no skip button, jump the ad to the end.
  64. skipUnskippableAd();
  65. }
  66. }
  67. // Also attempt to dismiss any adblock warning popups.
  68. handleAdBlockPopup();
  69. });
  70.  
  71. // Observe the entire document for added/removed nodes (needed because YouTube is an SPA).
  72. observer.observe(document, { childList: true, subtree: true });
  73.  
  74. // Run skip logic once immediately after page load in case an ad is already showing.
  75. if (document.readyState === 'complete' || document.readyState === 'interactive') {
  76. const player = document.getElementById('movie_player');
  77. if (player && player.classList.contains('ad-showing')) {
  78. if (!clickSkipButton()) {
  79. skipUnskippableAd();
  80. }
  81. }
  82. handleAdBlockPopup();
  83. }
  84. })();