Cleaning Twitter by unfollowing, to reset your follows/following flow.
hack social media

Cleaning Twitter by unfollowing, to reset your follows/following flow.

Dabitch
Dabitch

Sometimes a Twitter cleanse is necessary, as the Twitter app has some odd bugs in it and acts up from time to time. It'll suddenly bury your close friends and only show you news articles. It'll unfollow close friends without telling you. Out of curiosity, I wanted to find out who the first person to follow me was, and who the first person that I followed was.

To figure this out, go to your Twitter profile page, and click either "following" or "followers", and then open your javascript console under "View > Developer > Javascript Console". Once there, copy and paste this little nugget and scroll back to the very first tweep who followed/you followed. While you are down there in the very last page of scrolling back, you may find your pals that you never see these days, and you can check their pages, "like" some of their tweets, reply to recent stuff, unfollow&follow and whatnot to coax twitter into showing you them more often.

var ScrollTimer;
window.onclick = function () { clearInterval(ScrollTimer) }
ScrollTimer = setInterval(()=> { scrollTo(0, document.body.scrollHeight);console.log(document.body.scrollHeight) }, 500);

This is fun, you may find that you've not seen or interacted with these people in a bit. Which brings me to the next fix that I have. Mass unfollowing those who don't follow you. This may seem a bit excessive, after all you are not the type who only wants to follow people who follow you, but in the case of my account @adland I do actually want to engage with my real audience and see what they say. And Adland was following almost 20K people! Ugh! What to do?

Same story, roll over to your twitter profile and "following", then open View > Developer > Javascript Console".
Then prepare to be rate limited if you follow as many as @adland does because this is what you'll paste in your window now. This script is from jalbam on Github and is called unfollow-non-followers-twitter.js.
Note that you can establish a limit for the unfollow actions performed (per cycle and also in total) by editing the 'MAXIMUM_UNFOLLOW_ACTIONS_PER_CYCLE' and 'MAXIMUM_UNFOLLOW_ACTIONS_TOTAL' variables and I recommend that you do so if you have a large account.

/*
	Unfollow (stop following) those people who are not following you back on Twitter (or unfollow everyone if desired).
	
	This will work for new Twitter web site code structure (it was changed from July 2019, causing other unfollow-scripts to stop working).
	
	Instructions:
	1) The code may need to be modified depending on the language of your Twitter web site:
		* For English language web site, no modification needed.
		* For Spanish language web site, remember to set the 'LANGUAGE' variable to "ES".
		* For another language, remember to set the 'LANGUAGE' variable to that language and modify the 'WORDS' object to add the words in that language.
	2) Optionally, you can edit the 'SKIP_USERS' array to insert those users that you do not want to unfollow (even if they are not following you back).
	3) If you want to follow everyone (except the users in 'SKIP_USERS'), including those who are following you, just set the 'UNFOLLOW_FOLLOWERS' variable to 'true'.
	4) You can set the milliseconds per cycle (each call to the 'performUnfollow' function) by modifying the 'MS_PER_CYCLE' variable.
	5) If desired, set a number to the 'MAXIMUM_UNFOLLOW_ACTIONS_PER_CYCLE' variable to establish a maximum of unfollow actions to perform for each cycle (each call to the 'performUnfollow' function). Set to null to have no limit.
	6) If desired, set a number to the 'MAXIMUM_UNFOLLOW_ACTIONS_TOTAL' variable to establish a maximum of unfollow actions to perform in total for all cycles (all calls to the 'performUnfollow' function). Set to null to have no limit.
	7) When the code is fine, on Twitter web site, go to the section where it shows all the people you are following (https://twitter.com/YOUR_USERNAME_HERE/following).
	8) Once there, open the JavaScript console (F12 key, normally), paste all the code there and press enter.
	9) Wait until you see it has finished. If something goes wrong or some users were not unfollowed, reload the page and repeat from the step 8 again.
	
	* Gist by Joan Alba Maldonado: https://gist.github.com/jalbam/d7678c32b6f029c602c0bfb2a72e0c26
*/


var LANGUAGE = "EN"; //NOTE: change it to use your language!
var WORDS =
{
	//English language:
	EN:
	{
		followsYouText: "Follows you", //Text that informs that follows you.
		followingButtonText: "Following", //Text of the "Following" button.
		confirmationButtonText: "Unfollow" //Text of the confirmation button. I am not totally sure.
	},
	//Spanish language:
	ES:
	{
		followsYouText: "Te sigue", //Text that informs that follows you.
		followingButtonText: "Siguiendo", //Text of the "Following" button.
		confirmationButtonText: "Dejar de seguir" //Text of the confirmation button. I am not totally sure.
	}
	//NOTE: if needed, add your language here...
}
var UNFOLLOW_FOLLOWERS = false; //If set to true, it will also remove followers (unless they are skipped).
var MS_PER_CYCLE = 10; //Milliseconds per cycle (each call to 'performUnfollow').
var MAXIMUM_UNFOLLOW_ACTIONS_PER_CYCLE = null; //Maximum of unfollow actions to perform, per cycle (each call to 'performUnfollow'). Set to 'null' to have no limit.
var MAXIMUM_UNFOLLOW_ACTIONS_TOTAL = null; //Maximum of unfollow actions to perform, in total (among all calls to 'performUnfollow'). Set to 'null' to have no limit.
var SKIP_USERS = //Users that we do not want to unfollow (even if they are not following you back):
[
	//Place the user names that you want to skip here (they will not be unfollowed):
	"user_name_to_skip_example_1",
	"user_name_to_skip_example_2",
	"user_name_to_skip_example_3"
];
SKIP_USERS.forEach(function(value, index) { SKIP_USERS[index] = value.toLowerCase(); }); //Transforms all the user names to lower case as it will be case insensitive.

var _UNFOLLOWED_TOTAL = 0; //Keeps the number of total unfollow actions performed. Read-only (do not modify).

//Function that unfollows non-followers on Twitter:
var performUnfollow = function(followsYouText, followingButtonText, confirmationButtonText, unfollowFollowers, maximumUnfollowActionsPerCycle, maximumUnfollowActionsTotal)
{
	var unfollowed = 0;
	followsYouText = followsYouText || WORDS.EN.followsYouText; //Text that informs that follows you.
	followingButtonText = followingButtonText || WORDS.EN.followingButtonText; //Text of the "Following" button.
	confirmationButtonText = confirmationButtonText || WORDS.EN.confirmationButtonText; //Text of the confirmation button.
	unfollowFollowers = typeof(unfollowFollowers) === "undefined" || unfollowFollowers === null ? UNFOLLOW_FOLLOWERS : unfollowFollowers;
	maximumUnfollowActionsTotal = maximumUnfollowActionsTotal === null || !isNaN(parseInt(maximumUnfollowActionsTotal)) ? maximumUnfollowActionsTotal : MAXIMUM_UNFOLLOW_ACTIONS_TOTAL || null;
	maximumUnfollowActionsTotal = !isNaN(parseInt(maximumUnfollowActionsTotal)) ? parseInt(maximumUnfollowActionsTotal) : null;
	maximumUnfollowActionsPerCycle = maximumUnfollowActionsPerCycle === null || !isNaN(parseInt(maximumUnfollowActionsPerCycle)) ? maximumUnfollowActionsPerCycle : MAXIMUM_UNFOLLOW_ACTIONS_PER_CYCLE || null;
	maximumUnfollowActionsPerCycle = !isNaN(parseInt(maximumUnfollowActionsPerCycle)) ? parseInt(maximumUnfollowActionsPerCycle) : null;
	
	//Looks through all the containers of each user:
	var totalLimitReached = false;
	var localLimitReached = false;
	var userContainers = document.querySelectorAll('[data-testid=UserCell]');
	Array.prototype.filter.call
	(
		userContainers,
		function(userContainer)
		{
			//If we have reached a limit previously, exits silently:
			if (totalLimitReached || localLimitReached) { return; }
			//If we have reached the maximum desired number of total unfollow actions, exits:
			else if (maximumUnfollowActionsTotal !== null && _UNFOLLOWED_TOTAL >= maximumUnfollowActionsTotal) { console.log("Exiting! Limit of unfollow actions in total reached: " + maximumUnfollowActionsTotal); totalLimitReached = true; return;  }
			//...otherwise, if we have reached the maximum desired number of local unfollow actions, exits:
			else if (maximumUnfollowActionsPerCycle !== null && unfollowed >= maximumUnfollowActionsPerCycle) { console.log("Exiting! Limit of unfollow actions per cycle reached: " + maximumUnfollowActionsPerCycle); localLimitReached = true; return;  }
			
			//Checks whether the user is following you:
			if (!unfollowFollowers)
			{
				var followsYou = false;
				Array.from(userContainer.querySelectorAll("*")).find
				(
					function(element)
					{
						if (element.textContent === followsYouText) { followsYou = true; }
					}
				);
			}
			else { followsYou = false; } //If we want to also unfollow followers, we consider it is not a follower.

			//If the user is not following you (or we also want to unfollow followers):
			if (!followsYou)
			{
				//Finds the user name and checks whether we want to skip this user or not:
				var skipUser = false;
				var userName = "";
				Array.from(userContainer.querySelectorAll("[href^='/']")).find
				(
					function (element)
					{
						if (skipUser) { return; }
						if (element.href.indexOf("search?q=") !== -1 || element.href.indexOf("/") === -1) { return; }
						userName = element.href.substring(element.href.lastIndexOf("/") + 1).toLowerCase();
						Array.from(element.querySelectorAll("*")).find
						(
							function (subElement)
							{
								if (subElement.textContent.toLowerCase() === "@" + userName)
								{
									if (SKIP_USERS.indexOf(userName) !== -1)
									{
										console.log("We want to skip: " + userName);
										skipUser = true;
									}
								}
							}
						);
					}
				);
				
				//If we do not want to skip the user:
				if (!skipUser)
				{
					//Finds the unfollow button:
					Array.from(userContainer.querySelectorAll('[role=button]')).find
					(
						function(element)
						{
							//If the unfollow button is found, clicks it:
							if (element.textContent === followingButtonText)
							{
								console.log("* Unfollowing: " + userName);
								element.click();
								unfollowed++;
								_UNFOLLOWED_TOTAL++;
							}
						}
					);
				}
			}
		}
	);
	
	//If there is a confirmation dialog, press it automatically:
	Array.from(document.querySelectorAll('[role=button]')).find //Finds the confirmation button.
	(
		function(element)
		{
			//If the confirmation button is found, clicks it:
			if (element.textContent === confirmationButtonText)
			{
				element.click();
			}
		}
	);
	
	return totalLimitReached ? null : unfollowed; //If the total limit has been reached, returns null. Otherwise, returns the number of unfollowed people.
}


//Scrolls and unfollows non-followers, constantly:
var scrollAndUnfollow = function()
{
	window.scrollTo(0, document.body.scrollHeight);
	var unfollowed = performUnfollow(WORDS[LANGUAGE].followsYouText, WORDS[LANGUAGE].followingButtonText, WORDS[LANGUAGE].confirmationButtonText, UNFOLLOW_FOLLOWERS, MAXIMUM_UNFOLLOW_ACTIONS_PER_CYCLE, MAXIMUM_UNFOLLOW_ACTIONS_TOTAL); //For English, you can try to call it without parameters.
	if (unfollowed !== null) { setTimeout(scrollAndUnfollow, MS_PER_CYCLE); }
	else { console.log("Total desired of unfollow actions performed!"); }
};
scrollAndUnfollow();

As you can see, it's easily tweakable to follow everyone, instead of unfollowing, if that is what you would like to achieve instead.

I ran this on @adland's account and unfollowed almost 5000 users who were not following adland, which was great because I had noticed a lot of spam and botlike behavior in my adland feed which was making it quite useless to me.

Encouraged by this, I pulled the same trick on my @dabitch account, and while the number of accounts I unfollowed was only a couple of hundred, it drastically changed my feed there as well. I had followed a lot of news sources, unfollowing them allowed for people to show up rather than "AP" or whathaveyou, making it much friendlier at once.
But then I also began to see complete strangers and obvious bot accounts. I checked their pages, they were following me, I was following them back, and their accounts were established years ago like 2009. Yet the accounts were obvious one-topic bots, or retweet bots, and the avatars, locations and names didn't look familiar to me at all. I wonder if people have had their accounts hijacked, or if there is a black market for accounts with enough followers to be sold to clear twitter-bot runners. 🤔

If you want to make a list of people who you follow, or who are not following you, Jalbam on Github made a bit of code for that too! Then you can copy the names and add to a list! Here's the code for that.

/*
	Show user names of people you are following on Twitter, being able to choose certain filters to skip some users (and even skip followers or non-followers).
	
	This will work for new Twitter web site code structure (it was changed from July 2019).
	
	Instructions:
	1) The code may need to be modified depending on the language of your Twitter web site:
		* For English language web site, no modification needed.
		* For Spanish language web site, remember to set the 'LANGUAGE' variable to "ES".
		* For another language, remember to set the 'LANGUAGE' variable to that language and modify the 'WORDS' object to add the words in that language.
	2) If you do not want to print information about whether the user is following you or not, set the 'PRINT_FOLLOW_INFORMATION' variable to false.
	3) Optionally, you can edit the 'SKIP_USERS' array to insert those users whose names you do not want to print.
	4) To skip (do not print) users who are following you, set the 'SKIP_FOLLOWERS' variable to true. Both 'SKIP_FOLLOWERS' and 'SKIP_NON_FOLLOWERS' variables cannot be set to true at the same time.
	5) To skip (do not print) users who are not following you, set the 'SKIP_NON_FOLLOWERS' variable to true. Both 'SKIP_FOLLOWERS' and 'SKIP_NON_FOLLOWERS' variables cannot be set to true at the same time.
	6) You can set the milliseconds per cycle (each call to the 'printUserNames' function) by modifying the 'MS_PER_CYCLE' variable.
	7) When the code is fine, on Twitter web site, go to the section where it shows all the people you are following (https://twitter.com/YOUR_USERNAME_HERE/following).
	8) Once there, open the JavaScript console (F12 key, normally), paste all the code there and press enter.
	9) Wait until you see it has finished. If something goes wrong or some users were not printed, reload the page and repeat from the step 8 again.
	
	* Gist by Joan Alba Maldonado: https://gist.github.com/jalbam/1546b944f5074efd20e5bc838ee138f5
*/


var LANGUAGE = "EN"; //NOTE: change it to use your language!
var WORDS =
{
	//English language:
	EN:
	{
		followsYouText: "Follows you" //Text that informs that follows you.
	},
	//Spanish language:
	ES:
	{
		followsYouText: "Te sigue" //Text that informs that follows you.
	}
	//NOTE: if needed, add your language here...
}
var MS_PER_CYCLE = 10; //Milliseconds per cycle (each call to 'printUserNames').
var PRINT_FOLLOW_INFORMATION = true; //Sets whether to also print information about whether the user follows you or not.
var SKIP_FOLLOWERS = false; //Defines whether to avoid printing user names of followers.
var SKIP_NON_FOLLOWERS = false; //Defines whether to avoid printing user names of non-followers.
var SKIP_USERS = //Users whose name we do not want to print:
[
	//Place the user names that you want to skip here (they will not be printed):
	"user_name_to_skip_example_1",
	"user_name_to_skip_example_2",
	"user_name_to_skip_example_3"
];
SKIP_USERS.forEach(function(value, index) { SKIP_USERS[index] = value.toLowerCase(); }); //Transforms all the user names to lower case as it will be case insensitive.

//Function that names of the users that you are following on Twitter:
var USERS_PRINTED = {}; //Object that will keep the user names printed already and information about whether they are following you or not.
var printUserNames = function(followsYouText, skipFollowers, skipNonFollowers, printFollowInformation)
{
	followsYouText = followsYouText || WORDS.EN.followsYouText; //Text that informs that follows you.
	skipFollowers = (skipFollowers === true || skipFollowers === false) ? skipFollowers : SKIP_FOLLOWERS;
	skipNonFollowers = (skipNonFollowers === true || skipNonFollowers === false) ? skipNonFollowers : SKIP_NON_FOLLOWERS;
	printFollowInformation = (printFollowInformation === true || printFollowInformation === false) ? printFollowInformation : PRINT_FOLLOW_INFORMATION;
	
	if (skipFollowers && skipNonFollowers) { console.log("You cannot skip printing everyone!"); return; }
	
	//Looks through all the containers of each user:
	var userContainers = document.querySelectorAll('[data-testid=UserCell]');
	Array.prototype.filter.call
	(
		userContainers,
		function(userContainer)
		{
			//Checks whether the user is following you:
			var followsYou = false;
			Array.from(userContainer.querySelectorAll("*")).find
			(
				function(element)
				{
					if (element.textContent === followsYouText) { followsYou = true; }
				}
			);

			if (followsYou && skipFollowers) { return; }
			else if (!followsYou && skipNonFollowers) { return; }

			//Finds the user name and checks whether we want to skip this user or not:
			var skipUser = false;
			var userName = "";
			Array.from(userContainer.querySelectorAll("[href^='/']")).find
			(
				function (element)
				{
					if (skipUser) { return; }
					if (element.href.indexOf("search?q=") !== -1 || element.href.indexOf("/") === -1) { return; }
					userName = element.href.substring(element.href.lastIndexOf("/") + 1).toLowerCase();
					Array.from(element.querySelectorAll("*")).find
					(
						function (subElement)
						{
							if (subElement.textContent.toLowerCase() === "@" + userName)
							{
								if (SKIP_USERS.indexOf(userName) !== -1)
								{
									skipUser = true;
								}
							}
						}
					);
				}
			);
			
			//If we do not want to skip the user:
			if (!skipUser)
			{
				//Prints the username:
				if (!USERS_PRINTED[userName])
				{
					console.log("* Username: " + userName + (PRINT_FOLLOW_INFORMATION ? (followsYou ? " follows you" : " does NOT follow you") : ""));
					USERS_PRINTED[userName] = { userName: userName, followsYou: followsYou };
				}
			}
		}
	);
}


//Scrolls and prints usernames, constantly:
var scrollAndShowUsernames = function()
{
	if (SKIP_FOLLOWERS && SKIP_NON_FOLLOWERS) { console.log("You cannot skip printing everyone!"); return; }
	window.scrollTo(0, document.body.scrollHeight);
	printUserNames(WORDS[LANGUAGE].followsYouText, SKIP_FOLLOWERS, SKIP_NON_FOLLOWERS, PRINT_FOLLOW_INFORMATION); //For English, you can try to call it without parameters.
	setTimeout(scrollAndShowUsernames, MS_PER_CYCLE);
};
scrollAndShowUsernames();