Unsave all saved posts on old.reddit.com via Tampermonkey menu
// ==UserScript==
// @name Batch Unsave Reddit Posts
// @namespace https://github.com/YangHgRi
// @version 1.0
// @description Unsave all saved posts on old.reddit.com via Tampermonkey menu
// @author YangHgRi
// @match https://old.reddit.com/user/*/saved*
// @grant GM_registerMenuCommand
// @grant GM_notification
// @license MIT
// ==/UserScript==
(function () {
const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
const BATCH_SIZE = 50;
const BATCH_BREAK = 60000;
const DELAY_MIN = 2000;
const DELAY_MAX = 5000;
const originalTitle = document.title;
let totalUnsaved = 0;
let totalFound = 0;
// ── Toast UI ──
function createToast() {
const el = document.createElement("div");
Object.assign(el.style, {
position: "fixed",
bottom: "20px",
right: "20px",
zIndex: "99999",
padding: "12px 20px",
minWidth: "220px",
background: "#1a1a2e",
color: "#eee",
fontSize: "13px",
borderRadius: "8px",
boxShadow: "0 4px 16px rgba(0,0,0,.4)",
fontFamily: "system-ui, sans-serif",
transition: "opacity .4s",
lineHeight: "1.6",
});
document.body.appendChild(el);
return el;
}
let toast = null;
function updateProgress(msg) {
if (!toast) toast = createToast();
toast.innerHTML = msg;
document.title = `[${totalUnsaved}/${totalFound}] Unsaving… — Reddit`;
}
function dismissToast(delay = 4000) {
document.title = originalTitle;
if (!toast) return;
setTimeout(() => {
toast.style.opacity = "0";
}, delay);
setTimeout(() => {
toast.remove();
toast = null;
}, delay + 500);
}
// ── Core ──
async function getUnsaveLinks() {
return $("a")
.filter(function () {
return $(this).text().toLowerCase() === "unsave";
})
.toArray();
}
async function processLinks(links) {
for (let i = 0; i < links.length; i++) {
$(links[i]).click();
totalUnsaved++;
updateProgress(`⏳ Unsaving <b>${totalUnsaved}</b> / ${totalFound}`);
if (totalUnsaved % BATCH_SIZE === 0) {
updateProgress(
`⏸ Processed ${totalUnsaved} items, cooling down ${BATCH_BREAK / 1000}s…`,
);
await wait(BATCH_BREAK);
} else {
const delay =
Math.floor(Math.random() * (DELAY_MAX - DELAY_MIN + 1)) + DELAY_MIN;
await wait(delay);
}
}
}
async function scrollAndUnsave() {
let previousHeight = 0;
let sameHeightCount = 0;
updateProgress("🔍 Scanning saved list…");
while (true) {
const links = await getUnsaveLinks();
if (links.length === 0) break;
totalFound += links.length;
await processLinks(links);
window.scrollTo({ top: document.body.scrollHeight, behavior: "smooth" });
updateProgress("🔍 Scrolling for more…");
await wait(2000);
const currentHeight = document.body.scrollHeight;
if (currentHeight === previousHeight) {
sameHeightCount++;
if (sameHeightCount >= 3) break;
} else {
sameHeightCount = 0;
previousHeight = currentHeight;
}
}
updateProgress(`✅ Done! Unsaved <b>${totalUnsaved}</b> posts`);
GM_notification({
title: "Reddit Unsave",
text: `Done! Unsaved ${totalUnsaved} posts`,
timeout: 5000,
});
dismissToast(3000);
setTimeout(() => location.reload(), 4000);
}
GM_registerMenuCommand("Unsave All", () => {
if (typeof $ === "undefined") {
const s = document.createElement("script");
s.src = "https://code.jquery.com/jquery-3.6.0.min.js";
s.onload = () => scrollAndUnsave();
document.head.appendChild(s);
} else {
scrollAndUnsave();
}
});
})();