# How to Scrape Facebook in 2026 (Python, Node, curl) (https://www.socialcrawl.dev/blog/how-to-scrape-facebook-2026)
> Scrape Facebook Pages, posts, and the Ad Library without Graph API App Review: one GET request, cursor pagination, unified schema. Real endpoint, real response, honest on what the official API gates.
The fastest way to scrape public Facebook data in 2026 is a single GET request to a Facebook data API. No Meta app, no Graph API App Review, no Business Verification, no page access token that expires. Here is the whole thing:
```bash
curl "https://www.socialcrawl.dev/v1/facebook/profile/posts?url=https://www.facebook.com/nasa" \
-H "x-api-key: $SOCIALCRAWL_KEY"
```
That returns a page's recent posts in a unified schema: text, media, author, engagement, and timestamp, all normalized. The rest of this guide covers what the response looks like, how to paginate through a Page's timeline, how to reach profiles, posts, comments, and the Ad Library, how to handle errors, and the honest legal and access picture.
Facebook's official Graph API only reads Pages you manage; to read Pages you do
not own you need Page Public Content Access, which is gated behind Meta App
Review plus Business Verification and granted case by case. The working 2026
approach for public data is a third-party Facebook scraper API: `GET
/v1/facebook/profile/posts` takes a Page URL and one `x-api-key` header, costs
1 credit per page, and paginates with a `next_cursor`. A complete scraper fits
in about 40 lines of Python, and the free tier's 100 credits never expire.
**Stack:** Python 3.10+ · `requests` · a [SocialCrawl API key](/docs/quickstart) (free tier: 100 credits) · optionally `pandas` for CSV
---
## Why doesn't the official Facebook API give you this?
Meta's [Graph API](https://developers.facebook.com/docs/graph-api/) is the official interface, and for content you own it is excellent: read your own Page's posts, insights, and comments with a page access token. The problem is other people's Pages.
To read Pages your app does not manage, you need **Page Public Content Access (PPCA)**, a feature you request through Meta App Review. App Review requires a completed app, Business Verification, a documented use case, and a screencast, and PPCA specifically is granted case by case, mostly to established partners. For an individual developer or a small team that just wants public post data from a set of Pages, that is weeks of review with no guaranteed outcome.
Personal profiles are effectively off-limits: the Graph API exposes almost no third-party read access to a person's profile or their posts. And the [Ad Library API](https://www.facebook.com/ads/library/api/), while genuinely public, requires identity confirmation and is oriented toward ads about social issues, elections, and politics for full API results, so it does not cover general brand-ad research the way the web Ad Library does.
That leaves two routes for public Facebook data: drive a headless browser against Facebook's aggressively bot-defended front end yourself (login walls, rotating DOM, and checkpoints), or use a Facebook scraper API that maintains that collection layer and sells you a stable contract. This guide takes the second route.
## Is it legal to scrape Facebook?
Scraping publicly accessible pages has repeatedly survived legal challenge in US courts (the _hiQ v. LinkedIn_ line of cases), and reading public Facebook Page content sits on that precedent. That is not the whole story: Meta's Terms of Service prohibit automated collection without permission, post text and images carry copyright, and the personal data in posts and comments brings GDPR and CCPA obligations that depend on your jurisdiction and use case. Public Pages (brands, media, public figures) are a very different risk profile from private profiles and closed groups. Read our [legal and technical guide to social media scraping](/blog/social-media-scraping-legal-technical-guide) before you ship anything commercial, and talk to a lawyer if revenue depends on the answer. This section is a technical overview, not legal advice.
## Setup: one key, no Meta app
Install the only required dependency:
```bash
pip install requests
```
Get an API key at [socialcrawl.dev](https://www.socialcrawl.dev), then **Dashboard → API Keys**. New accounts get 100 free credits, most Facebook endpoints cost 1 credit per page, and credits never expire. Keep the key out of your source:
```bash
```
There is no Meta developer app, no App Review, and no access token to refresh. One header does it.
## Scraping a Facebook Page's posts
The endpoint is [`GET /v1/facebook/profile/posts`](/platforms/facebook/profile-posts). It takes one required parameter, `url` (the full Page URL), and paginates with `cursor`.
```python
API_KEY = os.environ["SOCIALCRAWL_API_KEY"]
BASE = "https://www.socialcrawl.dev/v1"
resp = requests.get(
f"{BASE}/facebook/profile/posts",
params={"url": "https://www.facebook.com/nasa"},
headers={"x-api-key": API_KEY},
timeout=30,
)
payload = resp.json()
```
Here is a real, trimmed response from that exact call (one item shown):
```json
{
"post": {
"id": "1578225093672861",
"url": "https://www.facebook.com/NASA/posts/pfbid02GyMo6ud...",
"content": {
"text": "To the skies 🚀\n\nAstronaut Anil Menon launched into space for the first time on July 14, 2026, lifting off from Baikonur Cosmodrome aboard a Soyuz spacecraft.",
"media_urls": "https://scontent-bos5-1.xx.fbcdn.net/v/t39.30808-6/747790293_...jpg"
},
"author": {
"display_name": "NASA - National Aeronautics and Space Administration"
},
"engagement": { "likes": 4316, "comments": 200 },
"flags": { "deleted": false },
"published_at": "2026-07-15T20:01:25.000Z",
"ext": { "author_id": "100044561550831" }
},
"computed": { "language": "en", "content_category": "other" }
}
```
The post shape is canonical: `content.text`, `content.media_urls`, `author.display_name`, `engagement.likes`, `engagement.comments`, `published_at` are the same field names you read on the [Instagram, YouTube, and Reddit](/platforms) post endpoints, so a parser you write here transfers unchanged. A few honest caveats about Facebook specifically: `engagement.shares` and `views` come back `null` on the list endpoint because the upstream does not expose those per post, and `author.username` is null for Pages that use a numeric ID rather than a vanity URL. The numeric Page ID is always in `ext.author_id`.
## Paginating through a Page's timeline
The response includes a `pagination` object with a `next_cursor` and a `has_more` flag. Pass the cursor back as the `cursor` query parameter, and stop when `has_more` is false.
```python
def scrape_page_posts(page_url: str, max_pages: int = 20) -> list[dict]:
"""Fetch a Facebook Page's posts, one page per credit."""
posts, cursor = [], None
for _ in range(max_pages):
params = {"url": page_url}
if cursor:
params["cursor"] = cursor # pass next_cursor back verbatim
resp = requests.get(
f"{BASE}/facebook/profile/posts",
params=params,
headers={"x-api-key": API_KEY},
timeout=30,
)
payload = resp.json()
if not payload.get("success"):
raise RuntimeError(payload["error"]["message"])
posts.extend(payload["data"]["items"])
page = payload.get("pagination", {})
cursor = page.get("next_cursor")
if not page.get("has_more"):
break
return posts
print(len(scrape_page_posts("https://www.facebook.com/nasa")), "posts")
```
## The same call in Node and curl
The endpoint, parameters, and envelope are identical across languages. Node:
```ts
const res = await fetch(
"https://www.socialcrawl.dev/v1/facebook/profile/posts?url=" +
encodeURIComponent("https://www.facebook.com/nasa"),
{ headers: { "x-api-key": process.env.SOCIALCRAWL_API_KEY! } },
);
const { data, pagination } = await res.json();
console.log(data.items.length, "posts, more:", pagination.has_more);
```
curl, for a quick check:
```bash
curl "https://www.socialcrawl.dev/v1/facebook/profile?url=https://www.facebook.com/nasa" \
-H "x-api-key: $SOCIALCRAWL_KEY"
```
That last one hits [`GET /v1/facebook/profile`](/platforms/facebook/profile), the Page profile endpoint, returning display name, avatar, bio, follower count, and page likes. In a live call it returned NASA's 28,000,000 followers and a `joined_at` of "March 4, 2009".
## Beyond posts: profiles, comments, and the Ad Library
Facebook is more than a timeline. The same key and envelope reach:
- **Page analytics in one call:** `GET /v1/facebook/profile/full` returns the profile, recent posts, and computed analytics (engagement rate, posting cadence, top post) for 5 credits.
- **Comments:** [`GET /v1/facebook/post/comments`](/platforms/facebook/post-comments) takes a post URL and returns the comment list, paginating the same way.
- **Ad Library:** the `adlibrary` endpoints search advertisers and pull a company's active ads without the identity-confirmation gate of Meta's own Ad Library API, useful for competitive ad research.
- **Marketplace and Events:** `marketplace/search` and `events/search` cover the commerce and events surfaces.
The full roster is on the [Facebook platform page](/platforms/facebook).
## Handling errors and rate limits
Failures use the same envelope with `success: false` and a typed error object. The types you will actually meet scraping Facebook:
| Error type | Status | What it means | Your move |
| ---------------------- | ------ | -------------------------------------- | ------------------------------------------- |
| `RESOURCE_NOT_FOUND` | 404 | Page removed, private, or URL typo'd | Skip it. Empty upstream refunds the credit. |
| `UPSTREAM_ERROR` | 502 | Facebook hiccuped | Retry with backoff; credit refunded. |
| `SERVICE_UNAVAILABLE` | 503 | Circuit breaker open | Honor the `Retry-After` header. |
| `CONCURRENCY_LIMIT` | 429 | More than 50 concurrent requests / key | Cap your worker pool below 50. |
| `INSUFFICIENT_CREDITS` | 402 | Balance below the call cost | Top up. |
Note what is not there: a queries-per-minute or daily quota. The only throughput constraint is 50 concurrent requests per key. And empty-upstream 404s, 502s, and 503s automatically refund the credit, so a retry wrapper does not double-spend. The full matrix is in the [error handling docs](/docs/errors).
## Scraping Facebook at scale: the credits math
The math is flat. The profile and posts endpoints are 1 credit per page; the all-in analytics endpoint is 5.
| Workload | Requests | Credits |
| ------------------------------------------ | -------- | ------- |
| One Page, first page of posts | 1 | 1 |
| One Page, 20 pages of posts | 20 | 20 |
| 100 Pages × profile + 5 pages of posts | 600 | 600 |
| 100 Pages, all-in analytics (5 cr each) | 100 | 500 |
The free tier's 100 credits cover the first rows. Past that, [pricing](/pricing) is pay-as-you-go and credits never expire: 2,500 credits is £15, and the Growth plan's 20,000 (£49) funds the 100-Page sweep many times over. Repeated requests for the same Page inside the cache window cost 0 credits, so iterative development is free. If you want brand mentions across Facebook and other platforms without writing code, the free [brand mention checker](/tools/brand-mention-checker) runs the same collection layer in your browser.
## Frequently asked questions
### How do I scrape Facebook without the Graph API?
Use a third-party Facebook API that runs the collection layer for you. `GET /v1/facebook/profile/posts` takes a Page URL and an `x-api-key` header and returns posts in a unified schema, with no Meta app, no App Review, and no Page Public Content Access approval. You paginate with the `next_cursor` and reach profiles, comments, and the Ad Library the same way.
### Is scraping Facebook legal?
Reading public Facebook Page content has meaningful precedent in its favor, but it depends on jurisdiction, data type, and access method, and Meta's Terms prohibit automated collection without permission. Post text and images carry copyright, and posts and comments contain personal data under GDPR and CCPA. Public Pages are a different risk profile from private profiles and groups. Check Meta's current terms and consult qualified counsel for commercial use. This is a technical overview, not legal advice.
### Can I scrape a personal Facebook profile?
The official Graph API exposes almost no third-party read access to a person's profile, and private profiles are not public data. This guide is about public Pages (brands, media, public figures) and public content like the Ad Library. Do not scrape private profiles; it is both a Terms violation and a legal risk.
### What is Page Public Content Access?
Page Public Content Access (PPCA) is the Graph API feature that lets an app read Pages it does not manage. It is gated behind Meta App Review plus Business Verification and granted case by case, mostly to established partners. A third-party Facebook API removes that gate for public Page data because it operates its own collection, not your Meta app.
### How much does it cost to scrape Facebook?
The profile and posts endpoints cost 1 credit per page, and the all-in analytics endpoint costs 5. New accounts get 100 credits that never expire, then pricing is pay-as-you-go from £15 for 2,500 credits. The official Graph API is free but gated behind App Review for other people's Pages, so third-party pricing is the practical number to budget against.
### Can I search the Facebook Ad Library by API?
Yes. The `adlibrary` endpoints search advertisers and return a company's active ads through the same `x-api-key`, without the identity-confirmation step and political-ad focus of Meta's own Ad Library API. It is aimed at competitive ad and creative research on public advertising.
### Does the same code scrape other platforms?
Almost. Facebook posts come back in the same canonical shape as Instagram, YouTube, TikTok, and Reddit posts (`content.text`, `author`, `engagement.likes`, `published_at`), so your parsing and export code transfers. The differences are the input parameter and the pagination token name per platform, both listed in the [pagination docs](/docs/pagination).
---
## Where to go from here
You now have a Facebook scraper that costs 1 credit per page and survives Facebook's front-end changes because maintaining that compatibility is the API's job, not yours. Next steps: browse the other endpoints on the [Facebook platform page](/platforms/facebook), read the [Facebook data API guide](/blog/facebook-data-api-2026) for the deeper reference, or compare providers in [best Facebook data APIs (2026)](/blog/best-facebook-data-apis-2026). Start with the free tier: [100 credits, no card](/pricing) is about a hundred pages of posts, more than enough to find out whether the data answers your question.