[UserScript] Better Progress Bar

:warning: This is a third-party script/app and is not created by the WaniKani team. By using this, you understand that it can stop working at any time or be discontinued indefinitely.

Saw a post earlier about the fact, that the progress bar on the wanikani page is kinda… weird. Usually You have it at 0 and then it suddenly jumps up in a few reviews at most then it goes back to 0. It would be better if it went up gradually actually showing some progress being made. So that’s what I did.

Introducing “WaniKani - Better Progress Bar”. It tracks the number of SRS stages you’ve completed and rescales the progress bar based on that:

Link to the userscript itself: WaniKani - Better Progress Bar

This script requires WKOF to work.
Install instructions can be found here

Update 2023-09-23:
Thanks to @LupoMikti, the script is working with the updates to the WK dashboard


Good script!


Accidentally left in the wrong URL to run on, which meant it didn’t run on for example WaniKani — Log in. Now that’s fixed

1 Like

There is also this one.


1 Like

That adds a bunch of other bars, I just change this one. It’s the simpler version for those that just want to see their progress but not change the dashboard in a huge way.

1 Like

I installed this script, and it’s running according to Tampermonkey, but I get this in the console:

Hint: I haven’t done any lessons for my current level yet…

Huh, so that can be null, will go ahead and fix that up later in the evening, thanks for the report

1 Like

Yeah, feels like a bit of an unfortunate API design, but it seems to be that way…

EDIT: Actually it’s undefined, which is different from null in JavaScript :rofl:

1 Like

Published an update, the issue was, that locked items don’t have assignments assigned to them. Also just included a different change for if you have no items left (really don’t know what happens past 60, this is a precaution against that)

1 Like

Hmmm, Greasyfork still shows me Ver. 0.1.1 (which still produces the error)? Maybe something went wrong in the update process?

Odd, I swear I copied the right thing, now it should be actually fixed

I find the Greasyfork UI to be somewhat… unintuitive, so don’t worry too much about it :woman_shrugging:

Anyways, now it works for me:

Thanks for the cool script and the speedy patch! :+1:

1 Like

Hello to the few of you who may still be tracking this thread c:

I recently discovered this script and thought it was a neat idea, so I installed it only to find out it is currently broken due to changes WaniKani have made to the dashboard. Luckily the script is fairly simple and straightforward so I was able to fix it with just a couple changes to class names.

While using it though, I noticed that it was possible for the bar to nearly fill up and push the label containing the text so far right it gets clipped off. This is because WaniKani does not move the label to the inside of the bar until a certain percentage fill happens (I don’t know what it is, hard to tell when you complete kanji in batches, but my guess is greater than 50%). So I also made an edit to the script to move the label when the bar gets filled more than 50%. I couldn’t test if this worked for a while though since I had just leveled up when I did it and I only just now got more than 50% of the SRS stages complete for my current level.

Since there’s no repository for this script linked, I’ll just share the code here since it is small enough that it shouldn’t be an issue. Just copy and paste it over the script in your script manager and save. Do note that if you do this, at least in Tampermonkey, this will disable automatic updates for the script (because you’ve made local edits). If an update is ever pushed, you will need to reenable checking for updates and have Tampermonkey do the update manually.

// ==UserScript==
// @name         WaniKani - Better Progress Bar
// @namespace    http://tampermonkey.net/
// @version      0.1.3
// @description  Change out kanji passed to srs stages beaten
// @author       Gorbit99
// @match        https://www.wanikani.com
// @match        https://www.wanikani.com/dashboard
// @match        https://preview.wanikani.com
// @match        https://preview.wanikani.com/dashboard
// @icon         https://www.google.com/s2/favicons?domain=wanikani.com
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    /* global wkof */

    if (!window.wkof) {
        alert('Better Progress Bar requires Wanikani Open Framework.\nYou will now be forwarded to installation instructions.');
        window.location.href = 'https://community.wanikani.com/t/instructions-installing-wanikani-open-framework/28549';



function do_query() {
        wk_items: {
            options: {
                assignments: true,
            filters: {
                item_type: ["rad", "kan"],
                level: '+0',

function handle_items(items) {
    let srsStages = items.filter(item => item.assignments !== undefined)
        .map(item =>
            item.assignments.passed_at !== null
                ? 5
                : Math.min(item.assignments.srs_stage, 5));

    if (srsStages.length < 0) {
        return 0;

    let max = srsStages.length * 5;
    let actual = srsStages.reduce((sum, x) => sum + x, 0);

    let progressBarFill = document.querySelector(".level-progress-bar__progress");
    const calculatedWidth = actual / max * 100;
    progressBarFill.style.width = `${calculatedWidth}%`;

    let progressBarLabel = document.querySelector('.level-progress-bar__label');
    if (progressBarLabel && !progressBarLabel.classList.contains('level-progress-bar__label--inside') && calculatedWidth > 50) {
    progressBarLabel.innerText = `${actual} of ${max} SRS stages`;

Do you mind if I push this as an update? Of course with some kind of attribution


I don’t mind at all! Just glad to get it in a working state again.


Strangely enough, while the post is only barely interacted with, this is still one of my nost popular scripts…


Why is this part using filter at all? It causes the graph to ignore locked items. You also need to unlock them to progress.

function handle_items(items) {
    let srsStages = items.filter(item => item.assignments !== undefined)
        .map(item =>
            item.assignments.passed_at !== null
                ? 5
                : Math.min(item.assignments.srs_stage, 5));

I changed it to this to make it work:

function handle_items(items) {
    let srsStages = items.map(item => (item.assignments === undefined) ? 0 : (item.assignments.passed_at !== null ? 5 : Math.min(item.assignments.srs_stage, 5)));

Now it shows correct number of SRS stages to pass.

Aren’t locked items srs -1?

Maybe they are, but the way it is checked in code works too and is more in line with the rest of the condition.