Skip to content

Instantly share code, notes, and snippets.

@jcguu95
Last active July 8, 2025 15:31
Show Gist options
  • Select an option

  • Save jcguu95/41681b9b5deafe1ba6cbd1b7cc1f1af7 to your computer and use it in GitHub Desktop.

Select an option

Save jcguu95/41681b9b5deafe1ba6cbd1b7cc1f1af7 to your computer and use it in GitHub Desktop.
Remove Instagram Unfollowed Content
// ==UserScript==
// @name Remove Instagram Unfollowed Content
// @version 2024-03-02
// @author Jin-Cheng Guu
// @match https://www.instagram.com/*
// @description Remove unfollowed content from the instagram main page.
// ==/UserScript==
(function() {
let blacklist = [
// Remove all unfollowed content.
'Follow',
// Ban your favorite texts.
'your.acquaintance.id.1',
'your.acquaintance.id.2',
];
function findsBannedText (element) {
let blacklistedText = '';
let text = element.textContent.trim();
let bannedText = blacklist.find (x => (x === text));
if (bannedText) {
// console.log("Found banned text in node.", bannedText, element)
return bannedText;
}
// No banned text found so far; search through its children recursively.
let children = element.children;
if (children.length > 0) {
for (let i = 0; i < children.length; i++) {
bannedText = findsBannedText(children[i])
if (bannedText) {
// console.log("Found banned text in node. ", bannedText, children[i]);
return bannedText;
}
}
} else {
return false;
}
};
function removeChildren (node) {
// Remove all children of node.
console.log("Remove all children of the node: ", node)
let children = node.children;
for (let i = 0; i < children.length; i++) {
children[i].remove();
}
}
//
function getAll (element, tag) {
let result = [];
if (element.tagName === tag) {
result.push(element);
}
let children = element.children;
for (let i = 0; i < children.length; i++) {
result = result.concat(getAll(children[i], tag));
}
return result;
}
function cleanAll (tag) {
getAll(document.body, tag).forEach (
article => {
let bannedtext = findsBannedText(article);
if (bannedtext) {
console.log("handling node because of text: ", article, bannedtext);
// we do not remove the unwelcome node itself as that crashes the page.
removeChildren(article);
}})
}
// One-time Clean
cleanAll('ARTICLE'); // Remove posts.
cleanAll('LI'); // Remove stories.
// Clean after each click.
let waitLength = 500
document.onclick = function (event) {
setTimeout(() => { cleanAll('ARTICLE'); // Remove posts.
cleanAll('LI'); // Remove stories.
},
waitLength);
};
//
// Make observer that constantly check for new articles.
//
function makeObserver () {
let callback = (mutationList, observer) => {
for (const mutation of mutationList) {
if (mutation.type === "childList" &&
mutation.addedNodes.length > 0) {
let addedNode = mutation.addedNodes[0];
let bannedText = findsBannedText(addedNode);
if (addedNode.tagName === 'ARTICLE' && bannedText) {
console.log("Handling node because of text: ", addedNode, bannedText);
// We do not remove the unwelcome node itself as that crashes the page.
removeChildren(addedNode);
}
}
}
};
return new MutationObserver(callback);
}
let config = { attributes: true, childList: true, subtree: true };
let observer = makeObserver();
observer.observe(document.body, config);
// observer.disconnect();
})();
@chrome-cirrus
Copy link

chrome-cirrus commented Jul 8, 2025

Stopped working for me as well. I noticed I still get the 'Follow' text, but the script only seems to detect and remove the related article if I click in its area. I guess this is the 'one time clean' triggered by clicks doing its thing. But just scrolling through the feed the script never triggers on those articles. I do still see it knocking out suggested posts in the console as expected without interaction.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment