Skip to content

Instantly share code, notes, and snippets.

@einarmagnus
Created December 1, 2023 22:13
Show Gist options
  • Save einarmagnus/b7c405614e53ad3583f1f235e99bcf24 to your computer and use it in GitHub Desktop.
Save einarmagnus/b7c405614e53ad3583f1f235e99bcf24 to your computer and use it in GitHub Desktop.
/*
Get a list of your Facebook friends and how many friends in common you have.
This works in Chrome, Edge, and Safari, and probably most other browsers too.
It should work in Firefox around xmas 2023 when they too have
the `:has()` selector working (annouced release date is 17th of Dec)
- DON'T RUN SCRIPTS LIKE THIS FROM PEOPLE YOU DON'T KNOW OR TRUST. only do this if you know me, or can read code.
- go to https://www.facebook.com/me/friends
- press F12 (maybe fn+F12 if you have a fancy laptop), or right-click the page and chose "inspect".
- say yes, to any warnings that may be displayed.
- choose the console tab of the developer tools (top, maybe hidden behind a ">>" button
- copy all the code and paste it in the console.
- if you want to test it, you can change the limit (row 74) to something like 100, to get a result quicker.
just increase it and run the script again to get all your friends.
- it will take a while, as facebook only loads 8 contacts at a time, but after a couple
of minutes or so depending on how many friends you have, you should see a table in the console
and have data copied to your clipboard that you can paste in coda or excel or google sheets or wherever.
*/
(async ({limit=Infinity, copy} = {}) => {
const $ = (a, b) => b ? a.querySelector(b) : document.querySelector(a);
const $$ = (a, b) => [...(b ? a.querySelectorAll(b) : document.querySelectorAll(a))];
const friendsUrl = /^https?:\/\/www\.facebook\.com\/(?:[\w.]+\/|profile.php\?id=\d+&sk=)friends\/?$/;
if (!friendsUrl.test(window.location.href)) {
alert("Wrong page for this script, redirecting...");
window.location = "/me/friends";
}
let parent = $("[href$=friends_mutual]");
while($$(parent, "[href$=friends_mutual]").length <= 1)
parent = parent.parentElement;
await new Promise((acc) => {
if ($$("[href$=photos_of]").length >= 1) {
// the phots section has loaded below the friends list
return acc();
}
let loadedFriends = 0;
const observer = new ResizeObserver(entries => {
const freshLoadedFriends = $$(parent, "a[href] img").length;
if (freshLoadedFriends === loadedFriends || freshLoadedFriends > limit) {
if (freshLoadedFriends === loadedFriends) {
console.log("All friends loaded!")
} else {
console.log("Limit reached!")
}
observer.disconnect();
return acc();
}
loadedFriends = freshLoadedFriends;
console.log(`${freshLoadedFriends} friends loaded`);
window.scrollTo(0, document.body.scrollHeight);
})
observer.observe($('body'))
});
const friends = $$(parent, ":scope > div")
.map(n => $$(n, "a:not(:has(img))").map(a => a.innerText))
.filter(([name, count]) => (name || count) !== undefined)
.map(([name, count]) => [name.trim(), parseInt(count??-1)])
.sort(([,a], [,b]) => b - a);
return {
friends,
csv: (separator=",") =>
friends.map(([name, count]) =>
`${name}${separator}${count === -1 ? "" : count}`
).join("\n"),
copy
};
})({limit: 5000, copy}).then(({friends, csv, copy}) => {
copy(csv('\t'));
console.table(friends);
console.log("data copied to clipboard")
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment