// ==UserScript== // @name Simple YouTube Age Restriction Bypass // @description Watch age-restricted YouTube videos without login or age verification 😎 // @version 2.6.0 // @author Zerody (Optimized by Cody) // @namespace https://github.com/zerodytrash/Simple-YouTube-Age-Restriction-Bypass/ // @supportURL https://github.com/zerodytrash/Simple-YouTube-Age-Restriction-Bypass/issues // @license MIT // @match https://www.youtube.com/* // @match https://www.youtube-nocookie.com/* // @match https://m.youtube.com/* // @match https://music.youtube.com/* // @grant none // @run-at document-start // @compatible chrome // @compatible firefox // @compatible opera // @compatible edge // @compatible safari // @downloadURL none // ==/UserScript== (function () { 'use strict'; // Configuration constants const UNLOCKABLE_PLAYABILITY_STATUSES = ['AGE_VERIFICATION_REQUIRED', 'AGE_CHECK_REQUIRED', 'CONTENT_CHECK_REQUIRED', 'LOGIN_REQUIRED']; const VALID_PLAYABILITY_STATUSES = ['OK', 'LIVE_STREAM_OFFLINE']; const ACCOUNT_PROXY_SERVER = 'https://youtube-proxy.zerody.one'; const VIDEO_PROXY_SERVER = 'https://ny.4everproxy.com'; const ENABLE_UNLOCK_NOTIFICATION = true; const ENABLE_UNLOCK_CONFIRMATION_EMBED = true; const GOOGLE_AUTH_HEADERS = ['Authorization', 'X-Goog-AuthUser', 'X-Origin']; const BLURRED_THUMBNAIL_LENGTHS = [32, 48, 56, 68, 72, 84, 88]; const LOG_PREFIX = '%cYouTube Age Bypass:'; const LOG_STYLE = 'color: white; background-color: #007BFF; padding: 3px;'; const logger = { info: (msg) => console.info(LOG_PREFIX, LOG_STYLE, msg), error: (err, msg) => console.error(LOG_PREFIX, LOG_STYLE, msg, err), }; // Helper to debounce functions const debounce = (fn, delay) => { let timeout; return (...args) => { clearTimeout(timeout); timeout = setTimeout(() => fn.apply(this, args), delay); }; }; // Element observer with timeout function waitForElement(selector, timeout = 5000) { return new Promise((resolve, reject) => { const observer = new MutationObserver((mutations, obs) => { const elem = document.querySelector(selector); if (elem) { obs.disconnect(); resolve(elem); } }); observer.observe(document.body, { childList: true, subtree: true }); setTimeout(() => { observer.disconnect(); reject(new Error('Element not found: ' + selector)); }, timeout); }); } // Check if video is restricted function isAgeRestricted(status) { return UNLOCKABLE_PLAYABILITY_STATUSES.includes(status?.status); } // Deep copy object function deepCopy(obj) { return JSON.parse(JSON.stringify(obj)); } // Unlock video response function unlockResponse(response) { if (isAgeRestricted(response.playabilityStatus)) { logger.info('Unlocking video...'); const unlockedResponse = fetchUnlockedResponse(response.videoDetails.videoId); if (unlockedResponse.errorMessage) { logger.error(null, `Unlock failed: ${unlockedResponse.errorMessage}`); return; } // Replace response content with unlocked data Object.assign(response, unlockedResponse); response.unlocked = true; logger.info('Video unlocked successfully.'); } } // Fetch unlocked video response function fetchUnlockedResponse(videoId) { const payload = { context: { client: { clientName: 'WEB', clientVersion: '2.20220203.04.00', }, }, videoId, racyCheckOk: true, contentCheckOk: true, }; try { const xhr = new XMLHttpRequest(); xhr.open('POST', `${ACCOUNT_PROXY_SERVER}/youtubei/v1/player`, false); xhr.send(JSON.stringify(payload)); return JSON.parse(xhr.responseText); } catch (err) { logger.error(err, 'Failed to fetch unlocked response'); return { errorMessage: 'Unlock failed' }; } } // Hook into JSON.parse to intercept video data const nativeJSONParse = JSON.parse; JSON.parse = function (text) { const data = nativeJSONParse.call(this, text); if (data && data.playabilityStatus) { try { unlockResponse(data); } catch (err) { logger.error(err, 'Error unlocking response'); } } return data; }; // Hook into XMLHttpRequest.open for unlocking const nativeXHROpen = XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open = function (method, url, ...args) { if (url.includes('/youtubei/v1/player')) { this.addEventListener('readystatechange', function () { if (this.readyState === 4 && this.status === 200) { try { const response = JSON.parse(this.responseText); unlockResponse(response); this.responseText = JSON.stringify(response); } catch (err) { logger.error(err, 'Failed to intercept response'); } } }); } nativeXHROpen.call(this, method, url, ...args); }; logger.info('Script initialized. Age restriction bypass enabled.'); })();