Skip to content

Instantly share code, notes, and snippets.

@jkluch
Last active October 28, 2025 07:43
Show Gist options
  • Select an option

  • Save jkluch/c26d4cd76d07f4b47850cb4525ac5917 to your computer and use it in GitHub Desktop.

Select an option

Save jkluch/c26d4cd76d07f4b47850cb4525ac5917 to your computer and use it in GitHub Desktop.
Easily control Instagram video behavior: auto-unmute, fullscreen on load or 'f', auto-play on maximize, start paused on load. Features are configurable via a simple settings panel (open "Instagram Video Settings" from Tampermonkey's menu).

Instagram Video Tools Userscript

Features

  • Auto-unmute videos: Videos are automatically unmuted on page load and when new ones appear.
  • Start videos paused on page load: Optionally, videos start paused when you first load Instagram.
  • Fullscreen video on load: Optionally, the largest video is maximized to fullscreen on page load.
  • Fullscreen with 'f' key: Press 'f' to toggle fullscreen for the largest visible video.
  • Auto-play on maximize: Optionally, videos automatically play when maximized to fullscreen.
  • Easy configuration UI: Easily toggle features using a built-in settings panel.

Installation

To install, simply open the raw script URL in your browser:

https://gist.github.com/jkluch/c26d4cd76d07f4b47850cb4525ac5917/raw/instagram-video-tools.user.js

If you have a userscript extension like Tampermonkey or Violentmonkey installed, you will be prompted to add or update the script automatically.

Configuration

After installation:

  • Click the Tampermonkey (or Violentmonkey) extension icon in your browser.
  • Find and click the menu item "Instagram Video Settings".
  • A configuration panel will appear over the Instagram page.
    Use the checkboxes to enable/disable features as you like.
  • Click Save to apply changes (the page will reload).

Author

jkluch

License

MIT

// ==UserScript==
// @name Instagram Video Tools
// @namespace https://github.com/jkluch
// @version 1.0.0
// @description Easily control Instagram video behavior: auto-unmute, fullscreen on load or 'f', auto-play on maximize, start paused on load. Features are configurable via a simple settings panel (open "Instagram Video Settings" from Tampermonkey's menu).
// @author jkluch
// @license MIT
// @match https://www.instagram.com/*
// @updateURL https://gist.github.com/jkluch/c26d4cd76d07f4b47850cb4525ac5917/raw/instagram-video-tools.user.js
// @downloadURL https://gist.github.com/jkluch/c26d4cd76d07f4b47850cb4525ac5917/raw/instagram-video-tools.user.js
// @grant GM_registerMenuCommand
// @grant GM_getValue
// @grant GM_setValue
// ==/UserScript==
/* --- Embedded configuration UI --- */
var GM_config = {
init: function(settings) {
this.settings = settings;
this.values = {};
for (var k in settings) {
this.values[k] = typeof settings[k].default === "undefined" ? false : settings[k].default;
}
Object.keys(settings).forEach(async (k) => {
const v = await GM_getValue(k);
if (typeof v !== "undefined") this.values[k] = v;
});
},
open: function() {
const oldPanel = document.getElementById("gm_config_panel");
if (oldPanel) oldPanel.remove();
var wrapper = document.createElement("div");
wrapper.id = "gm_config_panel";
wrapper.style.position = "fixed";
wrapper.style.top = "10%";
wrapper.style.left = "50%";
wrapper.style.transform = "translateX(-50%)";
wrapper.style.background = "#222";
wrapper.style.color = "#fff";
wrapper.style.padding = "30px 40px";
wrapper.style.borderRadius = "10px";
wrapper.style.boxShadow = "0 0 40px rgba(0,0,0,0.7)";
wrapper.style.zIndex = "2147483648";
wrapper.style.fontFamily = "sans-serif";
wrapper.style.textAlign = "left";
wrapper.innerHTML = '<h2 style="margin-top:0;">Instagram Video Settings</h2>';
for (var k in this.settings) {
var setting = this.settings[k];
var label = document.createElement("label");
label.style.display = "block";
label.style.margin = "16px 0";
label.style.fontSize = "1.08em";
var input = document.createElement("input");
input.type = "checkbox";
input.checked = this.values[k];
input.style.marginRight = "10px";
input.onchange = (function(key, gm_config) { return function() {
gm_config.values[key] = this.checked;
}; })(k, this);
label.appendChild(input);
label.appendChild(document.createTextNode(" " + setting.label));
wrapper.appendChild(label);
}
var saveBtn = document.createElement("button");
saveBtn.textContent = "Save";
saveBtn.style.marginRight = "20px";
saveBtn.style.padding = "8px 18px";
saveBtn.style.background = "#4caf50";
saveBtn.style.color = "#fff";
saveBtn.style.border = "none";
saveBtn.style.borderRadius = "5px";
saveBtn.style.fontWeight = "bold";
saveBtn.onclick = async () => {
for (var k in this.values) {
await GM_setValue(k, this.values[k]);
}
document.body.removeChild(wrapper);
window.location.reload();
};
var cancelBtn = document.createElement("button");
cancelBtn.textContent = "Cancel";
cancelBtn.style.padding = "8px 18px";
cancelBtn.style.background = "#888";
cancelBtn.style.color = "#fff";
cancelBtn.style.border = "none";
cancelBtn.style.borderRadius = "5px";
cancelBtn.onclick = () => {
document.body.removeChild(wrapper);
};
wrapper.appendChild(saveBtn);
wrapper.appendChild(cancelBtn);
document.body.appendChild(wrapper);
},
get: function(key) {
return this.values[key];
}
};
GM_config.init({
ENABLE_FULLSCREEN_ON_F: {
label: "Enable fullscreen on 'f' key press",
default: true
},
ENABLE_AUTOPLAY_ON_FULLSCREEN: {
label: "Auto-play when maximizing video",
default: true
},
ENABLE_UNMUTE_ON_LOAD: {
label: "Unmute videos on load and when new videos appear",
default: true
},
ENABLE_FULLSCREEN_ON_LOAD: {
label: "Fullscreen video on initial page load",
default: true
},
ENABLE_START_PAUSED_ON_LOAD: {
label: "Start video paused on initial page load",
default: false
}
});
GM_registerMenuCommand("Instagram Video Settings", function() {
GM_config.open();
});
(async function() {
'use strict';
for (const key in GM_config.settings) {
const v = await GM_getValue(key);
if (typeof v !== "undefined") GM_config.values[key] = v;
}
const ENABLE_FULLSCREEN_ON_F = GM_config.get("ENABLE_FULLSCREEN_ON_F");
const ENABLE_AUTOPLAY_ON_FULLSCREEN = GM_config.get("ENABLE_AUTOPLAY_ON_FULLSCREEN");
const ENABLE_UNMUTE_ON_LOAD = GM_config.get("ENABLE_UNMUTE_ON_LOAD");
const ENABLE_FULLSCREEN_ON_LOAD = GM_config.get("ENABLE_FULLSCREEN_ON_LOAD");
const ENABLE_START_PAUSED_ON_LOAD = GM_config.get("ENABLE_START_PAUSED_ON_LOAD");
function unmuteAllVideos() {
if (!ENABLE_UNMUTE_ON_LOAD) return;
const videos = document.querySelectorAll('video');
videos.forEach(video => {
video.muted = false;
video.volume = 1.0;
});
}
function pauseAllVideosOnLoad() {
const videos = document.querySelectorAll('video');
videos.forEach(video => {
video.pause();
});
}
// Only pause videos once, on initial load
if (ENABLE_START_PAUSED_ON_LOAD) {
window.addEventListener('load', pauseAllVideosOnLoad);
}
// Only unmute logic for MutationObserver and scroll events
if (ENABLE_UNMUTE_ON_LOAD) {
window.addEventListener('load', unmuteAllVideos);
const observer = new MutationObserver(() => unmuteAllVideos());
observer.observe(document.body, { childList: true, subtree: true });
document.addEventListener('scroll', () => setTimeout(unmuteAllVideos, 500));
}
let popupDiv = null;
let movedVideo = null;
let originalParent = null;
let originalNextSibling = null;
let originalStyles = null;
let originalControls = null;
let resizeVideo = null;
let handleEscape = null;
let debugListeners = [];
function addDebugListeners(video) {
debugListeners.forEach(({event, handler}) => {
video.removeEventListener(event, handler);
});
debugListeners = [];
const log = (msg) => {
console.log(`[IG Video Debug] ${msg} | muted=${video.muted} volume=${video.volume} paused=${video.paused} currentTime=${video.currentTime}`);
};
const playHandler = () => log('play event');
const pauseHandler = () => log('pause event');
const volumeHandler = () => {
if (video.muted) {
log('muted event');
} else {
log('unmuted event');
}
};
const endedHandler = () => log('ended event');
video.addEventListener('play', playHandler);
video.addEventListener('pause', pauseHandler);
video.addEventListener('volumechange', volumeHandler);
video.addEventListener('ended', endedHandler);
debugListeners = [
{event: 'play', handler: playHandler},
{event: 'pause', handler: pauseHandler},
{event: 'volumechange', handler: volumeHandler},
{event: 'ended', handler: endedHandler}
];
}
function popupLargestVideo({autoplayIfPaused = false} = {}) {
if (popupDiv) return;
const videos = document.querySelectorAll('video');
if (videos.length === 0) return;
let targetVideo = videos[0];
let maxArea = 0;
videos.forEach(video => {
const rect = video.getBoundingClientRect();
const area = rect.width * rect.height;
if (area > maxArea && rect.width > 100 && rect.height > 100 && rect.top >= 0 && rect.left >= 0) {
targetVideo = video;
maxArea = area;
}
});
originalParent = targetVideo.parentNode;
originalNextSibling = targetVideo.nextSibling;
originalStyles = targetVideo.getAttribute('style');
originalControls = targetVideo.controls;
popupDiv = document.createElement('div');
popupDiv.style.position = 'fixed';
popupDiv.style.zIndex = '2147483647';
popupDiv.style.top = '0';
popupDiv.style.left = '0';
popupDiv.style.width = '100vw';
popupDiv.style.height = '100vh';
popupDiv.style.display = 'flex';
popupDiv.style.alignItems = 'center';
popupDiv.style.justifyContent = 'center';
popupDiv.style.background = 'rgba(0,0,0,0.85)';
popupDiv.style.boxSizing = 'border-box';
popupDiv.style.overflow = 'hidden';
targetVideo.style.position = 'absolute';
targetVideo.style.zIndex = '2';
targetVideo.style.top = '0';
targetVideo.style.left = '0';
targetVideo.style.width = '100vw';
targetVideo.style.height = '100vh';
targetVideo.style.boxShadow = '0 0 40px rgba(0,0,0,0.7)';
targetVideo.style.background = '#000';
targetVideo.style.border = 'none';
targetVideo.style.borderRadius = '0';
targetVideo.style.objectFit = 'contain';
targetVideo.controls = true;
popupDiv.appendChild(targetVideo);
document.body.appendChild(popupDiv);
movedVideo = targetVideo;
movedVideo.setAttribute('tabindex', '0');
movedVideo.focus();
addDebugListeners(movedVideo);
resizeVideo = function() {
if (movedVideo) {
movedVideo.style.width = window.innerWidth + 'px';
movedVideo.style.height = window.innerHeight + 'px';
}
};
resizeVideo();
window.addEventListener('resize', resizeVideo);
if (autoplayIfPaused && movedVideo.paused) {
movedVideo.muted = true;
movedVideo.volume = 1.0;
let playPromise = movedVideo.play();
if (playPromise !== undefined) {
playPromise
.then(() => {
setTimeout(() => {
movedVideo.muted = false;
movedVideo.volume = 1.0;
}, 200);
})
.catch((err) => {
// Autoplay failed, do nothing
});
}
}
handleEscape = function(ev) {
if ((ev.key === 'Escape' || ev.key === 'f') && popupDiv) {
restoreVideo();
}
};
document.addEventListener('keydown', handleEscape);
popupDiv.addEventListener('click', function(ev) {
if (ev.target === popupDiv) {
restoreVideo();
}
});
popupDiv.addEventListener('mousedown', function(ev) {
if (ev.target === movedVideo) {
setTimeout(() => movedVideo.focus(), 0);
}
});
movedVideo.addEventListener('blur', () => {
setTimeout(() => {
if (popupDiv) movedVideo.focus();
}, 0);
});
function restoreVideo() {
if (movedVideo) {
if (originalStyles !== null) {
movedVideo.setAttribute('style', originalStyles);
} else {
movedVideo.removeAttribute('style');
}
movedVideo.controls = originalControls;
window.removeEventListener('resize', resizeVideo);
debugListeners.forEach(({event, handler}) => {
movedVideo.removeEventListener(event, handler);
});
debugListeners = [];
if (originalNextSibling) {
originalParent.insertBefore(movedVideo, originalNextSibling);
} else {
originalParent.appendChild(movedVideo);
}
movedVideo = null;
}
if (popupDiv) {
popupDiv.remove();
popupDiv = null;
document.removeEventListener('keydown', handleEscape);
}
resizeVideo = null;
handleEscape = null;
}
}
if (ENABLE_FULLSCREEN_ON_LOAD) {
window.addEventListener('load', function() {
setTimeout(() => popupLargestVideo({
autoplayIfPaused: false
}), 10);
});
}
if (ENABLE_FULLSCREEN_ON_F) {
document.addEventListener('keydown', function(e) {
if (e.key === 'f' && !e.ctrlKey && !e.metaKey && !e.altKey) {
if (popupDiv) {
const escEvent = new KeyboardEvent('keydown', {key: 'Escape'});
document.dispatchEvent(escEvent);
} else {
popupLargestVideo({
autoplayIfPaused: ENABLE_AUTOPLAY_ON_FULLSCREEN
});
}
}
});
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment