Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save juanbrujo/72c45057b104bd5986ebe54d1241dce5 to your computer and use it in GitHub Desktop.

Select an option

Save juanbrujo/72c45057b104bd5986ebe54d1241dce5 to your computer and use it in GitHub Desktop.
YouTube - Hide Live Chat By Default
// ==UserScript==
// @name YouTube - Hide Live Chat By Default
// @namespace https://gist.github.com/lbmaian/94824cef728917a53d3c6e6ea885469c
// @downloadURL https://gist.github.com/lbmaian/94824cef728917a53d3c6e6ea885469c/raw/youtube-hide-livechat.user.js
// @updateURL https://gist.github.com/lbmaian/94824cef728917a53d3c6e6ea885469c/raw/youtube-hide-livechat.user.js
// @version 0.14
// @description Hide live chat by default on live streams
// @author lbmaian
// @match https://www.youtube.com/*
// @exclude https://www.youtube.com/embed/*
// @icon https://www.youtube.com/favicon.ico
// @run-at document-start
// @grant none
// ==/UserScript==
(function() {
'use strict';
const DEBUG = false;
const logContext = '[YouTube - Hide Live Chat]';
var debug;
if (DEBUG) {
debug = function(...args) {
console.debug(logContext, ...args);
}
} else {
debug = function(...args) {}
}
function log(...args) {
console.log(logContext, ...args);
}
function warn(...args) {
console.warn(logContext, ...args);
}
function error(...args) {
console.error(logContext, ...args);
}
// Note: Following all relies on YT internals.
function updateChatData(data, collapsed) {
if (DEBUG) {
debug('data (before)', window.structuredClone(data));
}
const liveChatRenderer = data.liveChatRenderer;
if (liveChatRenderer) { // if no live chat despite #chat existing, e.g. "Live chat replay is not available for this video."
const expandedByDefault = liveChatRenderer.initialDisplayState === 'LIVE_CHAT_DISPLAY_STATE_EXPANDED';
if (expandedByDefault && collapsed) {
if (collapsed) {
log('hiding live chat');
}
debug('data.liveChatRenderer.initialDisplayState:', liveChatRenderer.initialDisplayState,
'=>', 'LIVE_CHAT_DISPLAY_STATE_COLLAPSED');
liveChatRenderer.initialDisplayState = 'LIVE_CHAT_DISPLAY_STATE_COLLAPSED';
}
const toggleButtonRenderer = liveChatRenderer.showHideButton?.toggleButtonRenderer;
if (toggleButtonRenderer) {
if (expandedByDefault) {
debug('data.liveChatRenderer.showHideButton.toggleButtonRenderer.defaultText/toggledText swapped');
[toggleButtonRenderer.defaultText, toggleButtonRenderer.toggledText] =
[toggleButtonRenderer.toggledText, toggleButtonRenderer.defaultText];
}
const isToggled = !collapsed;
if (DEBUG && toggleButtonRenderer.isToggled !== isToggled) {
debug('data.liveChatRenderer.showHideButton.toggleButtonRenderer.isToggled', toggleButtonRenderer.isToggled,
'=>', isToggled);
}
toggleButtonRenderer.isToggled = isToggled;
}
if (DEBUG) {
debug('data (updated)', window.structuredClone(data));
}
return expandedByDefault;
} else {
return false;
}
}
// Navigating to YouTube watch page can happen via AJAX rather than new page load.
// We can monitor this with YT's custom yt-page-data-fetched event,
// which conveniently also fires even for new/refreshed pages.
// yt-navigate-finish would also work (evt.detail.detail) but yt-page-data-fetched fires earlier.
document.addEventListener('yt-page-data-fetched', evt => {
debug('Navigated to', evt.detail.pageData.url);
debug(evt);
const conversationBar = evt.detail.pageData.response?.contents?.twoColumnWatchNextResults?.conversationBar;
debug('yt-page-data-fetched pageData.response contents.twoColumnWatchNextResults.conversationBar (corresponds to #chat.data)',
conversationBar);
// If response doesn't include conversationBar, there won't be a #chat element at all.
if (conversationBar) {
// If #chat element isn't created yet, default collapsed to true.
// Else keep current collapsed status between pages.
// TODO: sometimes for new pages when chat doesn't exist yet, this apparently happens too late?
// (chat already initialized with old data) and chat thus remains open?
// Detect & fix this - use chat.parentComponent (ytd-watch-flexy)'s updatePageData_ or ytd-app's onYtPageDataFetched?
const chat = document.getElementById('chat');
let collapsed;
if (chat) {
collapsed = chat.collapsed;
log('existing #chat', chat, 'collapsed:', collapsed);
} else {
log('no existing #chat, defaulting collapsed: true');
collapsed = true;
}
updateChatData(conversationBar, collapsed);
}
});
})();
@bflixcom-ai

Copy link
Copy Markdown

Such a simple script, but it fixes one of the most annoying YouTube behaviors. I love how it hooks into YouTube’s internal events instead of relying on clunky DOM Bflix hacks—makes it feel much more reliable across navigation. The attention to preserving toggle state is a really nice touch too. Clean, smart, and actually useful.

@GamingGuruBoBa

Copy link
Copy Markdown

my literal brain rn obsessing over the weird mystery boxes completely clogging up the conveyor belt in marble sort fr

@wooflixto

Copy link
Copy Markdown

Finally, a simple fix for one of YouTube’s most annoying “features.” This script feels like something that should’ve been built-in years ago—clean, lightweight, and it just works without messing with anything else. I especially like how it hooks into YouTube’s internal navigation instead of relying on clunky DOM hacks. Huge respect to the author for keeping it efficient and thoughtful—makes live streams way more watchable without the constant chat distraction.

@cineby

cineby commented Apr 16, 2026

Copy link
Copy Markdown

Honestly, this feels less like a workaround and more like restoring common sense to YouTube. It’s impressively streamlined—no bloat, no weird side effects—just a clean solution that does exactly what you want. The fact that it integrates with YouTube’s own navigation instead of patching things together makes it stand out even more.

@flixtorto

Copy link
Copy Markdown

This is one of those small tweaks that ends up making a surprisingly big difference. YouTube’s default behavior of auto-expanding live chat can be distracting, especially when you’re just there for the content. I like how this script hooks into YouTube’s internal page data rather than relying on brittle DOM hacks—it feels more reliable across navigation changes.

@flixerto

Copy link
Copy Markdown

This userscript is a clean and efficient solution for improving focus during YouTube live streams by automatically hiding the live chat by default. Instead of removing the chat entirely, it smartly modifies YouTube’s internal page data so the chat loads in a collapsed state, reducing distractions while still keeping it accessible when needed. By working directly with YouTube’s navigation events and UI state, it ensures the setting applies consistently across both refreshed and dynamically loaded pages.

@wcofun

wcofun commented May 9, 2026

Copy link
Copy Markdown

This userscript is a clever and practical quality-of-life tweak for anyone who regularly watches live streams on YouTube. Instead of relying on manual clicks every time a stream loads, it automatically collapses the live chat by modifying YouTube’s internal page data before the interface fully renders. That’s a smart approach—it makes the change feel native rather than forced after the fact. Visit

@gmoviestv

Copy link
Copy Markdown

This userscript is a smart quality-of-life upgrade for YouTube live stream viewers who prefer focus over noise. Instead of simply hiding chat after the page loads, it cleverly Punisher hooks into YouTube’s internal page data system to collapse live chat before it becomes a distraction—even during AJAX navigation between videos.

@lasbelaak1

Copy link
Copy Markdown

Nice approach. I’ve seen a lot of userscripts solve this by repeatedly manipulating the DOM after page load, but modifying the page data before the UI fully renders feels much cleaner and less fragile. The handling of YouTube’s AJAX navigation is especially useful since that’s where many older scripts break. I appreciate solutions that focus on reducing distractions without removing functionality entirely. Interestingly, I recently noticed a similar emphasis on user-friendly design while browsing https://phoenixarizonadentistry.com/ different niche, but the same idea of simplifying the experience without getting in the user’s way.

@emily410182

Copy link
Copy Markdown

youtube-hide-livechat.user.js is a userscript designed to automatically hide the live chat panel on YouTube livestreams. It helps create a cleaner, less distracting viewing experience by removing or collapsing the chat whenever a live stream is opened Redzhub Free.

@makeqiang321-cell

Copy link
Copy Markdown

He chose the brick breaker format because it needed only one axis of input — left and right. The trackball was perfect for it.

@makeqiang321-cell

Copy link
Copy Markdown

tried the paint system. Ready to put a disguise to the test? Play Meccha Chameleon online free in your browser. Prefer the one-page overview of all the maps with the play button

@makeqiang321-cell

Copy link
Copy Markdown

right at the top? Head back to the Meccha Chameleon Online homepage.

@makeqiang321-cell

Copy link
Copy Markdown

Bus Traffic Fever turns gridlock into a brain teaser — slide the buses, open the blocked lanes, and pick up every color-matched

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment