Last active
February 21, 2026 21:52
Disable Bilibili Danmaku and Autoplay
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // ==UserScript== | |
| // @name Disable Bilibili Danmaku and Autoplay | |
| // @name:zh-CN 禁用哔哩哔哩弹幕及自动连播 | |
| // @namespace http://tampermonkey.net/ | |
| // @version 1.1 | |
| // @description Turns off Bilibili danmaku and autoplay switches. Works even when signed out or after clearing cookies. | |
| // @description:zh-CN 自动关闭B站弹幕及自动连播,即使处于未登录状态或清理了 Cookie,该脚本依然可以正常运行。 | |
| // @match *://www.bilibili.com/video/* | |
| // @match *://player.bilibili.com/player.html* | |
| // @match *://www.bilibili.com/blackboard/html5mobileplayer.html* | |
| // @grant none | |
| // @icon https://www.bilibili.com/favicon.ico | |
| // @run-at document-start | |
| // @license MIT | |
| // ==/UserScript== | |
| (function() { | |
| 'use strict'; | |
| let lastExecutionTime = 0; | |
| let burstTimer = null; | |
| const COOLDOWN_MS = 2000; // Intervals between scans during idle periods to save CPU | |
| /** | |
| * Core function to detect and click active switches. | |
| */ | |
| const disableSettings = () => { | |
| let foundAnything = false; | |
| // 1. PC/Embedded Player | |
| // Only trigger click if 'checked' is true to prevent toggle loops | |
| const danmakuInput = document.querySelector('.bui-danmaku-switch-input'); | |
| if (danmakuInput && danmakuInput.checked) { | |
| danmakuInput.click(); | |
| foundAnything = true; | |
| } | |
| // 2. Autoplay switch | |
| // Once clicked, the '.on' class is removed, preventing re-execution | |
| const autoPlayBtn = document.querySelector('.next-play .switch-btn.on, .video-pod .switch-btn.on'); | |
| if (autoPlayBtn) { | |
| autoPlayBtn.click(); | |
| foundAnything = true; | |
| } | |
| // 3. Mobile Player | |
| // Mobile UI uses 'mplayer-active' class on an icon rather than a checkbox | |
| const mobileDanmakuBtn = document.querySelector('.mplayer-btn-comment .mplayer-active'); | |
| if (mobileDanmakuBtn) { | |
| mobileDanmakuBtn.click(); | |
| foundAnything = true; | |
| } | |
| lastExecutionTime = Date.now(); | |
| return foundAnything; | |
| }; | |
| /** | |
| * Burst Mode: Increases scanning frequency to 200ms when dynamic changes are detected. | |
| * Ensures settings are disabled immediately after SPA navigation or page load. | |
| */ | |
| const triggerBurst = () => { | |
| if (burstTimer) return; | |
| let attempts = 0; | |
| burstTimer = setInterval(() => { | |
| const deactivated = disableSettings(); | |
| attempts++; | |
| // Exit burst mode once switches are handled or timeout (5s) is reached | |
| if (deactivated || attempts > 25) { | |
| clearInterval(burstTimer); | |
| burstTimer = null; | |
| } | |
| }, 200); | |
| }; | |
| /** | |
| * MutationObserver to handle Bilibili's SPA navigation. | |
| * Monitors node additions within the player container. | |
| */ | |
| const observer = new MutationObserver((mutations) => { | |
| let shouldCheck = false; | |
| for (let i = 0; i < mutations.length; i++) { | |
| if (mutations[i].addedNodes.length > 0) { | |
| shouldCheck = true; | |
| break; | |
| } | |
| } | |
| if (shouldCheck) { | |
| const now = Date.now(); | |
| // If the last scan was long ago, start a high-frequency burst | |
| if (now - lastExecutionTime > COOLDOWN_MS) { | |
| triggerBurst(); | |
| } else { | |
| disableSettings(); | |
| } | |
| } | |
| }); | |
| const init = () => { | |
| // Narrow the scope to the main container found during DOM analysis to reduce overhead | |
| const targetContainer = document.querySelector('#mirror-vdcon') || document.body; | |
| observer.observe(targetContainer, { | |
| childList: true, | |
| subtree: true | |
| }); | |
| // Run initial burst to catch elements rendered during early load | |
| triggerBurst(); | |
| }; | |
| // Initialize as soon as the body is available | |
| if (document.body) { | |
| init(); | |
| } else { | |
| const preObserver = new MutationObserver(() => { | |
| if (document.body) { | |
| preObserver.disconnect(); | |
| init(); | |
| } | |
| }); | |
| preObserver.observe(document.documentElement, { childList: true }); | |
| } | |
| })(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment