Facebook group posts API
GET /api/v1/group_posts · GetSocialAPI
A group's post feed with cursor pagination (2–3 posts per page).
Request
| Parameter | In | Required | Description |
|---|---|---|---|
group_id | query | yes | Numeric group id |
after | query | no | Cursor from group_feed.page_info.end_cursor of the previous page; omit for the first page |
Response
The raw stitched GroupFeedCsrQuery payload (deep merge of JSONL chunks,
fields as-is): the group card plus group_feed-shaped sections with posts —
creation_time, message, actors, attachments — the same Story node schema
as the user timeline.
Response example — click to expand (abridged: one array item per array, long strings trimmed)
{
"data": {
"group_address": {
"group_feed": {
"edges": [
{
"node": {
"__typename": "GroupsSectionHeaderUnit",
"id": "61595704804288:800246542990860,ranked_posts:FBEntGroupsSectionHeaderStory:a:0:{}:::::6",
"title": {
"text": "Most relevant"
}
}
},
{
"node": {
"__typename": "Story",
"strong_id__": "-778317998239886270",
"cache_id": "-778317998239886270",
"id": "UzpfSTYxNTU4NzA0NDE2NjgwOlZLOjExMjI3Nzk3ODc0MDQxOTk=",
"actors": [
{
"__typename": "User",
"strong_id__": "61558704416680",
"id": "61558704416680",
"friendship_status": "CAN_REQUEST",
"gender": "FEMALE",
"name": "Karen Tatiana",
"profile_picture": "…",
"story_bucket": "…",
"is_additional_profile_plus": false,
"delegate_page": null,
"is_work_user": false,
"work_foreign_entity_info": null,
"work_info": null,
"is_verified": false,
"subscribe_status": "CANNOT_SUBSCRIBE",
"secondary_subscribe_status": "REGULAR_FOLLOW",
"short_name": "Karen",
"is_favorite": false,
"is_page_or_profile_plus_actor": false,
"url": "https://m.facebook.com/karen.tatiana.843069/"
}
],
"creation_time": 1792954302,
"message": {
"text": "Busco elefante, lo cambio por el eagle o el flamenco, ambos nacieron con más de 3 m, o doy los dos por un elefante de 2 …",
"ranges": [],
"delight_ranges": [],
"image_ranges": []
},
"attachments": [
{
"action_links": [],
"style_infos": [
"…"
],
"title": "",
"subtitle": null,
"title_with_entities": "…",
"description": "…",
"url": "https://www.facebook.com/photo.php?fbid=122232363722290147&set=gm.1122779787404199&id=61558704416680",
"source": null,
"style_list": [
"photo"
],
"media_reference_token": "gm.1122779787404199",
"attachment_properties": [
"…"
],
"tracking": "{}",
"target": "…",
"associated_application": null,
"deduplication_key": "d1a944d37829ecc0fdd5ef3db791dbce",
"instagram_user": null,
"use_carousel_infinite_scroll": false,
"is_mute_music_ad": false,
"mimicry_data": null,
"thumbnail_in_footer_uri": null,
"media_bloks_data": "…",
"bloks_footer": "…",
"bloks_ad_extensions": null,
"bloks_vton_extensions": null,
"bloks_virtual_try_on_carousel": null,
"bloks_video_highlights": null,
"bloks_grid_carousel": null,
"bloks_watch_and_browse_video_end_scene": null,
"media": "…",
"subattachments": [],
"is_video_deep_links": false,
"poll_sticker": null
}
],
"feedback": {}
}
}
]
}
},
"page_info": {
"start_cursor": "Cg8TZXhpc3RpbmdfdW5pdF9jb3VudAIADwtyZWFsX2N1cnNvcgkAAAEZQVFIVFE3dHdFbUdHalZWN0lOLWVYV2tMOWtOQnNkZ0IyU1VoSnlTWWctcDUxREdXV1UtRUhBc0p2WU42NnJQRG1Fa2ZyTzBXa2VmSHNNZ3ZrcW03VjBUdUp5emZ6NFJCSDFGV1pfT0RfOU5lWHpYMlAwTEVEcWJzWmtUanRWSzN4WlhDSDg4RTdVbmFjZUdPTHFXVExOMzBNVF9FM3JGWk5XanJOcnBkMmM4cy10UXJwRl81aUc0ZXpMbmprUmdIQUEzODpleUl3SWpveE56a3lPVFUwTkRNM0xDSXhJam8zTmpneUxDSXpJam93TENJMElqb3hMQ0kxSWpvekxDSTJJam93TENJM0lqb3RNU3dpT0NJNkxURjkPE2hlYWRlcl9nbG9iYWxfY291bnQCAA8SbWFpbl9mZWVkX3Bvc2l0aW9uAgAPDWZlZWRfb3JkZXJpbmcPG3JhbmtlZF9pbnRlcmVzdF9jb21tdW5pdGllcw8TaXNfZXZlcmdyZWVuX2N1cnNvchEADyJpc19vZmZsaW5lX2FnZ3JlZ2F0ZWRfcG9zdHNfY3Vyc29yEQAPEmdyb3VwX2ZlZWRfdmVyc2lvbg8CVjIPEGRlbW90ZWRfcG9zdF9pZHMKAQE=",
"end_cursor": "Cg8TZXhpc3RpbmdfdW5pdF9jb3VudAIDDwtyZWFsX2N1cnNvcg+vQVFIVHhQbnJDNFZtT2JOVThJZDFLZWtLeHRWMGoyUkJVaWt1NnlFbERXdzZUZ1c1b2pwckxuUVR4UTA0YUpvTV94WF80QUZ0Z1ZBVXNrdDVpY2RJaXhpNGZ3OmV5SXdJam94TnpreU9UVTBORE0zTENJeElqbzNOamd5TENJeklqb3dMQ0kwSWpveExDSTFJam96TENJMklqb3dMQ0kzSWpvdE1Td2lPQ0k2TFRGOQ8TaGVhZGVyX2dsb2JhbF9jb3VudAIBDxJtYWluX2ZlZWRfcG9zaXRpb24CAw8NZmVlZF9vcmRlcmluZw8bcmFua2VkX2ludGVyZXN0X2NvbW11bml0aWVzDxNpc19ldmVyZ3JlZW5fY3Vyc29yEQAPImlzX29mZmxpbmVfYWdncmVnYXRlZF9wb3N0c19jdXJzb3IRAA8SZ3JvdXBfZmVlZF92ZXJzaW9uDwJWMg8QZGVtb3RlZF9wb3N0X2lkcwoBAQ==",
"has_next_page": true,
"has_previous_page": false
}
},
"label": "GroupFeedCsrPageInfo",
"path": [
"group_address",
"group_feed"
]
}
Top-level posts live in data.group_address.group_feed.edges[].node;
__typename: "Story" nodes are posts (a GroupsSectionHeaderUnit may
precede them). The response is valid JSON as delivered — the example above
is trimmed for readability only.
Python SDK: client.fb.group_posts(group_id); see
Facebook SDK.
Pagination
The feed is paginated with the same after scheme as the user timeline:
- Request without
after→ first page. - Take the cursor from
data.group_address.group_feed.page_info.end_cursor(~548-char base64 string) and pass it back asafterverbatim (URL-encoded, unmodified). - Repeat while
page_info.has_next_pageistrue;false— end of feed.
Posts are only the edges with node.__typename == "Story"
(2–3 posts per page); skip GroupsSectionHeaderUnit edges and dedupe by
node.cache_id as a safety net. Cursor properties: reusable, not bound to
a session/key, take end_cursor only from group_feed.page_info.
import time, urllib.parse
BASE, K = "https://api.getsocialapi.com/fb", {"X-API-Key": KEY}
after, posts = None, []
while True:
url = f"{BASE}/api/v1/group_posts?group_id={GID}"
if after:
url += "&after=" + urllib.parse.quote(after, safe="")
r = requests.get(url, headers=K, timeout=30)
r.raise_for_status()
gf = r.json()["data"]["group_address"]["group_feed"]
posts += [e["node"] for e in gf.get("edges") or []
if e.get("node", {}).get("__typename") == "Story"]
pi = gf.get("page_info") or {}
if not pi.get("has_next_page") or not pi.get("end_cursor"):
break
after = pi["end_cursor"]
time.sleep(1.0) # stay ≤1 request/sec per key
Python SDK: client.fb.group_posts(group_id, after=...) — one page per
call, after taken from group_feed.page_info.end_cursor.
Errors
| HTTP | Case |
|---|---|
400 + {{"error": "Invalid Cursor…"}} | broken/foreign after — take the cursor only from group_feed.page_info |
401 / 429 | see Rate limits |
502 | upstream Facebook error (after retries) |
503 | no live slots (Retry-After: 15) |
An empty or closed group returns HTTP 200 with edges: []; posts in closed
groups depend on the scraper token's membership.