The internet is in bad shape. Siloed-off monopolies are continuously implementing arbitrary logic bombs that only inconvenience the people they intend to block, while real customers are sacrificed.

YouTube thinks I might be a bot. As far as I know, I’m not. Now I’m forced to use actual bots to watch YouTube.

YouTube: Sign in to confirm you're not a bot

Bender: If you prick me, do I not bleed?

There are many bots available for grabbing YouTube videos. None of them seem to be blocked.

This one works well. Paste the YouTube URL and select the quality to download.

An example of using a YT downloader like https://yt1ss.pro/ to watch a video.

So what has YouTube accomplished in trying to block bots? Real humans are blocked, savvy users are forced to turn to bots, and bots continue operating as they did before. YouTube has accomplished alienating its users and increasing the bot traffic they were trying to prevent.

But, I have found a better way to deal with this situation. It underscores why spending a bunch of money to develop logic bombs is pointless and only punishes people that don’t know how to work around them.

Embedded YouTube videos have different rules. While I might be considered a bot when I navigate to YouTube.com, I am not considered a bot when viewing embedded videos. Click the “share” button. Choose “embed” and copy the iframe snippet. Insert that iframe into any page and suddenly you’re not a bot anymore. What’s great about this method is I can write an automated script, a bot if you will, to do it for me.

Share via embed

I also noticed that certain videos that are “restricted from playing on this site”, will happily play when embedded in youtube or google sites. Either the video uploader is allowing Google or Google themselves have decided they won’t block themselves. Here is the result of pasting the iframe into google.com using Chrome’s developer tools:

Google.com can play any embedded video

Add the iframe snippet to a yt or google page

As I set out to write a tampermonkey script to automatically replace the blocked video player with an iframe on youtube, I wondered if someone else had already done it. Sure enough, someone had.

I started with this greasyfork.org script authored by JordanRO2. Thank you JordanRO2 for writing the bulk of what I needed. I made a few tweaks so that it would also detect the “You’re a bot” error.

Here is the final script. You can copy/paste this into a new tampermonkey script:

// ==UserScript==
// @name         YouTube iFrame AdBlocker
// @namespace    Booth-Stash
// @license      MIT
// @version      1.0
// @description  Bypass YouTube's ad-blocker detection by dynamically replacing the video player with an iframe.
// @author       JordanRO2
// @match        https://www.youtube.com/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // Utility functions
    function getAutoplayState() {
        return localStorage.getItem('autoplayNext') === 'true';
    }

    function setAutoplayState(state) {
        localStorage.setItem('autoplayNext', state.toString());
    }

    function toggleAutoplayState(button) {
        const autoplayNext = !getAutoplayState();
        setAutoplayState(autoplayNext);
        button.title = autoplayNext ? 'Autoplay is on' : 'Autoplay is off';
        button.setAttribute('aria-label', autoplayNext ? 'Autoplay is on' : 'Autoplay is off');
        button.querySelector('.ytp-autonav-toggle-button').setAttribute('aria-checked', autoplayNext.toString());
        return autoplayNext;
    }

    function isVideoEnded(iframeDoc) {
        return iframeDoc.querySelector('.html5-endscreen.ytp-show-tiles') !== null;
    }

    // Main script
    function replaceElement(oldElement) {
        const urlParams = new URLSearchParams(window.location.search);
        const videoId = urlParams.get('v');

        if (!videoId) {
            console.error('Video ID not found in URL');
            return;
        }

        console.log(`Video ID: ${videoId}`);
        console.log('Old element found');

        const newElement = document.createElement('iframe');
        newElement.width = "100%";
        newElement.height = "100%";
        newElement.src = `https://www.youtube-nocookie.com/embed/${videoId}`;
        newElement.title = "YouTube video player";
        newElement.frameBorder = "0";
        newElement.allow = "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share";
        newElement.allowFullscreen = true;
        newElement.referrerpolicy = 'strict-origin-when-cross-origin';

        oldElement.parentNode.replaceChild(newElement, oldElement);
        console.log('Element replaced successfully');

        newElement.onload = () => {
            const iframeDoc = newElement.contentDocument;

            const refButton = iframeDoc.querySelector('.ytp-subtitles-button');
            const youtubeButton = iframeDoc.querySelector('.ytp-youtube-button');

            if (youtubeButton) {
                youtubeButton.parentNode.removeChild(youtubeButton);
            } else {
                console.error('YouTube button not found');
            }

            if (refButton) {
                const autoPlayButton = document.createElement('button');
                autoPlayButton.className = 'ytp-button';
                autoPlayButton.setAttribute('data-priority', '2');
                autoPlayButton.setAttribute('data-tooltip-target-id', 'ytp-autonav-toggle-button');
                autoPlayButton.title = getAutoplayState() ? 'Autoplay is on' : 'Autoplay is off';
                autoPlayButton.setAttribute('aria-label', getAutoplayState() ? 'Autoplay is on' : 'Autoplay is off');
                autoPlayButton.innerHTML = `
                    <div class="ytp-autonav-toggle-button-container">
                        <div class="ytp-autonav-toggle-button" aria-checked="${getAutoplayState().toString()}"></div>
                    </div>
                `;

                refButton.parentNode.insertBefore(autoPlayButton, refButton.nextSibling);

                autoPlayButton.addEventListener('click', () => {
                    const isAutoplayOn = toggleAutoplayState(autoPlayButton);
                    if (isAutoplayOn && isVideoEnded(iframeDoc)) {
                        playNextVideo();
                    }
                });
            } else {
                console.error('Reference button not found');
            }

            const endScreenObserver = new MutationObserver((mutations) => {
                for (const mutation of mutations) {
                    if (mutation.target.classList.contains('ytp-show-tiles') && getAutoplayState()) {
                        playNextVideo();
                        break;
                    }
                }
            });

            endScreenObserver.observe(iframeDoc, { attributes: true, subtree: true, attributeFilter: ['class'] });
        };
    }

    function playNextVideo() {
        const rendererElements = document.querySelectorAll('ytd-compact-video-renderer');
        for (let rendererElement of rendererElements) {
            if (!rendererElement.querySelector('ytd-compact-radio-renderer')) {
                const nextVideoLink = rendererElement.querySelector('a#thumbnail');
                if (nextVideoLink && nextVideoLink.href) {
                    const autoplayURL = new URL(nextVideoLink.href);
                    autoplayURL.searchParams.set('autoplay', '1');
                    console.log(`Found next video link: ${autoplayURL.href}`);
                    window.location.href = autoplayURL.href;
                    return;
                }
            }
        }
        console.error('Next video link not found');
    }

    const observer = new MutationObserver((mutationsList) => {
        for (let mutation of mutationsList) {
            if (mutation.addedNodes.length) {
                for (let node of mutation.addedNodes) {
                    const nodeName = node.nodeName.toLowerCase();
                    if (nodeName === 'ytd-enforcement-message-view-model' || nodeName === 'yt-player-error-message-renderer') {
                        replaceElement(node);
                    }
                }
            }
        }
    });

    observer.observe(document, { childList: true, subtree: true });

})();

The final result is browsing youtube.com works normally. If/when youtube displays an error about playing a video, it is immediately replaced with an iframe that doesn’t have those superficial restrictions. It is seamless. It is unfair of YouTube to treat their users like this. Their logic bomb does not work. It blocks people it shouldn’t and is easily bypassed. All it does is punish people following the rules.

When will companies learn? YouTube should go ask Yahoo what happens when you start accusing your customer base of being robots.