Tampermonkey userscript that helps prevent MIUI/HyperOS from killing mobile browser tabs. No root required.
A Tampermonkey userscript that helps prevent mobile browser tabs from being killed by aggressive Android memory management (MIUI, HyperOS, ColorOS, FunTouchOS, and similar).
Works with Firefox Mobile, Microsoft Edge, Yandex Browser, Kiwi Browser, Lemur Browser, and other Tampermonkey-compatible mobile browsers.
Xiaomi's MIUI, HyperOS, and similar aggressive Android skins implement memory management that kills background applications and browser tabs without warning. This affects mobile browser users in several ways:
Android's standard application lifecycle is ignored by these ROMs, and there is no reliable way to prevent this behavior through system settings alone.
This userscript makes Android treat your browser as an active media application. Android ROMs, including aggressive ones like MIUI, usually avoid killing apps while they are actively playing media.
The script can keep the browser "alive" in two ways:
In both modes, the script registers a MediaSession that appears in Android's media controls as "Video KeepAlive" or "Audio KeepAlive". As long as this notification is present, the system is much less likely to kill the browser and discard tabs.
This script works with any mobile browser that supports the Tampermonkey extension:
| Browser | Status | Notes |
|---|---|---|
| Firefox Mobile | Recommended | Primary development and testing browser |
| Firefox Forks (Fennec, Mull, Iceraven) | Supported | Should work identically to Firefox Mobile |
| Microsoft Edge | Supported | |
| Yandex Browser | Supported | |
| Kiwi Browser | Supported | |
| Lemur Browser | Supported | |
| Safari (iOS) | Supported | Use "Userscripts" by Quoid from App Store, or similar Apps |
Note for browsers that block YouTube userscripts: Some browsers may prevent userscripts from running on YouTube. If you encounter this issue, you can use Vimeo as an alternative. The script already includes support for vimeo.com.
Install Tampermonkey from your browser's add-on/extension store:
Visit the Greasy Fork page and tap "Install": https://greasyfork.org/en/scripts/563527-miui-browser-tab-keepalive
Confirm the installation when Tampermonkey prompts you
Open any YouTube or Vimeo page to verify the installation — you should see a small circle badge in the bottom-right corner
(Optional) If videos stop playing when the browser is in the background or when the screen is switched off, you can also install this companion script:
Install Mobile Browser Background Video https://greasyfork.org/en/scripts/563528-mobile-browser-background-video
The script uses a Master Tab system. When you activate KeepAlive on any YouTube or Vimeo tab, that tab becomes the master. The important part is that the master tab protects all browser tabs, not just itself.
The recommended approach is to dedicate one YouTube or Vimeo tab as your permanent master tab. This tab does not need to play any real video content — it simply needs to exist and have KeepAlive activated.
Most mobile browsers require a user gesture before they allow background media playback and MediaSession controls.
To stop KeepAlive:
Alternatively, simply close the master tab.
By default, KeepAlive ignores pause commands from Android notification controls. This prevents accidental deactivation and makes KeepAlive more robust against other apps trying to stop it.
If you prefer to control KeepAlive via the notification player:
VideoKeepAliveAllowInput: true and/or AudioKeepAliveAllowInput: true in the profile configurationProfile 2 provides more aggressive KeepAlive settings for devices that need stronger protection.
To return to Profile 1, tap the badge to deactivate KeepAlive. The next short tap activation will use Profile 1 again.
The master tab can be transferred to any other YouTube or Vimeo tab:
Only one tab can be the master at any time.
| Badge Appearance | Meaning |
|---|---|
| Empty circle | KeepAlive is available but not active on this tab |
| Circle with white lock | This tab is the master, Profile 1 is active |
| Circle with red lock | This tab is the master, Profile 2 is active |
The script includes two configurable profiles:
You are encouraged to experiment and share your profile settings with the community.
The profile configuration is located near the top of the userscript:
PROFILE_1 and PROFILE_2 objects near the top of the codeEach profile contains the following parameters:
| Parameter | Type | Description |
|---|---|---|
VideoKeepAlive |
Boolean | Enable/disable Video KeepAlive (hidden video + MediaSession). |
VideoKeepAliveAllowInput |
Boolean | Allow pause/play from notification controls. false = ignores pause commands and resumes automatically. true = can be paused and resumed via notifications. |
canvasStreamFps |
Number | FPS for the canvas-based hidden video stream. Higher values create more activity but use more battery. Typical range: 0.1 to 2. |
muted |
Boolean | Whether the hidden video is muted. For silent operation set true. |
volume |
Number | Video volume (0 to 1). Usually keep at 0. |
| Parameter | Type | Description |
|---|---|---|
AudioKeepAlive |
Boolean | Enable/disable Audio KeepAlive (hidden audio + MediaSession). |
AudioKeepAliveAllowInput |
Boolean | Allow pause/play from notification controls. false = ignores pause commands and resumes automatically. true = can be paused and resumed via notifications. |
AudioFrequencyHz |
Number | Tone frequency in Hz. For quiet/less noticeable output, try high values like 18000. |
AudioGain |
Number | Tone loudness multiplier. Use very small values like 0.000001 to keep it effectively silent. |
AudioResumeIntervalMs |
Number | Audio resume interval, if it somehow stops (0 = off). |
If both VideoKeepAlive and AudioKeepAlive are enabled, this decides which mode is started first:
| Parameter | Type | Description |
|---|---|---|
KeepAlivePriority |
String | 'video' or 'audio'. Primary mode if both are enabled. |
MediaSession refresh periodically re-asserts the media notification. Some apps may stop playback when this is enabled.
| Parameter | Type | Description |
|---|---|---|
mediaSessionRefresh |
Boolean | Enable/disable MediaSession refresh (some music playing apps will stop playing!). |
mediaSessionRefreshIntervalMs |
Number | How often to re-assert. If set to 0 and true, it is asserted once at activation. |
The retry watchdog restarts KeepAlive if the active mode stops.
| Parameter | Type | Description |
|---|---|---|
retryWatchdog |
Boolean | Restart KeepAlive if Audio/Video stops. |
retryDelayMinMs |
Number | Minimum delay between retries (ms). |
retryDelayMaxMs |
Number | Maximum delay with exponential backoff (ms). |
| Parameter | Type | Description |
|---|---|---|
webLock |
Boolean | Holds an exclusive Web Lock to make the tab look less idle (low-cost mechanism). |
A practical strategy to find your optimal settings:
canvasStreamFpsretryWatchdogRuns only on YouTube and Vimeo: The script is designed to run on supported media pages. You can add more @match patterns if you want it on other sites.
Requires one YouTube or Vimeo tab open: You need at least one supported tab available to run KeepAlive.
Not a complete guarantee: Extremely aggressive battery saver modes or critically low memory situations may still cause your browser to be killed.
Visible media notification: The "Video KeepAlive" / "Audio KeepAlive" entry in your media controls is intentional and necessary, but may interfair with other media playing.
Some browsers may block YouTube userscripts: If your browser prevents userscripts from running on YouTube, use Vimeo as an alternative.
Loses effect while media is played in another app: The workaround relies on the browser’s media notification to appear “active” to the OS. When another app takes over audio/video playback, this signal is replaced and the keep-alive can no longer be maintained. Short playback in another app may sometimes work by chance, but this cannot be relied on.
youtube.com, m.youtube.com, or vimeo.comcanvasStreamFpsretryWatchdog| Device | ROM | Browser | Status |
|---|---|---|---|
| Xiaomi MI 11 Ultra | HyperOS | Firefox Mobile | Working |
If you have tested on other devices or browsers, please open an issue or pull request to add your configuration.
Finding the optimal profile settings for your device requires experimentation. Since every device, ROM version, and browser behaves differently, sharing your experiences helps other users.
When sharing your configuration, please include:
PROFILE_1 and PROFILE_2 settingsReddit Discussion Thread: https://www.reddit.com/r/Xiaomi/comments/1qlm81b/fixno_rootadb_miuihyperos_keeps_killing_your/
GitHub Repository: https://github.com/DJ-Flitzefinger/miui-browser-tab-keepalive
GNU General Public License v3 (GPL-3.0-or-later)
Buy me a coffee if you found this script helpful!