I made a little script to filter seasonal anime. The purpose is to make it easier to hunt for new anime to watch.
If you don't know how to install this, watch this video by hacker09.
Some scrips can be malicious and it's on you to keep yourself safe.
It hides any shows with <5 score or <5000 members and hides the "TV (Continuing)" section.
(Should be pretty safe values and not remove anything worth watching - except maybe some ecchi/hentai/chinese shows.)
Also makes completed shows a tiny bit blurry (but still readable).
* You can of course change the numbers to suit your taste, they're right at the top. Also whether continuing shows are hidden by default.
* Press ESCAPE to show hidden shows.
* Press BACKTICK ( ` ) to show "TV (Continuing)"
* Blur can be removed by setting it to 0.
Code is dead simple, feel free to examine and change at will.
(I would also like to express my gratitude to the developers of MAL for making a very developer friendly page.)
// ==UserScript==
// @name MAL Seasonal anime browser
// @namespace martixy
// @version 2025-09-09
// @description Make browsing the seasonal anime list easier.
// @author martixy
// @match https://myanimelist.net/anime/season*
// @icon https://www.google.com/s2/favicons?sz=64&domain=myanimelist.net
// @grant GM_addStyle
// ==/UserScript==
'use strict';
console.clear()
const FILTER_BELOW_SCORE = 5.0
const FILTER_BELOW_MEMBERS = 5000
const HIDE_CONTINUING_SHOWS = true
const BLUR_STRENGTH = 1 /* Noticeable at a glance, but still readable */
/**
* data-status
* 0 = Add to list (none)
* 1 = Watching
* 2 = Completed
* 3 = On Hold
* 4 = Dropped
* 6 = Plan to watch
*/
let style = /*css*/`
.seasonal-anime:has([data-status="2"]) {
filter: blur(${BLUR_STRENGTH}px);
}
.mx-hide,
.mx-hide-slop .mx-slop {
display: none !important; /* Some elements down the page get an element style */
}
`
GM_addStyle(style)
let allCategories = document.querySelector('.js-categories-seasonal')
let continuingShows = document.querySelector('.seasonal-middle+.js-seasonal-anime-list-key-1')
let header = document.querySelector('.anime-header')
let removedCount = 0
document.querySelectorAll('.seasonal-anime').forEach(el => {
let score = Number(el.querySelector('.js-score').textContent.trim()) || FILTER_BELOW_SCORE //rating can be N/A = 0 (obscure or not-yet-aired shows)
let members = Number(el.querySelector('.js-members').textContent.trim())
// console.log(el.querySelector('.js-title').textContent, score, members, score < FILTER_BELOW_SCORE || members < FILTER_BELOW_MEMBERS)
let parentHeader = el.parentElement.firstElementChild
if (parentHeader !== header) {
header.textContent += ` [${removedCount}]`
removedCount = 0
header = parentHeader
}
if (score < FILTER_BELOW_SCORE || members < FILTER_BELOW_MEMBERS) {
el.classList.add('mx-slop')
removedCount++ //Includes ones hidden by your other filters (e.g. kids shows)
// if (score > 7.5) console.log(el.querySelector('.js-title').textContent, score) //Almost universally chinese/korean shows (and very rare)
}
})
header.textContent += ` [${removedCount}]`
allCategories.classList.add('mx-hide-slop')
if (HIDE_CONTINUING_SHOWS) continuingShows.classList.add('mx-hide')
/**
* @param {KeyboardEvent} ev
*/
function kbHandler(ev) {
// console.log(ev)
if (ev.target instanceof HTMLInputElement) return
if (ev.ctrlKey || ev.shiftKey || ev.altKey) return
switch (ev.code) {
case 'Escape': {
allCategories.classList.toggle('mx-hide-slop')
break
}
case 'Backquote': {
continuingShows.classList.toggle('mx-hide')
break
}
}
}
document.addEventListener('keydown', kbHandler)
@hacker09 Well, my initial thought was: Anyone who can install this on their own can probably read the script enough to tell what it's doing and I didn't wanna encourage novice users who wouldn't be able to tell apart malicious code from benign.
@hacker09 Well, my initial thought was: Anyone who can install this on their own can probably read the script enough to tell what it's doing and I didn't wanna encourage novice users who wouldn't be able to tell apart malicious code from benign.
@martixy we post scripts in Creative Corner.
also the key presses weren't working for me everytime, didn't test the console.log on why, but me and hacker09 usually use GM_registerMenuCommand to enable/disable options.
@martixy we post scripts in Creative Corner.
also the key presses weren't working for me everytime, didn't test the console.log on why, but me and hacker09 usually use GM_registerMenuCommand to enable/disable options.
@martixy we post scripts in Creative Corner.
also the key presses weren't working for me everytime, didn't test the console.log on why, but me and hacker09 usually use GM_registerMenuCommand to enable/disable options.
@ShaggyZE Cool. You seem to be a userscripter yourself, so I'm sure if you wanted to, you could tell me any errors that crop up.