Skip to content

Instantly share code, notes, and snippets.

@SanteriHetekivi
Last active March 28, 2025 17:25
Show Gist options
  • Save SanteriHetekivi/146a3340343e05d6b3f35699103965a9 to your computer and use it in GitHub Desktop.
Save SanteriHetekivi/146a3340343e05d6b3f35699103965a9 to your computer and use it in GitHub Desktop.
Automatically plays the next YouTube short.
// ==UserScript==
// @name YouTube Shorts Auto Next
// @description Automatically plays the next YouTube short.
// @version 2024-03-02
// @author Santeri Hetekivi
// @match https://www.youtube.com/shorts/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=youtube.com
// @grant none
// @license Apache-2.0
// ==/UserScript==
(function () {
'use strict';
/**
* Get video element.
* @returns {HTMLVideoElement} The video element.
*/
function getVideo() {
// Get all video elements with src attribute.
const videos = document.querySelectorAll("video[src]")
// Get elements length.
const videosLength = videos.length
// If there is only one video element
if (videosLength === 1) {
// init get video timeout counter.
getVideo.timeoutCounter = 0
const video = videos[0]
if (!(video instanceof HTMLVideoElement)) {
throw new Error("Video is not a HTMLVideoElement!")
}
return video
}
// Else if no video elements found
else if (videosLength === 0) {
// Set timeout for getting video.
getVideo.timeout = setTimeout(
function () {
// Clear timeout.
clearTimeout(getVideo.timeout)
getVideo.timeout = null
return getVideo()
},
// Timeout time is 1000ms * times this has been called..
1000 * (++getVideo.timeoutCounter)
);
}
// Else if there are more than one video elements, throw error.
else {
throw new Error("Found " + videosLength + " video elements with src attribute!")
}
}
// Get and initialise video element.
const video = getVideo()
/**
* Init video element.
*/
function initVideo() {
// Set autoplay to false.
video.autoplay = false
// Set loop to false.
video.loop = false
}
// Init video.
initVideo()
// Add event listener for ended event.
video.addEventListener(
"ended",
function () {
// Get next button.
const button = document.querySelector("#navigation-button-down button")
if (!(button instanceof HTMLButtonElement)) {
throw new Error("No next button found!")
}
// Click the next button.
button.click()
}
)
// Add event listener for progress event.
video.addEventListener(
"progress",
function () {
// Init video again, because Youtube resets video element.
initVideo()
}
)
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment