🏠

Auto Skip YouTube Ads

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


Install this script?
Author's suggested script

You may also like YouTube Shorts To Normal Video.

Install this script
Ask a question, post a review, or report the script.
// ==UserScript==
// @name               Auto Skip YouTube Ads
// @name:ar            تخطي إعلانات YouTube تلقائيًا
// @name:es            Saltar Automáticamente Anuncios De YouTube
// @name:fr            Ignorer Automatiquement Les Publicités YouTube
// @name:hi            YouTube विज्ञापन स्वचालित रूप से छोड़ें
// @name:id            Lewati Otomatis Iklan YouTube
// @name:ja            YouTube 広告を自動スキップ
// @name:ko            YouTube 광고 자동 건너뛰기
// @name:nl            YouTube-Advertenties Automatisch Overslaan
// @name:pt-BR         Pular Automaticamente Anúncios Do YouTube
// @name:ru            Автоматический Пропуск Рекламы На YouTube
// @name:vi            Tự Động Bỏ Qua Quảng Cáo YouTube
// @name:zh-CN         自动跳过 YouTube 广告
// @name:zh-TW         自動跳過 YouTube 廣告
// @namespace          https://github.com/tientq64/userscripts
// @version            7.2.1
// @description        Automatically skip YouTube ads instantly. Undetected by YouTube ad blocker warnings.
// @description:ar     تخطي إعلانات YouTube تلقائيًا على الفور. دون أن يتم اكتشاف ذلك من خلال تحذيرات أداة حظر الإعلانات في YouTube.
// @description:es     Omite automáticamente los anuncios de YouTube al instante. Sin que te detecten las advertencias del bloqueador de anuncios de YouTube.
// @description:fr     Ignorez automatiquement et instantanément les publicités YouTube. Non détecté par les avertissements du bloqueur de publicités YouTube.
// @description:hi     YouTube विज्ञापनों को स्वचालित रूप से तुरंत छोड़ दें। YouTube विज्ञापन अवरोधक चेतावनियों द्वारा पता नहीं लगाया गया।
// @description:id     Lewati iklan YouTube secara otomatis secara instan. Tidak terdeteksi oleh peringatan pemblokir iklan YouTube.
// @description:ja     YouTube 広告を即座に自動的にスキップします。YouTube 広告ブロッカーの警告には検出されません。
// @description:ko     YouTube 광고를 즉시 자동으로 건너뜁니다. YouTube 광고 차단 경고에 감지되지 않습니다.
// @description:nl     Sla YouTube-advertenties direct automatisch over. Ongemerkt door YouTube-adblockerwaarschuwingen.
// @description:pt-BR  Pule anúncios do YouTube instantaneamente. Não detectado pelos avisos do bloqueador de anúncios do YouTube.
// @description:ru     Автоматически пропускать рекламу YouTube мгновенно. Не обнаруживается предупреждениями блокировщиков рекламы YouTube.
// @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.
// @description:zh-CN  立即自动跳过 YouTube 广告。不会被 YouTube 广告拦截器警告检测到。
// @description:zh-TW  立即自動跳過 YouTube 廣告。 YouTube 廣告攔截器警告未被偵測到。
// @author             tientq64
// @icon               https://cdn-icons-png.flaticon.com/64/2504/2504965.png
// @match              https://www.youtube.com/*
// @match              https://m.youtube.com/*
// @match              https://music.youtube.com/*
// @exclude            https://studio.youtube.com/*
// @grant              none
// @license            MIT
// @compatible         firefox
// @compatible         chrome
// @compatible         opera
// @compatible         safari
// @compatible         edge
// @noframes
// @homepage           https://github.com/tientq64/userscripts/tree/main/scripts/Auto-Skip-YouTube-Ads
// ==/UserScript==
function skipAd() {
if (checkIsYouTubeShorts()) return
// This element appears when a video ad appears.
const adShowing = document.querySelector('.ad-showing')
// Timed pie countdown ad.
const pieCountdown = document.querySelector('.ytp-ad-timed-pie-countdown-container')
// Survey questions in video player.
const surveyQuestions = document.querySelector('.ytp-ad-survey-questions')
if (adShowing === null && pieCountdown === null && surveyQuestions === null) return
let playerEl
let player
if (isYouTubeMobile || isYouTubeMusic) {
playerEl = document.querySelector('#movie_player')
player = playerEl
} else {
playerEl = document.querySelector('#ytd-player')
player = playerEl && playerEl.getPlayer()
}
if (playerEl === null || player === null) {
console.log({
message: 'Player not found',
timeStamp: getCurrentTimeString()
})
return
}
// ad.classList.remove('ad-showing')
let adVideo = null
if (pieCountdown === null && surveyQuestions === null) {
adVideo = document.querySelector(
'#ytd-player video.html5-main-video, #song-video video.html5-main-video'
)
console.table({
message: 'Ad video',
video: adVideo !== null,
src: adVideo?.src,
paused: adVideo?.paused,
currentTime: adVideo?.currentTime,
duration: adVideo?.duration,
timeStamp: getCurrentTimeString()
})
if (adVideo === null || !adVideo.src || adVideo.paused || isNaN(adVideo.duration)) return
console.log({
message: 'Ad video has finished loading',
timeStamp: getCurrentTimeString()
})
}
if (isYouTubeMusic && adVideo !== null) {
adVideo.currentTime = adVideo.duration
console.table({
message: 'Ad skipped',
timeStamp: getCurrentTimeString(),
adShowing: adShowing !== null,
pieCountdown: pieCountdown !== null,
surveyQuestions: surveyQuestions !== null
})
} else {
const videoData = player.getVideoData()
const videoId = videoData.video_id
const start = Math.floor(player.getCurrentTime())
if ('loadVideoWithPlayerVars' in playerEl) {
playerEl.loadVideoWithPlayerVars({ videoId, start })
} else {
playerEl.loadVideoByPlayerVars({ videoId, start })
}
console.table({
message: 'Ad skipped',
videoId,
start,
title: videoData.title,
timeStamp: getCurrentTimeString(),
adShowing: adShowing !== null,
pieCountdown: pieCountdown !== null,
surveyQuestions: surveyQuestions !== null
})
}
}
function checkIsYouTubeShorts() {
return location.pathname.startsWith('/shorts/')
}
function getCurrentTimeString() {
return new Date().toTimeString().split(' ', 1)[0]
}
function addCss() {
const adsSelectors = [
// Ad banner in the upper right corner, above the video playlist.
'#player-ads',
'#panels > ytd-engagement-panel-section-list-renderer[target-id="engagement-panel-ads"]',
// Masthead ad on home page.
'#masthead-ad',
// Sponsored ad video items on home page.
// 'ytd-ad-slot-renderer',
// '.ytp-suggested-action',
'.yt-mealbar-promo-renderer',
// Featured product ad banner at the bottom left of the video.
'.ytp-featured-product',
// Products shelf ad banner below the video description.
'ytd-merch-shelf-renderer',
// YouTube Music Premium trial promotion dialog, bottom left corner.
'ytmusic-mealbar-promo-renderer',
// YouTube Music Premium trial promotion banner on home page.
'ytmusic-statement-banner-renderer'
]
const adsSelector = adsSelectors.join(',')
const css = `${adsSelector} { display: none !important; }`
const style = document.createElement('style')
style.textContent = css
document.head.appendChild(style)
}
/**
* Remove ad elements using JavaScript because these selectors require the use of the CSS
* `:has` selector which is not supported in older browser versions.
*/
function removeAdElements() {
const adSelectors = [
// Sponsored ad video items on home page.
// ['ytd-rich-item-renderer', '.ytd-ad-slot-renderer'],
// ['ytd-rich-section-renderer', '.ytd-statement-banner-renderer'],
// Ad videos on YouTube Shorts.
['ytd-reel-video-renderer', '.ytd-ad-slot-renderer']
// Ad blocker warning dialog.
// ['tp-yt-paper-dialog', '#feedback.ytd-enforcement-message-view-model'],
// Survey dialog on home page, located at bottom right.
// ['tp-yt-paper-dialog', ':scope > ytd-checkbox-survey-renderer'],
// Survey to rate suggested content, located at bottom right.
// ['tp-yt-paper-dialog', ':scope > ytd-single-option-survey-renderer']
]
for (const adSelector of adSelectors) {
const adEl = document.querySelector(adSelector[0])
if (adEl === null) continue
const neededEl = adEl.querySelector(adSelector[1])
if (neededEl === null) continue
adEl.remove()
}
}
const isYouTubeMobile = location.hostname === 'm.youtube.com'
const isYouTubeMusic = location.hostname === 'music.youtube.com'
const isYouTubeDesktop = !isYouTubeMobile && !isYouTubeMusic
const isYouTubeVideo = isYouTubeMobile || isYouTubeDesktop
addCss()
if (isYouTubeVideo) {
window.setInterval(removeAdElements, 1000)
removeAdElements()
}
window.setInterval(skipAd, 500)
skipAd()
// const observer = new MutationObserver(skipAd)
// observer.observe(document.body, {
// 	attributes: true,
// 	attributeFilter: ['class'],
// 	childList: true,
// 	subtree: true
// })