Example: leaving a group
There are at least four requests before the actual "I want to leave" post request. Are they necessary?

Final request

POST /api/graphql/ HTTP/3
Host: www.facebook.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:134.0) Gecko/20100101 Firefox/134.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br, zstd
Content-Type: application/x-www-form-urlencoded
X-FB-Friendly-Name: GroupCometLeaveForumMutation
X-FB-LSD: RQtiK7BohbKu-I3JQXngZj
X-ASBD-ID: 129477
Content-Length: 1791
Origin: https://www.facebook.com
Alt-Used: www.facebook.com
Connection: keep-alive
Referer: https://www.facebook.com/groups/joins/?nav_source=tab
Cookie: datr=x5-CZ1nfaafafN8U5oqLu4; sb=x5-CZ0KafasfuGcr1tve-y; wd=840x561; locale=de_DE; c_user=52624124627; xs=42%3AW7AG8214ANA%3A2%3A1737130515%3A-1%3A13579%3A%3AAcUyi9fs52GqFC5wX_9-mq421Kys8QJphEJPnMg; fr=0MUA9U412RQs.AWW24d5h0PVy4ywpGqzqpC8IDtw.BnioIe..AAA.0.0.BnkPOY.A412cVm9tJM; m_pixel_ratio=1; x-referer=eyJyIjoiL2hvbWUuc124412ob21lLnBocCIsInMiOiJtIn0%3D; usida=eyJ2ZXIiOjEsImlkIjo412142NDE2M2NleDAiLCJ0aW1lIjoxNzI0MTU2ODI0fQ%3D%3D; presence=C%7B%22t3%22%3A%5B%5D%2C%22utc3%22%3A1737555514576%2C%22v%22%3A1%7D; dpr=1.3333333333333333
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
Priority: u=0
Pragma: no-cache
Cache-Control: no-cache

Payload

av=522440627&__aaid=0&__user=526441227&__a=1&__req=1c&__hs=20110.HYP%3Acomet_pkg.2.1.0.0.1&dpr=2&__ccg=EXCELLENT&__rev=101941858&__s=1vlc08%3Atddvry%3Adtxxnq&__hsi=7462744014955461116&__dyn=7xeXzWK4124xt0mUyEqxemh0noeEb8nwgUao5-ewSwAyUco2qwJyE1412OwpUe8hwaG0Z82_CxS320qa321Rwwwqo462mcw5Mx62G5Usw9m1YwBgK7o6C0Mo4G1hx-3m1mzXw8W58jwGzEaE5e3ym2SU4i5o7G4-5pUfEe88o4Wm7-2K0-obXCwLyESE2KwkQ0z8c86-bwHwKG4UrwFg2fwxyo6J0qo4e16wWzUfHDzUiwRK6E4-mEbUaUaE2Tw&__csr=g_14PT4myErkQjiRMFvk9Rkl9thkYjOjiIWHYBqnq9lfdjtfT8LZv9lOQzHaZOHBb-RydHcy4tblBHhrgx5RjCAjZrFaCBx1997DDzq_HAQBy-jy98xXl1412y9oSnKazpEswxKAexmml92UGfCxaA6ECEozGyqAGt4y9p89UiUSbAzkdx6cAxam2S9z8myoHBy8jwRgmolKEsKqEox2cz9Uiyolx28wUU4G6o-9wNG8DCzE42i5ECi9z8523LwqoC1AxSp0xwDwExi4EpwIwt8cE4y1sx5o2uxm0Co2-wjUfHwa7wXw9m0SA6U0NK1Pg4e0CE1jokwMwm83XwBp4A36QHodbaE04Me02iLw047fe0UU124A0pYE1LEugcE0_a1nw2sk0A82Mw11S04F8jglhDo0myw5Ig09JE0ewU0Vi1qw3PE34w1x61vw4YG0kW0iuvg0YmbBo&__comet_req=15&fb_dtsg=NAcNNQaku6pR7ScWSbYpvvF1AMsiSo3bY6c21FKa8qSENcuSHT77l5w%3A42%3A112430515&jazoest=25372&lsd=RQtiK7BohbKu-I3JQXngZj&__spin_r=101914218&__spin_b=trunk&__spin_t=1737555512&fb_api_caller_class=RelayModern&fb_api_req_friendly_name=GroupCometLeaveForumMutation&variables=%7B%22input%22%3A%7B%22attribution_id_v2%22%3A%22GroupsCometJoinsRoot.react%2Ccomet.groups.joins%2Cvia_cold_start%2C17375143291%2C880600%2C%2C%2C%22%2C%22group_id%22%3A%225142423557090%22%2C%22actor_id%22%3A%22526490627%22%2C%22client_mutation_id%22%3A%221%22%7D%2C%22inviteShortLinkKey%22%3Anull%2C%22isChainingRecommendationUnit%22%3Afalse%2C%22ordering%22%3A%5B%22viewer_added%22%5D%2C%22scale%22%3A2%2C%22groupID%22%3A%2250124623557090%22%2C%22__relay_internal__pv__GroupsCometGroupChatLazyLoadLastMessageSnippetrelayprovider%22%3Afalse%7D&server_timestamps=true&doc_id=900021443353444

Is it enough to replace the "groupID" in "variables" of the payload? Probably not. I would have to test it. No energy.

Log into Facebook

Log into Facebook to start sharing and connecting with your friends, family, and people you know.

Facebook
Replacing the ID didn't work. The response was the same as for the unedited request.

Let's compare two requests.

Headers stay the same. I feared "X-FB-LSD" or "X-ASBD-ID" would change.

Payload didn't change much either.

__req changed from "1k" to "1v"

__s from "7teaik:pjydzc:mc5q8x" to "dcinyc:pjydzc:mc5q8x" (only the first part changed)

__csr changed. After the first 14 characters.

I missed that there is "group_id" and "groupID" in variables. I will have to try changing both.

Last difference is within variables. client_mutation_id with "2" instead of "1".

Changing both group IDs resulted in a different response.

message: "A server error field_exception occured. Check server logs for details.", severity: "CRITICAL", code: 1665030

Setting "client_mutation_id" to "3" resulted in five errors in one response. Server is annoyed with my poking.

Comparing to a third request. Why did the header change: X-FB-Friendly-Name: useGroupLeaveMutation instead of GroupCometLeaveForumMutation. I guess in the backend those groups were not the same and one of the earlier requests tells the frontend what kind of group it is and what the user can do. Damn.

__req changed to "2g" (was 1v and 1k).

__s got first starting characters.

__csr changed completely. Not even the first characters are the same anymore. (Did I reload the page between the delete requests? I think so.

In "variables" there is now "action_source":"COMET_GROUP_PAGE".

"doc_id" changed. Probably related to "useGroupLeaveMutation".

Just took a look at the group. Some internal feedback group for group admins. Maybe that's the reason for some differences.

I compared another four requests. The client_mutation_id indeed is just client site counting how many groups one left while on the same page. Could be used serverside to compare if the amount is correct. __csr does not necessarily change between requests.

In the payload "group_id", "groupID" and "client_mutation_id" have to change. Those are easy. The other two are "__req" and "__s". I have no idea how those are created.

According to this blog post from three years ago where the messenger requests were inspected, they were present back then as well but weren't necessary for the requests. https://intuitiveexplanations.com/tech/messenger

Let's give it try without them.

Reverse engineering the Facebook Messenger API

It worked. You can Edit & Resend group removal requests and only replace "group_id" with the group you want to leave and "client_mutation_id" (+=1).

You don't need to bother changing "groupID" or anything else. Two hours wasted?

Just looked into a data export from last year. It contains group memberships, but not the group IDs. That's the json export. Could the html export contain more information like "go to online version of this group"?

Found three more json expors, but no HTML.

I guess, I will have to see, if I can get the IDs on the overview. I hate facebook html because of all the obfuscation they added.

I can get the URLs that contain IDs, but that's only about half of the groups in my test:
new Set([...document.querySelectorAll(`[href*=groups]`)].map(el => el.href).filter(url => url.search(/\d{10,20}/) > 1))

First working version. Use at your own risk. #FaceScrub

Leave all Facebook groups at once
1. Go to facebook.com/groups/joins/
2. Open the developer console, paste the code and execute it by pressing enter
3. Wait
4. Done.

5. Optional: Let me know how it went.

```javascript
let waitForElemToExist = async (selector) => {

const elem = document.querySelector(selector)
if (elem) return elem

return new Promise(resolve => {
const observer = new MutationObserver(() => {
const elem = document.querySelector(selector)
if (elem) {
resolve(elem)
observer.disconnect()
}
})

observer.observe(document.body, {
subtree: true,
childList: true,
})
})
}

let sleep = (ms) => {
return new Promise((resolve) => setTimeout(resolve, ms*1000))
}

let leave_groups = async () => {
// select groups with button
let groups = [...document.querySelectorAll(`[role="main"] > div [role="listitem"] > div [role="button"]`)]

// click button
for (const group of groups) {
group.click()
await waitForElemToExist('[role="menuitem"]')
_ = [...document.querySelectorAll('[role="menuitem"]')].slice(-1)[0].click()
await waitForElemToExist('[role="dialog"] [role="button"]')
_ = [...document.querySelectorAll('[role="dialog"] [role="button"]')].slice(-1)[0].click()
await (sleep(1))
}
}

leave_groups()
```

Facebook implemented an option to remove all your liked pages at once. No need to use a script for that.

1. Go to your profile
2. Click the button with the three dots on the right side below your cover photo
3. Click "Activity Log" in the overlay menu
4. On the new page, click "Pages, page likes and interests"
5. Scroll down so more pages get loaded.
6. Select "All" at the top left
7. Click "Remove on the right side at the same height as the "All" button
8. Repeat steps 5-7 until no new pages get loaded.

Not very reliable. Some things seem to not have been removed but clicking on the notification doesn't show them to me.

To make Facebook less annoying while I remove stuff, I use the userscript 'FB clean my feeds' https://greasyfork.org/en/scripts/431970-fb-clean-my-feeds-5-02.

The first 13 posts are spam (aka recommended content). Seems like the remaining 190 contacts and 12 groups either don't use FB that much or FB thinks the things that I am not interested in are more important.

FB - Clean my feeds (5.02)

Hide Sponsored and Suggested posts in FB's News Feed, Groups Feed, Watch Videos Feed and Marketplace Feed