// ==UserScript==
// @name bypass per i limiti di età di YouTube
// @namespace https://greasyfork.org/users/237458
// @version 0.5
// @description Visualizza i video soggetti a limiti di età su YouTube senza verifica e accesso
// @author figuccio
// @match https://www.youtube.com/*
// @grant none
// @run-at document-start
// @icon https://www.youtube.com/s/desktop/3748dff5/img/favicon_48.png
// @license MIT
// ==/UserScript==
(function () {
var nativeParse = window.JSON.parse;
var nativeDefineProperty = getNativeDefineProperty();
var nativeXmlHttpOpen = XMLHttpRequest.prototype.open;
var wrappedPlayerResponse = null;
var unlockablePlayerStates = ["AGE_VERIFICATION_REQUIRED", "LOGIN_REQUIRED", "UNPLAYABLE"];
var playerResponsePropertyAliases = ["ytInitialPlayerResponse", "playerResponse"];
var lastProxiedGoogleVideoUrlParams = null;
var responseCache = {};
var innertubeApiKey = "AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8";
var innertubeClientVersion = "2.20210721.00.00";
var accountProxyServerHost = "https://youtube-proxy.zerody.one";
var videoProxyServerHost = "https://phx.4everproxy.com";
var initialPlayerResponseDescriptor = window.Object.getOwnPropertyDescriptor(window, "ytInitialPlayerResponse");
var chainedSetter = initialPlayerResponseDescriptor ? initialPlayerResponseDescriptor.set : null;
var chainedGetter = initialPlayerResponseDescriptor ? initialPlayerResponseDescriptor.get : null;
window.Object.defineProperty = function (obj, prop, descriptor) {
if (obj === window && playerResponsePropertyAliases.includes(prop)) {
console.info("Another extension tries to re-define '" + prop + "' (probably an AdBlock extension). Chain it...");
if (descriptor && descriptor.set) chainedSetter = descriptor.set;
if (descriptor && descriptor.get) chainedGetter = descriptor.get;
} else {
nativeDefineProperty(obj, prop, descriptor);
}
}
nativeDefineProperty(window, "ytInitialPlayerResponse", {
set: function (playerResponse) {
if (playerResponse === wrappedPlayerResponse) return;
wrappedPlayerResponse = inspectJsonData(playerResponse);
if (typeof chainedSetter === "function") chainedSetter(wrappedPlayerResponse);
},
get: function () {
if (typeof chainedGetter === "function") try { return chainedGetter() } catch (err) { };
return wrappedPlayerResponse || {};
},
configurable: true
});
XMLHttpRequest.prototype.open = function () {
if (arguments.length > 1 && typeof arguments[1] === "string" && arguments[1].indexOf("https://") === 0) {
var method = arguments[0];
var url = new URL(arguments[1]);
var urlParams = new URLSearchParams(url.search);
function isGoogleVideo() {
return method === "GET" && url.host.indexOf(".googlevideo.com") > 0;
}
function hasGcrFlag() {
return urlParams.get("gcr") !== null;
}
function isUnlockedByAccountProxy() {
return urlParams.get("id") !== null && lastProxiedGoogleVideoUrlParams && urlParams.get("id") === lastProxiedGoogleVideoUrlParams.get("id");
}
if (videoProxyServerHost && isGoogleVideo() && hasGcrFlag() && isUnlockedByAccountProxy()) {
arguments[1] = videoProxyServerHost + "/direct/" + btoa(arguments[1]);
nativeDefineProperty(this, "withCredentials", {
set: function () { },
get: function () {
return false;
}
});
}
}
return nativeXmlHttpOpen.apply(this, arguments);
}
window.JSON.parse = function (text, reviver) {
return inspectJsonData(nativeParse(text, reviver));
}
function inspectJsonData(parsedData) {
try {
if (Array.isArray(parsedData)) {
var playerResponseArrayItem = parsedData.find(e => typeof e.playerResponse === "object");
var playerResponse = playerResponseArrayItem ? playerResponseArrayItem.playerResponse : null;
if (playerResponse && isUnlockable(playerResponse.playabilityStatus)) {
playerResponseArrayItem.playerResponse = unlockPlayerResponse(playerResponse);
}
}
if (parsedData.playerResponse && parsedData.playerResponse.playabilityStatus && parsedData.playerResponse.videoDetails && isUnlockable(parsedData.playerResponse.playabilityStatus)) {
parsedData.playerResponse = unlockPlayerResponse(parsedData.playerResponse);
}
if (parsedData.playabilityStatus && parsedData.videoDetails && isUnlockable(parsedData.playabilityStatus)) {
parsedData = unlockPlayerResponse(parsedData);
}
} catch (err) {
console.error("Simple-YouTube-Age-Restriction-Bypass-Error:", err);
}
return parsedData;
}
function isUnlockable(playabilityStatus) {
if (!playabilityStatus || !playabilityStatus.status) return false;
return unlockablePlayerStates.includes(playabilityStatus.status);
}
function unlockPlayerResponse(playerResponse) {
var videoId = playerResponse.videoDetails.videoId;
var reason = playerResponse.playabilityStatus?.status;
var unlockedPayerResponse = getUnlockedPlayerResponse(videoId, reason);
if (unlockedPayerResponse.errorMessage)
throw ("Simple-YouTube-Age-Restriction-Bypass: Unlock Failed, errorMessage:" + unlockedPayerResponse.errorMessage + "; innertubeApiKey:" + innertubeApiKey + "; innertubeClientVersion:" + innertubeClientVersion);
if (unlockedPayerResponse.playabilityStatus?.status !== "OK")
throw ("Simple-YouTube-Age-Restriction-Bypass: Unlock Failed, playabilityStatus:" + unlockedPayerResponse.playabilityStatus?.status + "; innertubeApiKey:" + innertubeApiKey + "; innertubeClientVersion:" + innertubeClientVersion);
if (unlockedPayerResponse.proxied && unlockedPayerResponse.streamingData?.adaptiveFormats) {
var videoUrl = unlockedPayerResponse.streamingData.adaptiveFormats.find(x => x.url)?.url;
var cipherText = unlockedPayerResponse.streamingData.adaptiveFormats.find(x => x.signatureCipher)?.signatureCipher;
if (cipherText) videoUrl = new URLSearchParams(cipherText).get("url");
lastProxiedGoogleVideoUrlParams = videoUrl ? new URLSearchParams(new URL(videoUrl).search) : null;
}
return unlockedPayerResponse;
}
function getUnlockedPlayerResponse(videoId, reason) {
if (responseCache.videoId === videoId) return responseCache.content;
setInnertubeConfigFromYtcfg();
var playerResponse = null;
function useInnertubeEmbed() {
console.info("Simple-YouTube-Age-Restriction-Bypass: Trying Unlock Method #1 (Innertube Embed)");
var payload = getInnertubeEmbedPlayerPayload(videoId);
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("POST", "/youtubei/v1/player?key=" + innertubeApiKey, false); // Synchronous!!!
xmlhttp.send(JSON.stringify(payload));
playerResponse = nativeParse(xmlhttp.responseText);
}
function useProxy() {
console.info("Simple-YouTube-Age-Restriction-Bypass: Trying Unlock Method #2 (Account Proxy)");
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", accountProxyServerHost + "/getPlayer?videoId=" + encodeURIComponent(videoId) + "&reason=" + encodeURIComponent(reason) + "&clientVersion=" + innertubeClientVersion, false); // Synchronous!!!
xmlhttp.send(null);
playerResponse = nativeParse(xmlhttp.responseText);
playerResponse.proxied = true;
}
if (playerResponse?.playabilityStatus?.status !== "OK") useInnertubeEmbed();
if (playerResponse?.playabilityStatus?.status !== "OK") useProxy();
responseCache = { videoId: videoId, content: playerResponse };
setTimeout(function () { responseCache = {} }, 10000);
return playerResponse;
}
function getInnertubeEmbedPlayerPayload(videoId) {
return {
"context": {
"client": {
"clientName": "WEB",
"clientVersion": innertubeClientVersion,
"clientScreen": "EMBED"
},
"thirdParty": {
"embedUrl": "https://www.youtube.com/"
}
},
"playbackContext": {
"contentPlaybackContext": {
"signatureTimestamp": 18830
}
},
"videoId": videoId
}
}
function setInnertubeConfigFromYtcfg() {
if (ytcfg?.data_?.INNERTUBE_API_KEY) innertubeApiKey = ytcfg.data_.INNERTUBE_API_KEY;
if (ytcfg?.data_?.INNERTUBE_CLIENT_VERSION) innertubeClientVersion = ytcfg.data_.INNERTUBE_CLIENT_VERSION;
}
function getNativeDefineProperty() {
if (window.Object.defineProperty && window.Object.defineProperty.toString().indexOf("[native code]") > -1) {
return window.Object.defineProperty;
}
try {
if (!document.body) document.body = document.createElement("body");
var tempFrame = document.createElement("iframe");
tempFrame.style.display = "none";
document.body.insertAdjacentElement("beforeend", tempFrame);
var nativeDefineProperty = tempFrame.contentWindow.Object.defineProperty;
tempFrame.remove();
console.info("Simple-YouTube-Age-Restriction-Bypass: Overidden Object.defineProperty function successfully restored!");
return nativeDefineProperty;
} catch (err) {
console.warn("Simple-YouTube-Age-Restriction-Bypass: Unable to restore the original Object.defineProperty function", err);
return window.Object.defineProperty;
}
}
})();