How to restore YouTube dislike stats
Without relying on third-party API
3 min readDec 8, 2021
1. Install Tampermonkey extension on your browser.
Chromium browsers (Chrome, Brave, Edge, etc.): https://chrome.google.com/webstore/detail/tampermonkey/dhdgffkkebhmkfjojejmpbldmpobfkfo?hl=enFirefox: https://addons.mozilla.org/en-US/firefox/addon/tampermonkey/Safari: https://apps.apple.com/app/apple-store/id1482490089
2. Add New Script
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 bonusif (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.
4. Done
You will see a red dot next to the Tampermonkey icon when the script is activated.