Node.js client for the GetSocialAPI Facebook Scraper API.
- Groups: resolve links, overview, paginated members
- Profiles: resolve links, About/contacts in raw GraphQL
- Connections: followers, followings, friends
- Raw responses — no transformations
- Automatic retries on 429/502/503, typed exceptions
- Zero dependencies — native
fetch(Node.js >= 18)
npm install getsocialapi-facebookimport { Client } from 'getsocialapi-facebook';
// Get your API key at https://getsocialapi.com/dashboard/
const client = new Client({ apiKey: 'gsa_live_...' }); // or set GETSOCIALAPI_FB_API_KEY
// Resolve any group link (slug, m.facebook, share/g) to a group_id
const group = await client.fb.resolve('https://www.facebook.com/groups/freegarden/');
const groupId = group.group_id;
// Profile links resolve the same way
const user = await client.fb.resolveProfile('https://www.facebook.com/nasa');
const userId = user.user_id;
// Group card
await client.fb.overview(groupId);
// Members: raw GraphQL pages (1st -> data.group, 2nd+ -> data.fetch__Group)
const page = await client.fb.members(groupId); // fixed page of 15 members
const cursor = page.data.group.group_member_profiles.page_info.end_cursor;
// Next page: pass page_info.end_cursor as `after`
await client.fb.members(groupId, cursor);Note: numeric ids above
Number.MAX_SAFE_INTEGER(2^53-1) lose precision in JS. Pass them as strings when in doubt.
Base URL: https://api.getsocialapi.com/fb — authenticate with the API key
from your dashboard.
new Client({ apiKey, baseUrl, timeout = 30, maxRetries = 3, fetchImpl })| Parameter | Default | Description |
|---|---|---|
apiKey |
env GETSOCIALAPI_FB_API_KEY |
your API key |
baseUrl |
API endpoint | override only for testing |
timeout |
30 |
per-request timeout, seconds |
maxRetries |
3 |
retries on 429/502/503/5xx and network errors |
fetchImpl |
native fetch |
inject a custom fetch for testing |
| Method | Route | Description |
|---|---|---|
resolve(url) |
GET /resolve |
group link → group_id (numeric id, slug, m.facebook, /share/g/…) |
resolveProfile(url) |
GET /resolve/profile |
profile link → user_id |
overview(groupId) |
GET /overview |
group card: name, visibility |
members(groupId, after = null) |
GET /api/v1/members |
raw GraphQL page of 15 (1st — data.group, 2nd+ — data.fetch__Group) |
groupPosts(groupId, after = null) |
GET /api/v1/group_posts |
group feed: page of 2–3 Story posts, cursor from group_feed.page_info.end_cursor |
contacts(userId) |
GET /api/v1/contacts |
profile About: raw GraphQL |
posts(userId, after = null) |
GET /api/v1/posts |
user timeline: page of ~100 posts (the fixed service maximum), cursor from timeline_feed_units.page_info.end_cursor |
feed({ userId, groupId, perPage, after }) |
GET /api/v1/feed |
unified user/group feed, small pages: perPage 3–20 (default 10) |
followers(userId, after = null) |
GET /api/v1/followers |
raw GraphQL full_profile_list |
followings(userId, after = null) |
GET /api/v1/followings |
same shape |
friends(userId, after = null) |
GET /api/v1/friends |
same shape |
Full request/response reference with live examples: getsocialapi.com/docs — API Reference / Facebook.
Every method returns one raw page. Pass the connection's
page_info.end_cursor as after while has_next_page is true.
| List | Page size (fixed) | Cursor source |
|---|---|---|
posts |
~100 posts — the service maximum, there is no count parameter |
data.profile.timeline_feed_units.page_info.end_cursor |
feed |
perPage 3–20 (default 10); a page may come back short — follow has_next_page |
same connection as the target: timeline_feed_units / group_feed page_info.end_cursor |
groupPosts |
2–3 Story posts (skip GroupsSectionHeaderUnit edges, dedupe by cache_id) |
data.group_address.group_feed.page_info.end_cursor |
members |
15 | data.(group / fetch__Group).group_member_profiles.page_info.end_cursor |
followers / followings / friends |
15 | …list_items.page_info.end_cursor |
Cursors are reusable and not bound to a session; a broken or foreign cursor
returns 400 Invalid Cursor — take end_cursor only from the connection's
page_info, never from node fields.
const posts = [];
let after = null;
for (;;) {
const page = await client.fb.posts(userId, after);
const tfu = page.data.profile.timeline_feed_units;
posts.push(...tfu.edges.map((e) => e.node));
const pi = tfu.page_info ?? {};
if (!pi.has_next_page || !pi.end_cursor) break;
after = pi.end_cursor;
}- members page 1 lives in
data.group, following pages indata.fetch__Group - connection lists:
can_see_follower_list: falsemeans the list is hidden by privacy settings (only the count is available)
| Exception | HTTP | Notes |
|---|---|---|
GetSocialFacebookError |
— | base class; also network errors |
BadRequestError |
400 | bad parameters |
APIKeyError |
401 | invalid key |
RateLimitError |
429 | .limit from the response |
UpstreamError |
502 | temporary upstream error — retried automatically |
ServiceUnavailableError |
503 | service overloaded — retried automatically |
All errors expose .status, .headers and .body of the failing response.
Only successful responses count against your quota. Plans and rate limits: getsocialapi.com/#pricing.
- Telegram: @getsocialapi
- Email: hello@getsocialapi.com
- Website: getsocialapi.com
- Documentation: getsocialapi.com/docs
- Status: getsocialapi.com/status
MIT