How to restore YouTube dislike stats

Without relying on third-party API

Lui Yong Sheng
3 min readDec 8, 2021
Press the plus button.
Press the plus button.

3. Paste UserScript

// ==UserScript==
// @name Restore YouTube Dislikes
// @version 1.0
// @description Restore YouTube dislikes stats.
// @author luiyongsheng
// @match *://www.youtube.com/*
// @run_at document_start
// ==/UserScript==
(function () {
"use strict";
function calculateDislikes(l, r) {
let d = Math.round(l * ((5 - r) / (r - 1)));
return d;
}
// Your code here...
function nFormatter(num, digits) {
const lookup = [
{ value: 1, symbol: "" },
{ value: 1e3, symbol: "k" },
{ value: 1e6, symbol: "M" },
{ value: 1e9, symbol: "G" },
{ value: 1e12, symbol: "T" },
{ value: 1e15, symbol: "P" },
{ value: 1e18, symbol: "E" },
];
const rx = /\.0+$|(\.[0-9]*[1-9])0+$/;
var item = lookup
.slice()
.reverse()
.find(function (item) {
return num >= item.value;
});
return item
? (num / item.value).toFixed(digits).replace(rx, "$1") + item.symbol
: "0";
}
async function waitForElm(s) {
while (!document.querySelector(s)) {
await new Promise((r) => requestAnimationFrame(r));
}
return;
}
async function init() {
try {
let data = document.querySelector("ytd-app").data;
for (
let p = 0;
p <
data.response.contents.twoColumnWatchNextResults.results.results
.contents.length;
p++
) {
if (
typeof data.response.contents.twoColumnWatchNextResults.results
.results.contents[p].videoPrimaryInfoRenderer != "undefined"
) {
var vidroot =
data.response.contents.twoColumnWatchNextResults.results.results
.contents[p];
}
}
let l;
if (
vidroot.videoPrimaryInfoRenderer.videoActions.menuRenderer
.topLevelButtons[0].toggleButtonRenderer.isToggled
) {
l = parseInt(
vidroot.videoPrimaryInfoRenderer.videoActions.menuRenderer.topLevelButtons[0].toggleButtonRenderer.toggledText.accessibility.accessibilityData.label.replace(
/( likes|,)/g,
""
)
);
} else {
l = parseInt(
vidroot.videoPrimaryInfoRenderer.videoActions.menuRenderer.topLevelButtons[0].toggleButtonRenderer.defaultText.accessibility.accessibilityData.label.replace(
/( likes|,)/g,
""
)
);
}
let r = data.playerResponse.videoDetails.averageRating;
let dislikes = r != 0 ? await calculateDislikes(l, r) : 0;let dislikesfin = nFormatter(dislikes);
let likesfin = nFormatter(l);
// added bonus
if (r != 0) {
document.querySelector(
"yt-formatted-string#text.ytd-toggle-button-renderer"
).innerHTML = likesfin;
} else {
document.querySelector(
"yt-formatted-string#text.ytd-toggle-button-renderer"
).innerHTML = "0";
}
document.querySelectorAll(
"yt-formatted-string#text.ytd-toggle-button-renderer"
)[1].innerHTML = dislikesfin;
document.querySelector(
"yt-formatted-string#text.ytd-toggle-button-renderer"
).onmouseup = function () {
document.querySelector(
"yt-formatted-string#text.ytd-toggle-button-renderer"
).innerHTML = "";
};
document.querySelectorAll(
"yt-formatted-string#text.ytd-toggle-button-renderer"
)[1].onmouseup = function () {
document.querySelectorAll(
"yt-formatted-string#text.ytd-toggle-button-renderer"
)[1].innerHTML = "";
};
let sentimentPercent = (l / (l + dislikes)) * 100;document
.querySelector("ytd-sentiment-bar-renderer")
.removeAttribute("hidden");
document
.getElementById("like-bar")
.setAttribute("style", "width: " + sentimentPercent + "%;");
} catch (e) {
console.warn(e);
}
}
waitForElm("yt-formatted-string#text.ytd-toggle-button-renderer").then(() =>
init()
);
window.addEventListener("yt-page-data-updated", init, false);
})();

Credit: I modified the original code to support thousands separator.

Paste the script and save.
Paste the script and save.

4. Done

You will see a red dot next to the Tampermonkey icon when the script is activated.

Tampermonkey script running on YouTube.com
Tampermonkey script running on YouTube.com

--

--