Skip to main content

How to export Facebook group members with pagination

· 3 min read
Product documentation and integration guides

Every Facebook group scraping task eventually hits the same wall: the member list is paginated in small pages, and naive collection loses people at the seams. This guide shows the exact protocol we use in production at GetSocialAPI — the same one the group members endpoint implements.

The endpoint​

GET /fb/members/all/{group_id}?after=<cursor>

One page holds a fixed batch of 15 members — the size is set by the upstream and there is no count knob. The response carries three things you care about:

  • data.group.new_member_list.edges[] — member nodes of this page
  • data.group.new_member_list.page_info.end_cursor — the cursor to the next page
  • data.group.new_member_list.page_info.has_next_page — your loop condition

To resolve a group from its URL (facebook.com/groups/800246542990860) use the resolve endpoint first, or pass the numeric id directly.

The walking loop​

from getsocialapi_facebook import Client

fb = Client(api_key="gsa_live_...").facebook

members, cursor = [], None
while True:
page = fb.members("800246542990860", after=cursor)
conn = page["data"]["group"]["new_member_list"]
members += [e["node"] for e in conn["edges"]]
if not conn["page_info"].get("has_next_page"):
break
cursor = conn["page_info"]["end_cursor"]

print(len(members), "members exported")

Three rules that make this loop lossless:

  1. Pass the cursor verbatim. end_cursor is a long base64 string; copy it as-is into after. Never try to decode or slice it — cursors are opaque and session-independent, but only whole.
  2. Loop on has_next_page, not on counting. Page size can wobble by one node at seam boundaries; the flag is the source of truth.
  3. Deduplicate by node id if you re-run the walk — Facebook occasionally reshuffles members between pages while you paginate (joins/leaves happen live).

What a member node looks like​

Each edge carries node.name, node.id, node.profile_picture and — for searchable lists — a node.subtitle with the city. Business accounts may include job_history entries.

Errors that matter​

HTTPMeaning
400 Invalid Cursoryou mangled or reused a cursor from another group — restart from page 1
404group id does not exist or the group is hidden
429you exceeded your plan RPS — back off for Retry-After seconds

Failed calls (everything except 200/404) are not billed — a safe property of the whole GetSocialAPI billing model.

Takeaways​

Full group export is a solved problem if you respect the cursor protocol: fixed pages, has_next_page as the loop condition, verbatim cursors, dedupe on re-runs. The Python walker above is ~10 lines and exports groups of any size. Open an account — the first 100 calls are free — and try it on your own group id.

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.