Greasy Fork is available in English.

Auto Skip YouTube Ads

Automatically skip YouTube ads instantly. Undetected by YouTube ad blocker warnings.

Nainstalovat skript?
Skript doporučený autorem

Mohlo by se vám také líbit YouTube Shorts To Normal Video.

Nainstalovat skript
  1. // ==UserScript==
  2. // @name Auto Skip YouTube Ads
  3. // @name:ar تخطي إعلانات YouTube تلقائيًا
  4. // @name:es Saltar Automáticamente Anuncios De YouTube
  5. // @name:fr Ignorer Automatiquement Les Publicités YouTube
  6. // @name:hi YouTube विज्ञापन स्वचालित रूप से छोड़ें
  7. // @name:id Lewati Otomatis Iklan YouTube
  8. // @name:ja YouTube 広告を自動スキップ
  9. // @name:ko YouTube 광고 자동 건너뛰기
  10. // @name:nl YouTube-Advertenties Automatisch Overslaan
  11. // @name:pt-BR Pular Automaticamente Anúncios Do YouTube
  12. // @name:ru Автоматический Пропуск Рекламы На YouTube
  13. // @name:vi Tự Động Bỏ Qua Quảng Cáo YouTube
  14. // @name:zh-CN 自动跳过 YouTube 广告
  15. // @name:zh-TW 自動跳過 YouTube 廣告
  16. // @namespace https://github.com/tientq64/userscripts
  17. // @version 7.2.2
  18. // @description Automatically skip YouTube ads instantly. Undetected by YouTube ad blocker warnings.
  19. // @description:ar تخطي إعلانات YouTube تلقائيًا على الفور. دون أن يتم اكتشاف ذلك من خلال تحذيرات أداة حظر الإعلانات في YouTube.
  20. // @description:es Omite automáticamente los anuncios de YouTube al instante. Sin que te detecten las advertencias del bloqueador de anuncios de YouTube.
  21. // @description:fr Ignorez automatiquement et instantanément les publicités YouTube. Non détecté par les avertissements du bloqueur de publicités YouTube.
  22. // @description:hi YouTube विज्ञापनों को स्वचालित रूप से तुरंत छोड़ दें। YouTube विज्ञापन अवरोधक चेतावनियों द्वारा पता नहीं लगाया गया।
  23. // @description:id Lewati iklan YouTube secara otomatis secara instan. Tidak terdeteksi oleh peringatan pemblokir iklan YouTube.
  24. // @description:ja YouTube 広告を即座に自動的にスキップします。YouTube 広告ブロッカーの警告には検出されません。
  25. // @description:ko YouTube 광고를 즉시 자동으로 건너뜁니다. YouTube 광고 차단 경고에 감지되지 않습니다.
  26. // @description:nl Sla YouTube-advertenties direct automatisch over. Ongemerkt door YouTube-adblockerwaarschuwingen.
  27. // @description:pt-BR Pule anúncios do YouTube instantaneamente. Não detectado pelos avisos do bloqueador de anúncios do YouTube.
  28. // @description:ru Автоматически пропускать рекламу YouTube мгновенно. Не обнаруживается предупреждениями блокировщиков рекламы YouTube.
  29. // @description:vi Tự động bỏ qua quảng cáo YouTube ngay lập tức. Không bị phát hiện bởi cảnh báo trình chặn quảng cáo của YouTube.
  30. // @description:zh-CN 立即自动跳过 YouTube 广告。不会被 YouTube 广告拦截器警告检测到。
  31. // @description:zh-TW 立即自動跳過 YouTube 廣告。 YouTube 廣告攔截器警告未被偵測到。
  32. // @author tientq64
  33. // @icon https://cdn-icons-png.flaticon.com/64/2504/2504965.png
  34. // @match https://www.youtube.com/*
  35. // @match https://m.youtube.com/*
  36. // @match https://music.youtube.com/*
  37. // @exclude https://studio.youtube.com/*
  38. // @grant none
  39. // @license MIT
  40. // @compatible firefox
  41. // @compatible chrome
  42. // @compatible opera
  43. // @compatible safari
  44. // @compatible edge
  45. // @noframes
  46. // @homepage https://github.com/tientq64/userscripts/tree/main/scripts/Auto-Skip-YouTube-Ads
  47. // ==/UserScript==
  48.  
  49. function skipAd() {
  50. if (checkIsYouTubeShorts()) return
  51.  
  52. // This element appears when a video ad appears.
  53. const adShowing = document.querySelector('.ad-showing')
  54.  
  55. // Timed pie countdown ad.
  56. const pieCountdown = document.querySelector('.ytp-ad-timed-pie-countdown-container')
  57.  
  58. // Survey questions in video player.
  59. const surveyQuestions = document.querySelector('.ytp-ad-survey-questions')
  60.  
  61. if (adShowing === null && pieCountdown === null && surveyQuestions === null) return
  62.  
  63. let playerEl
  64. let player
  65. if (isYouTubeMobile || isYouTubeMusic) {
  66. playerEl = document.querySelector('#movie_player')
  67. player = playerEl
  68. } else {
  69. playerEl = document.querySelector('#ytd-player')
  70. player = playerEl && playerEl.getPlayer()
  71. }
  72.  
  73. if (playerEl === null || player === null) {
  74. console.log({
  75. message: 'Player not found',
  76. timeStamp: getCurrentTimeString()
  77. })
  78. return
  79. }
  80.  
  81. // ad.classList.remove('ad-showing')
  82.  
  83. let adVideo = null
  84.  
  85. if (pieCountdown === null && surveyQuestions === null) {
  86. adVideo = document.querySelector(
  87. '#ytd-player video.html5-main-video, #song-video video.html5-main-video'
  88. )
  89.  
  90. console.table({
  91. message: 'Ad video',
  92. video: adVideo !== null,
  93. src: adVideo?.src,
  94. paused: adVideo?.paused,
  95. currentTime: adVideo?.currentTime,
  96. duration: adVideo?.duration,
  97. timeStamp: getCurrentTimeString()
  98. })
  99.  
  100. if (adVideo === null || !adVideo.src || adVideo.paused || isNaN(adVideo.duration)) return
  101.  
  102. console.log({
  103. message: 'Ad video has finished loading',
  104. timeStamp: getCurrentTimeString()
  105. })
  106. }
  107.  
  108. if (isYouTubeMusic && adVideo !== null) {
  109. adVideo.currentTime = adVideo.duration
  110.  
  111. console.table({
  112. message: 'Ad skipped',
  113. timeStamp: getCurrentTimeString(),
  114. adShowing: adShowing !== null,
  115. pieCountdown: pieCountdown !== null,
  116. surveyQuestions: surveyQuestions !== null
  117. })
  118. } else {
  119. const videoData = player.getVideoData()
  120. const videoId = videoData.video_id
  121. const start = Math.floor(player.getCurrentTime())
  122.  
  123. if ('loadVideoWithPlayerVars' in playerEl) {
  124. playerEl.loadVideoWithPlayerVars({ videoId, start })
  125. } else {
  126. playerEl.loadVideoByPlayerVars({ videoId, start })
  127. }
  128.  
  129. console.table({
  130. message: 'Ad skipped',
  131. videoId,
  132. start,
  133. title: videoData.title,
  134. timeStamp: getCurrentTimeString(),
  135. adShowing: adShowing !== null,
  136. pieCountdown: pieCountdown !== null,
  137. surveyQuestions: surveyQuestions !== null
  138. })
  139. }
  140. }
  141.  
  142. function checkIsYouTubeShorts() {
  143. return location.pathname.startsWith('/shorts/')
  144. }
  145.  
  146. function getCurrentTimeString() {
  147. return new Date().toTimeString().split(' ', 1)[0]
  148. }
  149.  
  150. function addCss() {
  151. const adsSelectors = [
  152. // Ad banner in the upper right corner, above the video playlist.
  153. '#player-ads',
  154. '#panels > ytd-engagement-panel-section-list-renderer[target-id="engagement-panel-ads"]',
  155.  
  156. // Masthead ad on home page.
  157. '#masthead-ad',
  158.  
  159. // Sponsored ad video items on home page.
  160. // 'ytd-ad-slot-renderer',
  161.  
  162. // '.ytp-suggested-action',
  163. '.yt-mealbar-promo-renderer',
  164.  
  165. // Featured product ad banner at the bottom left of the video.
  166. '.ytp-featured-product',
  167.  
  168. // Products shelf ad banner below the video description.
  169. 'ytd-merch-shelf-renderer',
  170.  
  171. // YouTube Music Premium trial promotion dialog, bottom left corner.
  172. 'ytmusic-mealbar-promo-renderer',
  173.  
  174. // YouTube Music Premium trial promotion banner on home page.
  175. 'ytmusic-statement-banner-renderer'
  176. ]
  177. const adsSelector = adsSelectors.join(',')
  178. const css = `${adsSelector} { display: none !important; }`
  179. const style = document.createElement('style')
  180. style.textContent = css
  181. document.head.appendChild(style)
  182. }
  183.  
  184. /**
  185. * Remove ad elements using JavaScript because these selectors require the use of the CSS
  186. * `:has` selector which is not supported in older browser versions.
  187. */
  188. function removeAdElements() {
  189. const adSelectors = [
  190. // Sponsored ad video items on home page.
  191. // ['ytd-rich-item-renderer', '.ytd-ad-slot-renderer'],
  192.  
  193. // ['ytd-rich-section-renderer', '.ytd-statement-banner-renderer'],
  194.  
  195. // Ad videos on YouTube Shorts.
  196. ['ytd-reel-video-renderer', '.ytd-ad-slot-renderer']
  197.  
  198. // Ad blocker warning dialog.
  199. // ['tp-yt-paper-dialog', '#feedback.ytd-enforcement-message-view-model'],
  200.  
  201. // Survey dialog on home page, located at bottom right.
  202. // ['tp-yt-paper-dialog', ':scope > ytd-checkbox-survey-renderer'],
  203.  
  204. // Survey to rate suggested content, located at bottom right.
  205. // ['tp-yt-paper-dialog', ':scope > ytd-single-option-survey-renderer']
  206. ]
  207. for (const adSelector of adSelectors) {
  208. const adEl = document.querySelector(adSelector[0])
  209. if (adEl === null) continue
  210. const neededEl = adEl.querySelector(adSelector[1])
  211. if (neededEl === null) continue
  212. adEl.remove()
  213. }
  214. }
  215.  
  216. const isYouTubeMobile = location.hostname === 'm.youtube.com'
  217. const isYouTubeDesktop = !isYouTubeMobile
  218.  
  219. const isYouTubeMusic = location.hostname === 'music.youtube.com'
  220. const isYouTubeVideo = !isYouTubeMusic
  221.  
  222. addCss()
  223.  
  224. if (isYouTubeVideo) {
  225. window.setInterval(removeAdElements, 1000)
  226. removeAdElements()
  227. }
  228.  
  229. window.setInterval(skipAd, 500)
  230. skipAd()
  231.  
  232. // const observer = new MutationObserver(skipAd)
  233. // observer.observe(document.body, {
  234. // attributes: true,
  235. // attributeFilter: ['class'],
  236. // childList: true,
  237. // subtree: true
  238. // })