Bypasses YouTube content warning on possibly unsafe content.
// ==UserScript==
// @name YTCWBypass
// @namespace http://tampermonkey.net/
// @version 3.0
// @description Bypasses YouTube content warning on possibly unsafe content.
// @author Dormy
// @match *://www.youtube.com/*
// @icon https://www.google.com/s2/favicons?domain=youtube.com
// @license MIT
// @grant GM_getValue
// @grant GM_setValue
// @grant unsafeWindow
// ==/UserScript==
(async function() {
'use strict';
const SKIPPER_STATE_KEY = 'yt-bypass-enabled-state';
const TOGGLE_BUTTON_ID = 'yt-bypass-toggle-button';
let isBypassEnabled = true;
function performMultiProngedClick(element) {
try {
element.focus();
element.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true }));
} catch (e) { /* Silently fail */ }
try { element.click(); } catch (e) { /* Silently fail */ }
try {
const eventInit = { bubbles: true, cancelable: true, view: unsafeWindow };
element.dispatchEvent(new MouseEvent('mousedown', eventInit));
element.dispatchEvent(new MouseEvent('mouseup', eventInit));
element.dispatchEvent(new MouseEvent('click', eventInit));
} catch (e) { /* Silently fail */ }
}
/**
* Finds and clicks the warning button if it's visible.
* @returns {boolean} - True if the button was found and clicked, otherwise false.
*/
function findAndClickWarningButton() {
const buttonIdentifiers = ["I understand and wish to proceed", "Continue"];
for (const text of buttonIdentifiers) {
const xpath = `(//button | //*[@role="button"] | //yt-button-shape | //yt-button-renderer)[contains(., "${text}") or @aria-label="${text}"]`;
const result = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
const container = result.singleNodeValue;
if (container && container.offsetParent !== null) {
const elementToClick = container.querySelector('button') || container;
performMultiProngedClick(elementToClick);
return true; // Success
}
}
return false; // Not found
}
/**
* Starts a polling process that checks for the warning button every 500ms for 15 seconds.
*/
function attemptBypassWithPolling() {
if (!isBypassEnabled) return;
const intervalId = setInterval(() => {
if (findAndClickWarningButton()) {
clearInterval(intervalId); // Stop polling on success
}
}, 500); // Check every half-second
setTimeout(() => {
clearInterval(intervalId); // Stop polling after 15 seconds
}, 15000);
}
function updateButtonAppearance() {
const button = document.getElementById(TOGGLE_BUTTON_ID);
if (!button) return;
const textElement = button.querySelector('.ytcwb-text');
if (textElement) {
textElement.style.color = isBypassEnabled ? '#2ecc71' : '#e74c3c';
}
}
async function toggleBypassState() {
isBypassEnabled = !isBypassEnabled;
await GM_setValue(SKIPPER_STATE_KEY, isBypassEnabled);
updateButtonAppearance();
// --- NEW: Trigger the bypass action immediately when toggled on ---
if (isBypassEnabled) {
attemptBypassWithPolling();
}
}
function injectHeaderButton() {
if (document.getElementById(TOGGLE_BUTTON_ID)) return;
const buttonsContainer = document.querySelector('ytd-masthead #end #buttons');
if (!buttonsContainer) return;
const buttonWrapper = document.createElement('div');
buttonWrapper.id = TOGGLE_BUTTON_ID;
buttonWrapper.style.marginRight = '15px';
const buttonEl = document.createElement('button');
Object.assign(buttonEl.style, {
width: '36px', height: '36px', borderRadius: '50%', border: 'none', padding: '0',
backgroundColor: '#212121', display: 'flex', alignItems: 'center',
justifyContent: 'center', cursor: 'pointer'
});
buttonEl.onmouseover = () => buttonEl.style.backgroundColor = '#3d3d3d';
buttonEl.onmouseout = () => buttonEl.style.backgroundColor = '#212121';
const textElement = document.createElement('div');
textElement.textContent = 'YTCW';
textElement.className = 'ytcwb-text';
Object.assign(textElement.style, {
fontFamily: 'Roboto, Arial, sans-serif', fontSize: '11px', fontWeight: 'bold',
lineHeight: 'normal', pointerEvents: 'none'
});
buttonEl.appendChild(textElement);
buttonWrapper.appendChild(buttonEl);
buttonEl.setAttribute('aria-label', 'Toggle YTCWBypass');
buttonEl.addEventListener('click', toggleBypassState);
buttonsContainer.insertBefore(buttonWrapper, buttonsContainer.firstChild);
updateButtonAppearance();
}
async function initialize() {
isBypassEnabled = await GM_getValue(SKIPPER_STATE_KEY, true);
// --- NEW: Start the initial bypass attempt on page load ---
attemptBypassWithPolling();
// The observer is now ONLY for injecting the button when the header changes
const uiObserver = new MutationObserver(() => injectHeaderButton());
uiObserver.observe(document.body, { childList: true, subtree: true });
}
initialize();
})();