Skip to content

Instantly share code, notes, and snippets.

@renestalder
Last active July 8, 2025 04:22
Show Gist options
  • Save renestalder/c5b77635bfbec8f94d28 to your computer and use it in GitHub Desktop.
Save renestalder/c5b77635bfbec8f94d28 to your computer and use it in GitHub Desktop.
Unfollow all on Facebook

Facebook: Unfollow people and pages

See comments section for more up-to-date versions of the script. The original script is from 2014 and will not work as is.

  1. Open news feed preferences on your Facebook menu (browser)
  2. Click people or pages
  3. Scroll down (or click see more) until your full list is loaded
  4. Run the script in your browser console

Facebook will block this feature for you while you use it, depending on how much entities you try to unfollow. It automatically unblocks in a couple of hours and you will be able to continue.

var unfollowButtons = document.querySelectorAll('[data-followed="1"]'); for(var i=0;i<unfollowButtons.length;i++){ unfollowButtons[i].click(); } alert(unfollowButtons.length+' people are now unfollowed! ');
@PabloLN
Copy link

PabloLN commented Oct 14, 2021

Thank you very much everyone, you saved my profile from when I was a kid😅 (I used the translator) 🇧🇷
image

@MSPTW
Copy link

MSPTW commented Oct 14, 2021

Worked great for me... with over 1600 entries. Well done :)

@Homwer
Copy link

Homwer commented Oct 20, 2021

Works! Thanks a lot.
If you'r FB is in another language, remember to lookup [aria-label="Toggle to follow"] and replace Toggle to follow with whatever FB uses in your language.

This works for the german FB version:

var follows = document.querySelectorAll('div[aria-label="Einstellung für Abonnements"]');

@Emil23501
Copy link

Works! Thanks a lot. If you'r FB is in another language, remember to lookup [aria-label="Toggle to follow"] and replace Toggle to follow with whatever FB uses in your language.

This works for the german FB version:

var follows = document.querySelectorAll('div[aria-label="Einstellung für Abonnements"]');

Hi Homwer, now it works, thanks a lot!!

@Manon25
Copy link

Manon25 commented Oct 22, 2021

Hi Everyone, first comment on Github after reading this article https://slate.com/technology/2021/10/facebook-unfollow-everything-cease-desist.html and wishing to try this !

I've tried the last version here but as I was using Facebook in French, it was not working (and I couldn't find the words they are using in French to replace "Toggle to unfollow' as this is just an Icon with no text here...). But I found an easy solution for people like me ! I just turned Facebook in English (for the time of the completion of the task and then I will go back to my language. And It's working so far !
I hope this will change my life (a bit... :-) )

Thanks a lot to all of you !

@Emil23501
Copy link

Emil23501 commented Oct 22, 2021

Hi, it's me again 😄

Can anyone help me also to scroll down (and load new from me followed persons and pages) the window?

I tried this :

(function() { 'use strict'; var lastScrollHeight = 0; function autoScroll() { var sh = document.documentElement.scrollHeight; if (sh != lastScrollHeight) { lastScrollHeight = sh; document.documentElement.scrollTop = sh; } } window.setInterval(autoScroll, 100); })();

But it seems to work only with a normal page, not in this case, where we have a window hoovering over a page.

Thanks a lot.

@kkiyomi
Copy link

kkiyomi commented Oct 23, 2021

The previous scripts didn't work for me so i had to change it a bit

var follows = document.querySelectorAll('div[aria-label="More"]');
var delay = 600;

var i = 0;

function unfollow() {
    if (i == follows.length) {
        return;
    }


    follows[i].click()

    var menu = document.querySelectorAll('div:nth-child(2) > div:nth-child(2) > div:nth-child(1) > div:nth-child(1) > span:nth-child(1)[dir="auto"]');
    var checking = document.querySelectorAll('div:nth-child(2) > div:nth-child(2) > div:nth-child(1) > div:nth-child(2) > span:nth-child(1)')

    var remaining = ((follows.length - i) * delay / 1000).toFixed(2);


    if (checking.length != 0 && checking[0].textContent == "Stop seeing posts but stay friends.") {
        menu[0].click()
        console.log("Unfollowing", i + 1, "of", follows.length + ",", remaining + "s", "remaining…");
    } else {
        console.log("Skipping", i + 1, "of", follows.length + ",", remaining + "s", "remaining…");
    }

    var closing_menu = document.querySelectorAll('div.__fb-dark-mode > div')

    closing_menu[0].remove();

    i = i + 1;

    setTimeout(unfollow, delay);
}

@volkankaban
Copy link

volkankaban commented Oct 28, 2021

// Facebook unfollow all people, groups, and pages.
var follows = document.querySelectorAll('div[aria-label="Toggle to follow"]');
var delay = 500;
var i = 0;
function unfollow() {
if (i == follows.length) {
return;
}
var remaining = ((follows.length - i) * (delay+500) / 100).toFixed(0);
console.log(
'Unfollowing', i + 1, 'of', follows.length + ', ~', remaining + 's',
'remaining…');
follows[i].click();
i = i + 1;
setTimeout(unfollow, Math.floor(500 + Math.random() * delay * 1));
}
unfollow();

// AUTO SCROLL TO THE BOTTOM
scroll=window.setInterval(function(){window.scrollTo(0,document.body.scrollHeight);},2000);

@AKmatiAK
Copy link

thank u everyone!!! works, no more wasting time for fb

@Starboy-Xo
Copy link

// Facebook unfollow all people, groups, and pages.
var follows = document.querySelectorAll('div[aria-label="Toggle to follow"]');
var delay = 500;
var i = 0;
function unfollow() {
	if (i == follows.length) {
		console.log('Unfollowed All (', follows.length, ') Successfully.');
		return;
	}
	var remaining = ((follows.length - i) * (delay+500) / 100).toFixed(0);
	console.log(
	'Unfollowing', i + 1, 'of', follows.length + ', ~', remaining + 's',
	'remaining…');
	follows[i].click();
	i = i + 1;
	setTimeout(unfollow, Math.floor(500 + Math.random() * delay * 1));
}
unfollow();

@pravy-cinsky-prasopes
Copy link

pravy-cinsky-prasopes commented Nov 21, 2021

@AmmarSaleemG works flawlessly, right 14 hours ago ^_^

Same code for unfavorite (remove favorites):

  1. Settings & Privacy
  2. News Feed Preferences
  3. Manage Favorites
  4. Select "Favorites only" to remove your favorites
  5. paste code bellow to console (F12)

"edited" code of @AmmarSaleemG :

var favorites = document.querySelectorAll('div[aria-label="Toggle Favorites"]'); var delay = 500; var i = 0; function unfavorites() { if (i == favorites.length) { console.log('unfavoritesed All (', favorites.length, ') Successfully.'); return; } var remaining = ((favorites.length - i) * (delay+500) / 1000).toFixed(0); console.log( 'unfavoritesing', i + 1, 'of', favorites.length + ', ~', remaining + 's', 'remaining…'); favorites[i].click(); i = i + 1; setTimeout(unfavorites, Math.floor(500 + Math.random() * delay * 1)); } unfavorites();

@0bamo0
Copy link

0bamo0 commented Dec 21, 2021

if it doesn't work for someone , u should check that the aria-label of the unfollow button or anything is "Toggle to follow" if ur using facebook in another language it might change acordingly , so anyway , just insepect the button unfollow and replace the label

for me , im using Facebook in french and the script is this one
// Facebook unfollow all people, groups, and pages.
var follows = document.querySelectorAll('div[aria-label="Bouton pour s’abonner"]');
var delay = 500;
var i = 0;
function unfollow() {
if (i == follows.length) {
console.log('Unfollowed All (', follows.length, ') Successfully.');
return;
}
var remaining = ((follows.length - i) * (delay+500) / 100).toFixed(0);
console.log(
'Unfollowing', i + 1, 'of', follows.length + ', ~', remaining + 's',
'remaining…');
follows[i].click();
i = i + 1;
setTimeout(unfollow, Math.floor(500 + Math.random() * delay * 1));
}
unfollow();

Copy link

ghost commented Jan 13, 2022

Please help me anyone , i have too many following people on facebook , i want to unfollow everyone...please anyone make a video and give me link please....i dont know how to do that , please helppppppppppppp

Copy link

ghost commented Jan 13, 2022

Please help me anyone , i have too many following people on facebook , i want to unfollow everyone...please anyone make a video and give me link please....i dont know how to do that , please helppppppppppppp****__

@Zorono
Copy link

Zorono commented Feb 2, 2022

Those filthy pages got hidden only from https://www.facebook.com/pages/?category=liked but not https://www.facebook.com/{USER}/following which means they aren't really unfollowed (i don't know how but I feel this...)

@Zorono
Copy link

Zorono commented Feb 6, 2022

Oh never mind... that is Facebook's fault!!!! it is so buggy and full of security issues...

@Mywk
Copy link

Mywk commented Feb 9, 2022

Working as of 2022-02-09

Profile -> Top right corner -> Settings & privacy -> News Feed preferences -> Unfollow -> Scroll to the bottom to load everything

F12 and paste the following (if your page is not in English, change the "Toggle to follow" to the label in your language)

matches = document.querySelectorAll('div[aria-label="Toggle to follow"]');
matches.forEach(function(el) {
  el.click();
});

@mursman
Copy link

mursman commented May 8, 2022

Screenshot (73)

if you guys write some lines to automate this tiring process of unfollowing people not in my friendliest , it will be a life saver.

@mursman
Copy link

mursman commented May 8, 2022

@renestalder @AmmarSaleemG

@underlines
Copy link

underlines commented May 24, 2022

Unfollowing friends, pages and groups is only half of the story

I have a huuuuge list of People that I still follow, because whenever I sent a friend request that was not accepted, it still automatically followed that profile.

URL: https://www.facebook.com/{{your ID or name}}/following
Or navigating on Desktop: Open facebook.com > Top left: Click your own Name to open your own profile > Click the More Dropdown next to Posts, About, Likes

You now see a ton of people you follow, but which are NOT your friends, if some of your friend requests in the past were left unanswered. I found no way to unfollow them programmatically via javascript, because the unfollow button only appears dynamically after hovering over the profile.

And ideas?

fb problem

@mursman
Copy link

mursman commented May 26, 2022

Unfollowing friends, pages and groups is only half of the story

I have a huuuuge list of People that I still follow, because whenever I sent a friend request that was not accepted, it still automatically followed that profile.

URL: https://www.facebook.com/{{your ID or name}}/following Or navigating on Desktop: Open facebook.com > Top left: Click your own Name to open your own profile > Click the More Dropdown next to Posts, About, Likes

You now see a ton of people you follow, but which are NOT your friends, if some of your friend requests in the past were left unanswered. I found no way to unfollow them programmatically via javascript, because the unfollow button only appears dynamically after hovering over the profile.

And ideas?

fb problem

this is exactly my problem too...looking for a solution....maybe a kind programmer from here will write us a code or give us a magical elixir i hope

@victorlin
Copy link

These scripts run great. The only problem is, I noticed that the friends/pages/groups listed at Settings and Privacy > News Feed Preferences > Unfollow isn't actually everything. I unfollowed all groups on there to test, and there still seems to be many groups showing up in my news feed 😕

@Revenant4
Copy link

Dejar de seguir a amigos, páginas y grupos es solo la mitad de la historia

Tengo una lista enorme de personas que todavía sigo, porque cada vez que envié una solicitud de amistad que no fue aceptada, siguió automáticamente ese perfil.
**URL: ** https://www.facebook.com/{{tu ID o nombre}}/siguiendo O navegando en el escritorio: abre facebook.com > Arriba a la izquierda: haz clic en tu propio nombre para abrir tu propio perfil > Haz clic en el menú desplegable Más a continuación a Publicaciones, Acerca de, Me gusta
Ahora ves un montón de personas a las que sigues, pero que NO son tus amigos, si algunas de tus solicitudes de amistad en el pasado quedaron sin respuesta. No encontré ninguna forma de dejar de seguirlos programáticamente a través de javascript, porque el botón de dejar de seguir solo aparece dinámicamente después de pasar el mouse sobre el perfil.
¿Y las ideas?
problema fb

este es exactamente mi problema también... buscando una solución... tal vez un amable programador de aquí nos escriba un código o nos dé un elixir mágico, espero

Unfollowing friends, pages and groups is only half of the story

I have a huuuuge list of People that I still follow, because whenever I sent a friend request that was not accepted, it still automatically followed that profile.

URL: https://www.facebook.com/{{your ID or name}}/following Or navigating on Desktop: Open facebook.com > Top left: Click your own Name to open your own profile > Click the More Dropdown next to Posts, About, Likes

You now see a ton of people you follow, but which are NOT your friends, if some of your friend requests in the past were left unanswered. I found no way to unfollow them programmatically via javascript, because the unfollow button only appears dynamically after hovering over the profile.

And ideas?

fb problem

I am trying to find a solution. In my case I have 8k in a row and the only solution is to go to the friends>followed section and manually unfollow by hovering over the profile. I will look for a solution to create a method where it does it automatically.

@moinulmoin
Copy link

All of this works great!

@Hs293Go's commented version of @casey's masterful script from 2021-01-28 is missing the final unfollow();, and @chesterbr's randomization seems like a good idea, so here's an updated version integrating it all, with a few minor copy/readability edits. Please let me know if there are any typos.

To use this script:

  1. Navigate to facebook.com
  2. Down arrow > Settings and Privacy > News Feed Preferences > Unfollow
    (Use the drop-down filter to only select friends/pages/groups if you want)
  3. Scroll to the bottom of the list to load everything. If you have lots of friends, this will take a while.
  4. Open Developer Tools (Usually Cmd-Option-I or Ctrl-Option-I)
  5. Click Console
  6. Paste all of the following script into the Javascript console and press enter
    (The console might give you a warning and make you type something before letting you paste a script in. You should heed that warning and carefully read the following script to make sure it's safe. Never assume a random script you find on the internet is safe.)
  7. Watch as the script unfollows every person/page you've scrolled past!
// Get a list of elements that match selectors, i.e. "Toggle to follow" buttons. 
// Maintainers probably need to change the selector string for new FB versions

var follows = document.querySelectorAll('div[aria-label="Toggle to follow"]');

// If you want to make sure this script doesn't click on the wrong buttons, go
// to the Elements tab, press Ctrl-F, enter "Toggle to follow" in the search
// bar, then find the button that is highlighted

var delay = 1500;  // Delay between clicks to prevent being blocked by FB

var i = 0;  // Initialize a counter of unfollows

function unfollow() {
  // unfollow() calls itself recursively. If counter of unfollows reaches length
  // of friend list, stop
  if (i == follows.length) {
    return;
  }

  // Calculate remaining time based on the num. of friends not yet unfollowed
  var remaining = ((follows.length - i) * (delay+500) / 1000).toFixed(0);

  console.log(
      'Unfollowing', i + 1, 'of', follows.length + ', ~', remaining + 's',
      'remaining…');

  follows[i].click();  // Click!

  i = i + 1;  // Increment the counter of unfollows

  // Recursively call itself with a randomized delay of 500-2000ms to keep 
  // on unfollowing
  setTimeout(unfollow, Math.floor(500 + Math.random() * delay * 2));
}

// run the unfollow function
unfollow();

thanks

@boc-github-user
Copy link

@mursman @Revenant4 @victorlin I wrote a script that I think will solve your problem. Just make sure before you run it, you scroll down the list of followed pages as long as you can, in order for it to reach all the users. Here's the script (and yes, a human being typed it all up, sorta):

Only tested in Desktop Chrome and intended on the page: https://www.facebook.com/{username}/following

var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __generator = (this && this.__generator) || function (thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (_) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
};
var _this = this;
(function () { return __awaiter(_this, void 0, void 0, function () {
    var selectors, friends, i, friend, followBtn, likedBtn, error_1;
    var _a, _b;
    return __generator(this, function (_c) {
        switch (_c.label) {
            case 0:
                selectors = getSelectors();
                friends = document.querySelector(selectors.friendList).children;
                i = 0;
                _c.label = 1;
            case 1:
                if (!(i < friends.length)) return [3 /*break*/, 11];
                _c.label = 2;
            case 2:
                _c.trys.push([2, 9, , 10]);
                friend = friends[i];
                simulateMousedown(friend.querySelector("img"));
                return [4 /*yield*/, wait(1000)];
            case 3:
                _c.sent();
                followBtn = document.querySelector(selectors.followingBtn);
                likedBtn = document.querySelector(selectors.likedBtn);
                (_a = (followBtn || likedBtn)) === null || _a === void 0 ? void 0 : _a.click();
                return [4 /*yield*/, wait(200)];
            case 4:
                _c.sent();
                // Press "Unfollow" Option
                getUnfollowTab().click();
                return [4 /*yield*/, wait(100)];
            case 5:
                _c.sent();
                // Press "Unlike this page" if option exists
                (_b = getUnlikeThisPageSwitch()) === null || _b === void 0 ? void 0 : _b.click();
                return [4 /*yield*/, wait(100)];
            case 6:
                _c.sent();
                // Press Update
                document.querySelector(selectors.updateBtn).click();
                return [4 /*yield*/, wait(2000)];
            case 7:
                _c.sent();
                // Dismiss Dialog
                document.body.click();
                return [4 /*yield*/, wait(500)];
            case 8:
                _c.sent();
                return [3 /*break*/, 10];
            case 9:
                error_1 = _c.sent();
                console.error(error_1);
                return [3 /*break*/, 10];
            case 10:
                i++;
                return [3 /*break*/, 1];
            case 11: return [2 /*return*/];
        }
    });
}); })();
function wait(milliseconds) {
    return __awaiter(this, void 0, void 0, function () {
        return __generator(this, function (_a) {
            return [2 /*return*/, new Promise(function (resolve) {
                    setTimeout(function () {
                        resolve(null);
                    }, milliseconds);
                })];
        });
    });
}
function simulateMousedown(targetNode) {
    function triggerMouseEvent(targetNode, eventType) {
        var clickEvent = document.createEvent("MouseEvents");
        clickEvent.initEvent(eventType, true, true);
        targetNode.dispatchEvent(clickEvent);
    }
    ["mouseover", "mousedown"].forEach(function (eventType) {
        triggerMouseEvent(targetNode, eventType);
    });
}
function getSelectors() {
    return {
        friendList: "[class=\"alzwoclg jl2a5g8c o7bt71qk sl27f92c\"]",
        followingBtn: "[aria-label=\"Following\"]",
        likedBtn: "[aria-label=\"Liked\"]",
        updateBtn: "[aria-label=\"Update\"]"
    };
}
function getUnfollowTab() {
    var xpath = "//span[text()='Unfollow']";
    var matchingElement = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
    return matchingElement;
}
function getUnlikeThisPageSwitch() {
    var xpath = "//span[text()='Unlike this Page']";
    var matchingElement = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
    return matchingElement;
}

@mursman
Copy link

mursman commented Sep 1, 2022

var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator"throw"); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (
) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var _this = this;
(function () { return __awaiter(_this, void 0, void 0, function () {
var selectors, friends, i, friend, followBtn, likedBtn, error_1;
var _a, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
selectors = getSelectors();
friends = document.querySelector(selectors.friendList).children;
i = 0;
_c.label = 1;
case 1:
if (!(i < friends.length)) return [3 /break/, 11];
_c.label = 2;
case 2:
_c.trys.push([2, 9, , 10]);
friend = friends[i];
simulateMousedown(friend.querySelector("img"));
return [4 /yield/, wait(1000)];
case 3:
_c.sent();
followBtn = document.querySelector(selectors.followingBtn);
likedBtn = document.querySelector(selectors.likedBtn);
(_a = (followBtn || likedBtn)) === null || _a === void 0 ? void 0 : _a.click();
return [4 /yield/, wait(200)];
case 4:
_c.sent();
// Press "Unfollow" Option
getUnfollowTab().click();
return [4 /yield/, wait(100)];
case 5:
_c.sent();
// Press "Unlike this page" if option exists
(_b = getUnlikeThisPageSwitch()) === null || _b === void 0 ? void 0 : _b.click();
return [4 /yield/, wait(100)];
case 6:
_c.sent();
// Press Update
document.querySelector(selectors.updateBtn).click();
return [4 /yield/, wait(2000)];
case 7:
_c.sent();
// Dismiss Dialog
document.body.click();
return [4 /yield/, wait(500)];
case 8:
_c.sent();
return [3 /break/, 10];
case 9:
error_1 = _c.sent();
console.error(error_1);
return [3 /break/, 10];
case 10:
i++;
return [3 /break/, 1];
case 11: return [2 /return/];
}
});
}); })();
function wait(milliseconds) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /return/, new Promise(function (resolve) {
setTimeout(function () {
resolve(null);
}, milliseconds);
})];
});
});
}
function simulateMousedown(targetNode) {
function triggerMouseEvent(targetNode, eventType) {
var clickEvent = document.createEvent("MouseEvents");
clickEvent.initEvent(eventType, true, true);
targetNode.dispatchEvent(clickEvent);
}
["mouseover", "mousedown"].forEach(function (eventType) {
triggerMouseEvent(targetNode, eventType);
});
}
function getSelectors() {
return {
friendList: "[class="alzwoclg jl2a5g8c o7bt71qk sl27f92c"]",
followingBtn: "[aria-label="Following"]",
likedBtn: "[aria-label="Liked"]",
updateBtn: "[aria-label="Update"]"
};
}
function getUnfollowTab() {
var xpath = "//span[text()='Unfollow']";
var matchingElement = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
return matchingElement;
}
function getUnlikeThisPageSwitch() {
var xpath = "//span[text()='Unlike this Page']";
var matchingElement = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
return matchingElement;
}

thanks for the script. works well, amazing work. my suggestion is you can also fine-tune more to work more efficiently .

@boc-github-user
Copy link

@mursman Your welcome, always glad to help in any way I can.

@casey
Copy link

casey commented Sep 3, 2022

@BookOfCooks That's some crazy code! How did you write it?

@hoangkhanglun
Copy link

@mursman @Revenant4 @victorlin I wrote a script that I think will solve your problem. Just make sure before you run it, you scroll down the list of followed pages as long as you can, in order for it to reach all the users. Here's the script (and yes, a human being typed it all up, sorta):

Only tested in Desktop Chrome and intended on the page: https://www.facebook.com/{username}/following

var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __generator = (this && this.__generator) || function (thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (_) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
};
var _this = this;
(function () { return __awaiter(_this, void 0, void 0, function () {
    var selectors, friends, i, friend, followBtn, likedBtn, error_1;
    var _a, _b;
    return __generator(this, function (_c) {
        switch (_c.label) {
            case 0:
                selectors = getSelectors();
                friends = document.querySelector(selectors.friendList).children;
                i = 0;
                _c.label = 1;
            case 1:
                if (!(i < friends.length)) return [3 /*break*/, 11];
                _c.label = 2;
            case 2:
                _c.trys.push([2, 9, , 10]);
                friend = friends[i];
                simulateMousedown(friend.querySelector("img"));
                return [4 /*yield*/, wait(1000)];
            case 3:
                _c.sent();
                followBtn = document.querySelector(selectors.followingBtn);
                likedBtn = document.querySelector(selectors.likedBtn);
                (_a = (followBtn || likedBtn)) === null || _a === void 0 ? void 0 : _a.click();
                return [4 /*yield*/, wait(200)];
            case 4:
                _c.sent();
                // Press "Unfollow" Option
                getUnfollowTab().click();
                return [4 /*yield*/, wait(100)];
            case 5:
                _c.sent();
                // Press "Unlike this page" if option exists
                (_b = getUnlikeThisPageSwitch()) === null || _b === void 0 ? void 0 : _b.click();
                return [4 /*yield*/, wait(100)];
            case 6:
                _c.sent();
                // Press Update
                document.querySelector(selectors.updateBtn).click();
                return [4 /*yield*/, wait(2000)];
            case 7:
                _c.sent();
                // Dismiss Dialog
                document.body.click();
                return [4 /*yield*/, wait(500)];
            case 8:
                _c.sent();
                return [3 /*break*/, 10];
            case 9:
                error_1 = _c.sent();
                console.error(error_1);
                return [3 /*break*/, 10];
            case 10:
                i++;
                return [3 /*break*/, 1];
            case 11: return [2 /*return*/];
        }
    });
}); })();
function wait(milliseconds) {
    return __awaiter(this, void 0, void 0, function () {
        return __generator(this, function (_a) {
            return [2 /*return*/, new Promise(function (resolve) {
                    setTimeout(function () {
                        resolve(null);
                    }, milliseconds);
                })];
        });
    });
}
function simulateMousedown(targetNode) {
    function triggerMouseEvent(targetNode, eventType) {
        var clickEvent = document.createEvent("MouseEvents");
        clickEvent.initEvent(eventType, true, true);
        targetNode.dispatchEvent(clickEvent);
    }
    ["mouseover", "mousedown"].forEach(function (eventType) {
        triggerMouseEvent(targetNode, eventType);
    });
}
function getSelectors() {
    return {
        friendList: "[class=\"alzwoclg jl2a5g8c o7bt71qk sl27f92c\"]",
        followingBtn: "[aria-label=\"Following\"]",
        likedBtn: "[aria-label=\"Liked\"]",
        updateBtn: "[aria-label=\"Update\"]"
    };
}
function getUnfollowTab() {
    var xpath = "//span[text()='Unfollow']";
    var matchingElement = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
    return matchingElement;
}
function getUnlikeThisPageSwitch() {
    var xpath = "//span[text()='Unlike this Page']";
    var matchingElement = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
    return matchingElement;
}

Screenshot 2022-09-05 181832
Hi it seem your code wont work with me, or i missing something. Thank you

@boc-github-user
Copy link

@casey I wrote the script with typescript, then compiled into javascript in es5 (this make sure it runs on all browsers). Here's the script when compiled using esnext:

(async () => {
    var selectors = getSelectors();
    var pages = document.querySelector(selectors.pageList).parentElement.children;
    for (let i = 0; i < pages.length; i++) {
        try {
            // Mousedown on page (wait 500ms)
            const page = pages[i].firstChild.firstChild;
            console.log(page);
            simulateMousedown(page);
            await wait(1000);
            // Press "Liked" (wait 100s)
            document.body.querySelector(selectors.likedBtn).click();
            await wait(100);
            document.body.click();
        }
        catch (error) {
            console.error(error);
        }
    }
})();
function getSelectors() {
    return {
        pageList: `[class="bdao358l jg3vgc78 cgu29s5g lq84ybu9 hf30pyar om3e55n1"]`,
        likedBtn: `[aria-label="Liked"]`,
        moreActions: `[aria-label="More actions"]`,
        updateBtn: `[aria-label="Update"]`,
    };
}
function simulateMousedown(targetNode) {
    function triggerMouseEvent(targetNode, eventType) {
        var clickEvent = document.createEvent("MouseEvents");
        clickEvent.initEvent(eventType, true, true);
        targetNode.dispatchEvent(clickEvent);
    }
    ["mouseover", "mousedown"].forEach(function (eventType) {
        triggerMouseEvent(targetNode, eventType);
    });
}
function getFollowSettingsBtn() {
    var xpath = "//span[text()='Follow settings']";
    var matchingElement = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
    return matchingElement;
}
function getUnfollowTab() {
    var xpath = "//span[text()='Unfollow this Page']";
    var matchingElement = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
    return matchingElement;
}
async function wait(milliseconds) {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve(null);
        }, milliseconds);
    });
}

Much easier to understand...

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