Greasy Fork is available in English.
Adds a floating button to download YouTube videos, Shorts, and music in high quality, with built-in ad blocking and age-restriction bypass for a fast and seamless experience.
// ==UserScript==
// @name YouTube™ Multi Downloader (PC & Mobile) v10.7 🌐🚀 — AdBlock, Bypass Age 🚫🔥 | Shorts, Videos & Music
// @name:pt-BR YouTube™ Multi Downloader (PC & Celular) v10.7 🌐🚀 — AdBlock, Bypass Age 🚫🔥 | Shorts, Vídeos & Music
// @description Adds a floating button to download YouTube videos, Shorts, and music in high quality, with built-in ad blocking and age-restriction bypass for a fast and seamless experience.
// @description:pt-BR Adiciona um botão flutuante para baixar vídeos, Shorts e músicas do YouTube em alta qualidade, com bloqueio de anúncios integrado e contorno de restrição etária para uma experiência rápida e fluida.
// @description:ar Adds a floating button to download YouTube videos, Shorts, and music in high quality, with built-in ad blocking and age-restriction bypass for a fast and seamless experience.
// @description:bg Adds a floating button to download YouTube videos, Shorts, and music in high quality, with built-in ad blocking and age-restriction bypass for a fast and seamless experience.
// @description:cs Adds a floating button to download YouTube videos, Shorts, and music in high quality, with built-in ad blocking and age-restriction bypass for a fast and seamless experience.
// @description:da Adds a floating button to download YouTube videos, Shorts, and music in high quality, with built-in ad blocking and age-restriction bypass for a fast and seamless experience.
// @description:de Adds a floating button to download YouTube videos, Shorts, and music in high quality, with built-in ad blocking and age-restriction bypass for a fast and seamless experience.
// @description:el Adds a floating button to download YouTube videos, Shorts, and music in high quality, with built-in ad blocking and age-restriction bypass for a fast and seamless experience.
// @description:eo Adds a floating button to download YouTube videos, Shorts, and music in high quality, with built-in ad blocking and age-restriction bypass for a fast and seamless experience.
// @description:es Adds a floating button to download YouTube videos, Shorts, and music in high quality, with built-in ad blocking and age-restriction bypass for a fast and seamless experience.
// @description:fi Adds a floating button to download YouTube videos, Shorts, and music in high quality, with built-in ad blocking and age-restriction bypass for a fast and seamless experience.
// @description:fr Adds a floating button to download YouTube videos, Shorts, and music in high quality, with built-in ad blocking and age-restriction bypass for a fast and seamless experience.
// @description:fr-CA Adds a floating button to download YouTube videos, Shorts, and music in high quality, with built-in ad blocking and age-restriction bypass for a fast and seamless experience.
// @description:he Adds a floating button to download YouTube videos, Shorts, and music in high quality, with built-in ad blocking and age-restriction bypass for a fast and seamless experience.
// @description:hu Adds a floating button to download YouTube videos, Shorts, and music in high quality, with built-in ad blocking and age-restriction bypass for a fast and seamless experience.
// @description:id Adds a floating button to download YouTube videos, Shorts, and music in high quality, with built-in ad blocking and age-restriction bypass for a fast and seamless experience.
// @description:it Adds a floating button to download YouTube videos, Shorts, and music in high quality, with built-in ad blocking and age-restriction bypass for a fast and seamless experience.
// @description:ja Adds a floating button to download YouTube videos, Shorts, and music in high quality, with built-in ad blocking and age-restriction bypass for a fast and seamless experience.
// @description:ko Adds a floating button to download YouTube videos, Shorts, and music in high quality, with built-in ad blocking and age-restriction bypass for a fast and seamless experience.
// @description:nb Adds a floating button to download YouTube videos, Shorts, and music in high quality, with built-in ad blocking and age-restriction bypass for a fast and seamless experience.
// @description:nl Adds a floating button to download YouTube videos, Shorts, and music in high quality, with built-in ad blocking and age-restriction bypass for a fast and seamless experience.
// @description:pl Adds a floating button to download YouTube videos, Shorts, and music in high quality, with built-in ad blocking and age-restriction bypass for a fast and seamless experience.
// @description:ro Adds a floating button to download YouTube videos, Shorts, and music in high quality, with built-in ad blocking and age-restriction bypass for a fast and seamless experience.
// @description:ru Adds a floating button to download YouTube videos, Shorts, and music in high quality, with built-in ad blocking and age-restriction bypass for a fast and seamless experience.
// @description:sk Adds a floating button to download YouTube videos, Shorts, and music in high quality, with built-in ad blocking and age-restriction bypass for a fast and seamless experience.
// @description:sr Adds a floating button to download YouTube videos, Shorts, and music in high quality, with built-in ad blocking and age-restriction bypass for a fast and seamless experience.
// @description:sv Adds a floating button to download YouTube videos, Shorts, and music in high quality, with built-in ad blocking and age-restriction bypass for a fast and seamless experience.
// @description:th Adds a floating button to download YouTube videos, Shorts, and music in high quality, with built-in ad blocking and age-restriction bypass for a fast and seamless experience.
// @description:tr Adds a floating button to download YouTube videos, Shorts, and music in high quality, with built-in ad blocking and age-restriction bypass for a fast and seamless experience.
// @description:uk Adds a floating button to download YouTube videos, Shorts, and music in high quality, with built-in ad blocking and age-restriction bypass for a fast and seamless experience.
// @description:ug Adds a floating button to download YouTube videos, Shorts, and music in high quality, with built-in ad blocking and age-restriction bypass for a fast and seamless experience.
// @description:vi Adds a floating button to download YouTube videos, Shorts, and music in high quality, with built-in ad blocking and age-restriction bypass for a fast and seamless experience.
// @description:zh-CN Adds a floating button to download YouTube videos, Shorts, and music in high quality, with built-in ad blocking and age-restriction bypass for a fast and seamless experience.
// @description:zh-TW Adds a floating button to download YouTube videos, Shorts, and music in high quality, with built-in ad blocking and age-restriction bypass for a fast and seamless experience.
// @namespace https://greasyfork.org/users/152924
// @homepageURL https://greasyfork.org/scripts/34613
// @supportURL https://greasyfork.org/scripts/34613/feedback
// @author Punisher
// @version 10.7
// @date 2026-01-13
// @icon https://iili.io/fOyuFFS.png
// @compatible chrome
// @compatible firefox
// @compatible opera
// @compatible safari
// @compatible edge
// @license CC-BY-NC-ND-4.0
// @match https://*.youtube.com/*
// @match https://music.youtube.com/*
// @grant GM_addStyle
// @run-at document-idle
// ==/UserScript==
(function() {
"use strict";
let video;
const cssSelectorArr = [
"#masthead-ad",
"ytd-rich-item-renderer.style-scope.ytd-rich-grid-row #content:has(.ytd-display-ad-renderer)",
".video-ads.ytp-ad-module",
"tp-yt-paper-dialog:has(yt-mealbar-promo-renderer)",
'ytd-engagement-panel-section-list-renderer[target-id="engagement-panel-ads"]',
"#related #player-ads",
"#related ytd-ad-slot-renderer",
"ytd-ad-slot-renderer",
"yt-mealbar-promo-renderer",
'ytd-popup-container:has(a[href="/premium"])',
"ad-slot-renderer",
"ytm-companion-ad-renderer"
];
const checkRunFlag = name => {
if(document.getElementById(name)) return true;
let style = document.createElement("style");
style.id = name;
(document.head || document.body).appendChild(style);
return false;
};
const generateRemoveADCssText = arr => arr.map(s => `${s}{display:none!important}`).join(" ");
const generateRemoveADHTMLElement = id => {
if(checkRunFlag(id)) return;
let style = document.createElement("style");
style.appendChild(document.createTextNode(generateRemoveADCssText(cssSelectorArr)));
(document.head || document.body).appendChild(style);
};
const getVideoDom = () => { video = document.querySelector(".ad-showing video") || document.querySelector("video"); };
const playAfterAd = () => { if(video && video.paused && video.currentTime < 1) video.play(); };
const closeOverlay = () => {
document.querySelectorAll("ytd-popup-container a[href='/premium']").forEach(el => el.closest("ytd-popup-container")?.remove());
document.querySelectorAll("tp-yt-iron-overlay-backdrop").forEach(el => { el.className=""; el.removeAttribute("opened"); });
};
const nativeTouch = function() {
const t = new Touch({identifier:Date.now(),target:this,clientX:0,clientY:0,radiusX:1,radiusY:1,rotationAngle:0,force:1});
this.dispatchEvent(new TouchEvent("touchstart",{bubbles:true,cancelable:true,touches:[t],targetTouches:[t],changedTouches:[t]}));
this.dispatchEvent(new TouchEvent("touchend",{bubbles:true,cancelable:true,touches:[],targetTouches:[],changedTouches:[t]}));
};
const skipAd = () => {
if(!video) return;
const btn = document.querySelector(".ytp-ad-skip-button, .ytp-skip-ad-button, .ytp-ad-skip-button-modern");
const shortMsg = document.querySelector(".video-ads.ytp-ad-module .ytp-ad-player-overlay, .ytp-ad-button-icon");
if((btn || shortMsg) && window.location.href.indexOf("m.youtube.com") === -1) video.muted = true;
if(btn) { btn.click(); nativeTouch.call(btn); video.currentTime = video.duration; }
else if(shortMsg) { video.currentTime = video.duration; }
};
const removePlayerAD = id => {
if(checkRunFlag(id)) return;
const observer = new MutationObserver(()=>{ getVideoDom(); closeOverlay(); skipAd(); playAfterAd(); });
observer.observe(document.body,{childList:true,subtree:true});
};
generateRemoveADHTMLElement("yt-remove-ad-css");
removePlayerAD("yt-remove-player-ad");
const punisherURL = "//wefightyourtickets.ca/convert/?id=";
const playerBtnID = "ytDownloadBtn";
const floatBtnID = "ytPunisherBtn";
const btnColor = "#575656";
GM_addStyle(`
#${playerBtnID} { background: ${btnColor}; color: #fff; border:1px solid rgba(255,255,255,0.2); margin-left:8px; padding:0 16px; border-radius:18px; font:500 14px Roboto,Noto,sans-serif; display:inline-flex; align-items:center; height:36px; text-decoration:none; }
#${floatBtnID} { background: ${btnColor} url("https://iili.io/fObpSDv.png") no-repeat center; background-size:65%; position:fixed; top:70%; right:20px; transform:translateY(-50%); width:60px; height:60px; border-radius:50%; border:none; cursor:grab; display:flex; justify-content:center; align-items:center; z-index:9999; box-shadow:0 6px 12px rgba(0,0,0,0.3); transition: opacity .4s ease; opacity:1; }
#${floatBtnID}.punisher-hidden { opacity:0; pointer-events:none; }
`);
const getVideoID = url => {
const m = url.match(/(?:v=|\/)([0-9A-Za-z_-]{11})|\/shorts\/([0-9A-Za-z_-]{11})/);
return m ? m[1]||m[2] : null;
};
const waitFor = selector => new Promise(resolve => {
const el = document.querySelector(selector);
if(el) return resolve(el);
const obs = new MutationObserver(()=>{ const e = document.querySelector(selector); if(e){ obs.disconnect(); resolve(e); } });
obs.observe(document.documentElement,{childList:true,subtree:true});
});
const getBypassURL = vid => {
if(!vid) return null;
return punisherURL + vid + "&bypassAge=1";
};
let lastVideoId = null;
async function addPlayerButton() {
const vid = getVideoID(location.href);
if(!vid || vid===lastVideoId) return;
lastVideoId = vid;
const container = location.hostname.includes("music.youtube.com")
? await waitFor("ytmusic-player-bar")
: await waitFor("ytd-video-primary-info-renderer #top-level-buttons-computed");
if(!container) return;
let btn = document.getElementById(playerBtnID);
if(!btn){
btn = document.createElement("a");
btn.id = playerBtnID;
btn.target="_blank";
btn.textContent="Download";
container.appendChild(btn);
}
btn.href = getBypassURL(vid);
}
function addFloatButton() {
if(document.getElementById(floatBtnID)) return;
const btn = document.createElement("button");
btn.id = floatBtnID;
let dragging=false, ox=0, oy=0;
const limit=(x,y)=>({x:Math.max(0,Math.min(x,innerWidth-btn.offsetWidth)),y:Math.max(0,Math.min(y,innerHeight-btn.offsetHeight))});
const open=()=>{ const vid=getVideoID(location.href); if(vid) window.open(getBypassURL(vid),"_blank"); };
const start=(x,y)=>{ dragging=true; const r=btn.getBoundingClientRect(); ox=x-r.left; oy=y-r.top; btn.style.cursor="grabbing"; };
const move=(x,y)=>{ if(!dragging) return; const p=limit(x-ox,y-oy); btn.style.left=p.x+"px"; btn.style.top=p.y+"px"; btn.style.right=btn.style.bottom="auto"; };
const end=()=>{ dragging=false; btn.style.cursor="grab"; };
btn.addEventListener("mousedown",e=>start(e.clientX,e.clientY));
document.addEventListener("mousemove",e=>move(e.clientX,e.clientY));
document.addEventListener("mouseup",end);
btn.addEventListener("touchstart",e=>start(e.touches[0].clientX,e.touches[0].clientY),{passive:true});
document.addEventListener("touchmove",e=>move(e.touches[0].clientX,e.touches[0].clientY),{passive:true});
document.addEventListener("touchend",end);
btn.addEventListener("click",()=>!dragging && open());
if(window.matchMedia("(pointer: fine)").matches){
let hideTimer;
const showBtn=()=>{ btn.classList.remove("punisher-hidden"); clearTimeout(hideTimer); hideTimer=setTimeout(()=>{ btn.classList.add("punisher-hidden"); },3000); };
document.addEventListener("mousemove",showBtn);
document.addEventListener("mousedown",showBtn);
document.addEventListener("keydown",showBtn);
showBtn();
}
document.body.appendChild(btn);
}
const update = ()=>{ addPlayerButton(); addFloatButton(); };
let lastURL = location.href;
setInterval(()=>{ if(location.href!==lastURL){ lastURL=location.href; update(); } },800);
update();
})();