You can scrape any public Facebook post — reactions, comments, shares, view counts, media and author details — without a Facebook account, a session cookie, or a browser. This guide shows the manual approach, why it breaks, and the one-call method that takes about two seconds per post.
Short answer: send the post URL to the Facebook Post Scraper and read the structured JSON it returns. No login, no cookies, no browser automation.
Why scraping Facebook posts is harder than it looks
Facebook stopped being a scrapable HTML site years ago. Three things break naive scrapers:
1. The page you get is not the page you see. A logged-out request to a post URL usually returns a shell — a few kilobytes of markup with an empty <div id="mount"> and no post content. The real data arrives later over a separate GraphQL call the page makes to itself. If your scraper parses the first response, it parses nothing. Worse, it returns HTTP 200, so naive error handling reports success.
2. Every route is token-gated. Facebook's internal GraphQL endpoint requires an lsd token, a fb_dtsg token, and a doc ID that rotate constantly. You cannot hardcode them. They have to be minted from a live page load and replayed within their validity window.
3. Logged-out routes disappear without notice. Routes that worked last month return 404 today. Anything you build against a specific URL pattern has a short shelf life.
The usual answers — Puppeteer with a logged-in account, or buying session cookies — both fail commercially. A logged-in account scraping at volume gets checkpointed within hours, and cookie-based scraping means your data pipeline dies the moment that account is flagged.
The reliable approach: no account at all
The Facebook Post Scraper works entirely from public, logged-out data. It mints the tokens it needs per request, replays them against the right internal endpoint, and returns parsed JSON. Because it never authenticates, there is no account to ban and no cookie to expire.
Step 1 — Give it post URLs
{
"urls": [
{ "url": "https://www.facebook.com/apifytech/posts/pfbid0ABC123" },
{ "url": "https://www.facebook.com/watch/?v=1234567890" },
{ "url": "https://www.facebook.com/reel/625885050263599/" }
],
"maxConcurrency": 5
}
Posts, videos, reels and photo posts all work. Pass one URL or ten thousand.
Step 2 — Read the results
Each post comes back as one dataset record:
{
"post_id": "122150535824513880",
"type": "video",
"permalink_url": "https://www.facebook.com/reel/625885050263599/",
"owner_name": "El fútbol",
"thumbnail": "https://scontent.fdxb3-4.fna.fbcdn.net/...",
"statistics": {
"reaction_count": { "count": 1204, "is_empty": false },
"comment_count": 87,
"shares_count": 33,
"video_view_count": 41208
}
}
Note reaction_count.is_empty. Facebook returns a zero-valued object both when a post genuinely has no reactions and when it withholds the count. The is_empty flag is the only way to tell "zero" from "not disclosed" — treat a missing flag as unknown rather than as zero, or your engagement averages will be quietly wrong.
Posts that were deleted or made private return an explicit error instead of silent nulls:
{
"url": "https://www.facebook.com/apifytech/posts/deleted",
"data": { "permalink_url": "https://www.facebook.com/apifytech/posts/deleted" },
"error": "not found"
}
Calling it from your own code
The Apify API runs the scraper and returns the dataset in a single request.
cURL
curl -X POST "https://api.apify.com/v2/acts/mina_safwat~facebook-post-scraper-ppr/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \
-H "Content-Type: application/json" \
-d '{"urls":[{"url":"https://www.facebook.com/apifytech/posts/pfbid0ABC123"}]}'
Python
from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("mina_safwat/facebook-post-scraper-ppr").call(
run_input={"urls": [{"url": "https://www.facebook.com/apifytech/posts/pfbid0ABC123"}]}
)
for post in client.dataset(run["defaultDatasetId"]).iterate_items():
stats = post.get("statistics", {})
print(post["post_id"], stats.get("comment_count"), stats.get("shares_count"))
JavaScript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('mina_safwat/facebook-post-scraper-ppr').call({
urls: [{ url: 'https://www.facebook.com/apifytech/posts/pfbid0ABC123' }],
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
Results also export as JSON, CSV, Excel or XML from the Apify Console if you would rather not write code at all.
What it costs
Pricing is per post returned, and drops with your Apify plan: $0.009 per post on the free plan, $0.007 on Bronze, $0.005 on Silver, and $0.003 on Gold and above. Failed or deleted posts are not charged as results.
Scraping 10,000 posts costs roughly $30 on Gold — cheaper than a single hour of engineering time spent keeping a Puppeteer fleet alive.
Common use cases
- Competitor benchmarking. Track reactions, comments and shares across a rival's posts to see which formats actually land.
- Influencer verification. Check whether engagement on a creator's posts matches their claimed reach before you pay them.
- Ad creative research. Pull the top-performing organic posts in your niche and reverse-engineer what works.
- Brand monitoring. Watch engagement on posts that mention you and catch a problem while it is still small.
FAQ
Do I need a Facebook account to scrape posts?
No. This scraper reads only public, logged-out data. There is no account to create, no password to store, and no account that can be banned.
Is scraping public Facebook posts legal?
Scraping publicly accessible data is generally permitted in many jurisdictions, and courts in the US have repeatedly declined to treat public-web scraping as unauthorised access. That is not legal advice. You remain responsible for complying with Facebook's Terms of Service, with GDPR and similar laws where personal data is involved, and with the rules of your own jurisdiction. Do not scrape private posts or use the data to build profiles of private individuals.
Can it scrape comments too?
This scraper returns comment counts. For the comment text itself, use the Facebook Comments Scraper.
Can it scrape every post from a page rather than one URL at a time?
Yes — that is a different tool. Use the Facebook Profile/Page Scraper, which walks a page's whole timeline.
How fast is it?
Roughly two seconds per post, and it runs them concurrently. Ten thousand posts finish in well under an hour.
Why not just use the official Graph API?
The Graph API only returns posts from pages you administer, and requires app review for almost anything useful. For competitor and market research it is not an option.
Try it: Facebook Post Scraper on Apify Store — no login, no cookies, pay only for posts returned.
Top comments (0)