Facebook feed API: user timeline and group posts in one endpoint
Most feed integrations want the same thing: a stream of posts, in small pages, from either a profile or a group — without wiring two different pipelines. The unified feed endpoint does exactly that: one route, two targets.
One call, two targets
GET /fb/api/v1/feed?user_id=<id> # profile timeline
GET /fb/api/v1/feed?group_id=<id>&per_page=10 # group feed
Pass exactly one of user_id / group_id. Page size is per_page
(integer 3–20, default 10), and the cursor comes from
page_info.end_cursor of each page.
The two pagination behaviors
Profile timelines ask Facebook for exactly per_page posts. Two
honest quirks:
- Facebook sometimes returns a post or two more than requested. The service does not trim the response — trimming would silently lose posts at page seams, and per-page cursors do not exist upstream.
- Loop on
has_next_page, not on counting posts.
Group feeds are different: Facebook hard-caps its native page at
roughly two posts. The service stitches several native pages up to
per_page — which means up to two duplicate edges can appear at a
seam. Deduplicate by node.cache_id.
from getsocialapi_facebook import Client
fb = Client(api_key="gsa_live_...").facebook
posts, cursor, seen = [], None, set()
while True:
page = fb.feed(user_id="100053723115450", per_page=10, after=cursor)
conn = page["data"]["profile"]["timeline_feed_units"]
for e in conn["edges"]:
node = e["node"]
if node.get("cache_id") not in seen:
seen.add(node.get("cache_id"))
posts.append(node)
if not conn["page_info"].get("has_next_page"):
break
cursor = conn["page_info"]["end_cursor"]
The same walker works for a group — the connection just lives at
data.group_address.group_feed instead.
Example observations
The figures below are illustrative observations, not a reproducible benchmark or a performance guarantee. Response sizes, latency and coverage depend on the target and upstream availability. Before sizing a production export, record the date, endpoint, parameters, page count and deduplicated item count for your own test.
| Target | Latency | Page | Seam quality |
|---|---|---|---|
| Profile page 1 | ~2.5 s | exactly 10 posts + cursor | — |
| Profile page 2 | ~2.5 s | 10 posts | 0 duplicates, 0 lost |
| Group, per_page=10 | ~9 s | 10 Story posts | ≤2 dupes, dedupe by cache_id |
Errors worth handling
A broken or foreign cursor returns 400 Invalid Cursor — restart
from page 1 instead of retrying. Timeouts come back as 503 with
Retry-After: 2; cursors are session-independent, so a retry of the
same request after a timeout is always safe.
When to use which endpoint
feed— dashboards, monitoring, "latest N posts" widgets. Small pages, low latency, one code path for both targets.posts— bulk export of a full timeline. Pages of ~100 posts per request, fixed by the service.group_posts— group-only pipelines that want the raw native behavior without stitching.
All three share the same cursor protocol, so switching between them is a base-URL change, not a rewrite. Start with 100 free calls on getsocialapi.com.
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.