Scraping Facebook group posts: Story nodes, reactions, pagination
A Facebook group feed is not a flat list of posts. It mixes real posts with section headers ("New members", "Suggested for you") and promotions — and a naive collector happily saves the noise as content. Here is what the group posts endpoint actually returns and how to walk it.
The endpoint and its shape
GET /fb/api/v1/group_posts/{group_id}?after=<cursor>
The payload lives at data.group_address.group_feed:
edges[]— mixed units; filter bynode.__typenamepage_info.end_cursor— the cursor (~550 chars, base64)page_info.has_next_page— loop condition
__typename values that matter:
| Value | Meaning | Action |
|---|---|---|
Story | an actual post | keep |
GroupsSectionHeaderUnit | section divider | skip |
QuickPromotionNativeTemplateFeedUnit | native promo | skip |
Every Story node carries cache_id (dedupe key), the author,
message text, attachment, reaction and comment counters, and timestamps.
The walker
from getsocialapi_facebook import Client
fb = Client(api_key="gsa_live_...").facebook
posts, cursor, seen = [], None, set()
while True:
page = fb.group_posts("800246542990860", after=cursor)
feed = page["data"]["group_address"]["group_feed"]
for e in feed["edges"]:
n = e["node"]
if n.get("__typename") == "Story" and n.get("cache_id") not in seen:
seen.add(n.get("cache_id"))
posts.append(n)
if not feed["page_info"].get("has_next_page"):
break
cursor = feed["page_info"]["end_cursor"]
print(len(posts), "posts collected")
Per-page reality
Facebook serves its native group page in chunks of 2–3 Story
posts — that is upstream behavior, not an API limitation. One
request = one chunk; a 100-post group costs ~40 requests. Latency per
page is ~3 seconds. If that cadence does not fit your use case, the
unified feed endpoint stitches chunks
server-side up to per_page=20 at the cost of occasional seam
duplicates.
Cursor rules
- Take
end_cursoronly frompage_info— nodes contain internal cursor fields that look identical and produceInvalid Cursorerrors. - Pass it verbatim as
after; never decode or slice it. - Cursors are reusable and session-independent — safe to checkpoint long exports.
A broken cursor returns 400 Invalid Cursor (not billed) — restart the walk from page 1.
Enrich with members
Post collection answers "what"; the group members endpoint answers "who". Cross-referencing post authors against the member export catches lurkers (members who never post) and power posters (members dominating the feed) — the two lists every community manager wants.
Start on getsocialapi.com — 100 free calls cover a small group end to end.
Build with GetSocialAPI
Explore Facebook API for capabilities, pricing and integration examples. Create an account to start with 100 free calls, or follow the quickstart.