Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save tkhorik/0042837583ef675b3d217a317f78c220 to your computer and use it in GitHub Desktop.

Select an option

Save tkhorik/0042837583ef675b3d217a317f78c220 to your computer and use it in GitHub Desktop.
Tampermonkey script preventing autoplay in YouTube on Chrome
// ==UserScript==
// @name YouTube — disable autoplay until I press Play
// @namespace local.dmitry.youtube.autoplay.block
// @version 2.0.0
// @description Prevent YouTube videos from auto-playing on open; only play after a recent user gesture.
// @author you
// @match https://www.youtube.com/*
// @run-at document-start
// @grant none
// ==/UserScript==
(function () {
'use strict';
// Allow play only if there was a user gesture in the last N ms
const GESTURE_WINDOW_MS = 600;
let lastGestureTs = 0;
// Count clicks/taps/keyboard as gestures
const markGesture = () => { lastGestureTs = Date.now(); };
window.addEventListener('pointerdown', markGesture, true);
window.addEventListener('keydown', markGesture, true);
// Helper: pause if the play wasn't user-initiated
function guardPlay(ev) {
const v = ev.target;
if (!(v instanceof HTMLVideoElement)) return;
const recentGesture = (Date.now() - lastGestureTs) <= GESTURE_WINDOW_MS;
// If no recent gesture, immediately pause (blocks autoplay)
if (!recentGesture) {
// Prevent “play” from continuing
try { v.pause(); } catch {}
// Mark as not playing
v.__blockedOnce = true;
}
}
// On first attachment and on SPA navigations, ensure listeners exist and pause if already playing
function attachToAllVideos() {
document.querySelectorAll('video').forEach(v => {
if (v.__autoplayGuardAttached) return;
v.__autoplayGuardAttached = true;
// If YouTube already started it, stop it right away
try {
if (!v.paused) v.pause();
} catch {}
// Listen in capture so we run before player handlers
v.addEventListener('play', guardPlay, true);
});
}
// Observe DOM for new video elements (YouTube swaps them frequently)
const mo = new MutationObserver(() => attachToAllVideos());
mo.observe(document.documentElement, { childList: true, subtree: true });
// Handle YouTube SPA events (navigations without full reload)
window.addEventListener('yt-navigate-finish', () => {
// Reset gesture; a new page shouldn’t auto-play
lastGestureTs = 0;
attachToAllVideos();
// If a video element already exists, pause it once more
const v = document.querySelector('video');
if (v) { try { v.pause(); } catch {} }
});
// First pass (for hard reloads or when run-at is late)
attachToAllVideos();
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment