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! ');
@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...

@boc-github-user
Copy link

boc-github-user commented Sep 5, 2022

@hoangkhanglun The problem is, the script searches for element by using the XPath text() selector (ex: //span[text()='Unlike this Page']). But on your side, facebook isn't in English, it's in... korean dialects (sorry, I have no idea)? Update your facebook settings to use English, then try again.

You can revert it back to your native language after the script finishes. Here's the instructions (even though google could easily provide that):

@kevindashgit
Copy link

this seems to work (even as a toggle)

document.querySelectorAll('[aria-label="Toggle to follow"]').forEach(i=>i.click())

@COFFEEHOLIC47
Copy link

My page is in English.

I entered [https://www.facebook.com/{USER}/following], then I pressed F12, click Console, it then popped up as follows (read link appears as follows):-

FB-unfollow everyone all at once

Then, I tried to enter

"document.querySelectorAll('[aria-label="Toggle to follow"]').forEach(i=>i.click())"

But still appears what shown as follows:-

FB2

I even tried every single comment mentioned above but none of it was unable to allow me to unfollow everyone, all at once.
It might take me hours if I have to unfollow everyone, one by one.

@boc-github-user
Copy link

@COFFEEHOLIC47 I wrote a comment 6 days ago to unfollow all users. What was the result?

@COFFEEHOLIC47
Copy link

Hi BookOfCooks,

It popped up

"
Promise {: TypeError: Cannot read properties of null (reading 'parentElement')
at :3:59
at …}"

@kevindashgit
Copy link

@COFFEEHOLIC47 gotta get to the place in facebook UI where you see the actual modal w/ the checkboxes that you would otherwise click each unfollow button - then right click and inspect one of the unfollow buttons - you might need to alter the selector.

@pgbnguyen
Copy link

image
This pop-up after run the scripts!
Really appreciate this masterpiece scripts would save times and lives! Thank you @BookOfCooks, hope you could release the update new scripts soon.
+100 Respect

@pgbnguyen
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;
}

@boc-github-user
Copy link

boc-github-user commented Sep 14, 2022

@COFFEEHOLIC47 @pgbnguyen @kevindashgit I wrote a new script that unlike pages/users (unfollow will take another script, hopefully someone else does it). To use it:

  1. Open Facebook > Open your profile (https://www.facebook.com/{username})
  2. On the right-hand side, click the "..." button > Activity Log
  3. Go to Connections > Pages, page likes and interests
  4. Scroll down as far down as you can (this ensures the script unlikes everything)

The benefit of using the Activity Log is you can unlike deleted/inactive pages, which you can't do in https://www.facebook.com/{username}/following

Then run this script (I can make it much more performant later):

(async () => {
    var logs = document.querySelectorAll(selectors().log);
    for (let i = 0; i < logs.length; i++) {
        try {
            const logElement = logs[i];
            logElement.querySelector(selectors().moreActions).click();
            await wait(1500);
            document
                .querySelector(selectors().unlikeBtn)
                .firstChild.firstChild.click();
            await wait(500);
            i--;
        }
        catch (error) {
            console.log(error);
        }
    }
})();
function selectors() {
    return {
        log: `[class="om3e55n1 jl2a5g8c alzwoclg"]`,
        moreActions: `[aria-label="Action options"]`,
        unlikeBtn: `[role="menu"] [class="alzwoclg cqf1kptm cgu29s5g om3e55n1"]`,
    };
}
function wait(milliseconds) {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve(null);
        }, milliseconds);
    });
}
//# sourceMappingURL=index.js.map

Happy Coding!

@zeeatsh
Copy link

zeeatsh commented Sep 16, 2022

image
This Keeping showing up what should I do?

@boc-github-user
Copy link

@zeeatsh Try the latest solution in this thread, and see if that helps you.

@zeeatsh
Copy link

zeeatsh commented Sep 17, 2022

@zeeatsh Try the latest solution in this thread, and see if that helps you.

AWESOME!!! it worked ... But What about unfollowing all the friends do you have any codes for that? ,,, and thank you for the latest solution

@boc-github-user
Copy link

boc-github-user commented Sep 18, 2022

@zeeatsh I'm glad the script worked for you. However, unfortunately, I see no way to unfollow/unfriend friends from the activity log. It may be possible from public profile page, but it would be a pain to create and maintain considering how Facebook CSS classes are minified. I mean, what is this?

Untitled

There's no gaurentee these classes will remain consistent for more than two days. I wrote a script for me that worked that day, two days later, everything is broken. Point being, this sort of task may have to be done with an application made by C# that uses Facebook APIs. Hopefully, someone creates that soon.

@COFFEEHOLIC47
Copy link

COFFEEHOLIC47 commented Sep 18, 2022

Hi BookOfCooks,

I did what your advice and it popped up "Promise {: undefined}", also appears as follows (read at the bottom on the right-hand corner):-

image

After I entered,

const promise1 = new Promise((resolve, reject) => {
resolve('Success!');
});

promise1.then((value) => {
console.log(value);
// expected output: "Success!"
});

it then became

Success!
Promise {: undefined}

But when I entered again what you provided to us, it came back same message, appears as follow:-

Promise {: undefined}

@boc-github-user
Copy link

@COFFEEHOLIC47 It's because you have no liked pages ("Nothing to show" is said in the screenshot). In other words, the script worked, it just didn't do anything because there's nothing to do. If you're trying to unfriend/unfollow friends (not pages), I don't have a working script for that, and as I told [zeeatsh] in my latest reply, I have no possible way of doing it with Javascript (at least, as far as I am aware of).

@cosmoshiki
Copy link

i run the script today, not working anymore, hope there will be updates soon

@boc-github-user
Copy link

@cosmoshiki did you try the latest solution in this thread?

@busonolsun
Copy link

busonolsun commented Nov 30, 2022

@cosmoshiki did you try the latest solution in this thread?

@boc-github-user
Is there a ready-made script that can currently unfollow all the "https://www.facebook.com/{username}/following" page?
I don't understand what the final solution is. For this reason, I cannot apply the last solution step.

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