Facebook Posts Scraper - Page Posts, Photos & Reactions
Pricing
from $0.62 / 1,000 posts
Facebook Posts Scraper - Page Posts, Photos & Reactions
Facebook posts scraper for the recent public posts of a Facebook Page. Each post has the full text, exact posting time and permalink, every photo and video, and reaction, comment and share counts, plus the Page identity. Up to 20 posts per Page, 50 Pages per run. $0.65 per 1,000 posts.
Pricing
from $0.62 / 1,000 posts
Rating
0.0
(0)
Developer
Dami's Studio
Maintained by CommunityActor stats
0
Bookmarked
76
Total users
39
Monthly active users
4.2 hours
Issues response
10 hours ago
Last modified
Categories
Security
Limited permissionsShare
Facebook posts scraper for Page links or plain handles, recent public posts only, one row each: the full text, the exact posting time, the permalink, every photo and video, and the reaction, comment and share counts.
The ceiling is the thing to know first. A Page shows a signed-out visitor its 20 most recent posts, so 20 per Page is as deep as anyone reads it without logging in. This actor is built to go wide instead: 50 Pages in a run, newest posts from each, rather than a thousand posts from one Page.
| Input | Page links or handles, or links to single posts and videos, up to 50 per run |
| Output | One row per post: text, posting time, permalink, photos and videos with view counts, reactions by type, comments, shares, the top comment, links and hashtags in the text, Page identity |
| Ceiling | 20 posts per Page, newest first |
| Account needed | None |
| Price | $0.65 per 1,000 posts on the free plan, down to $0.62 on Business. The free plan's $5 a month covers about 7,500 |
🔍 What Facebook Posts Scraper does
For every Page you list, it returns the newest posts that Page shows the public, one row per post. They come back together, so 20 posts from a Page take about as long as 3. Paste the link of one post or video instead and you get that one post.
Reactions come back two ways. reactionsCount is the total, and topReactions breaks that same
total down by type, so you can see 3,356 likes against 3 angry without a second request.
The two date fields narrow that recent batch rather than reaching further back. On a Page that posts daily, asking for last quarter will correctly return nothing, and no post rows are charged.
📋 What data you get from each Facebook post
| What you get | Field |
|---|---|
| The post's id and permalink | postId, postUrl |
| The full text | text, textLength |
| When it was posted | time, timestamp |
| Reactions, by type, plus comments and shares | reactionsCount, topReactions, commentsCount, sharesCount |
| One column per reaction type | reactionLikeCount, reactionLoveCount, reactionCareCount, reactionHahaCount, reactionWowCount, reactionSadCount, reactionAngryCount |
| What kind of post it is | postType, isReel, isSponsored |
| Every photo and video, with alt text, and each photo's width and height | media, mediaCount |
| Views on a video, live viewers, and a link to the video file | videoViews, liveViewerCount, videoUrl |
| The outbound link on a link post, and the card's description, site and image | linkUrl, linkTitle, linkDescription, linkSource, linkImage |
| Links, hashtags and tagged accounts in the post text | textLinks, hashtags, taggedAccounts |
| The comment Facebook shows first: text, time, replies, likes, who wrote it | topComment |
| The original post when a Page reshares one: link, author, time | isReshare, sharedPost |
| Facebook's own captions on a video (optional) | captionsText, captionsLanguage |
| The Page it came from | pageName, pageId, pageUrl, pageHandle, pageIsVerified, pageFollowers, pageLikes, pageProfilePicture |
| The post's id for Facebook's reactions and comments | feedbackId |
| The Page or post link you asked for | inputUrl |
▶️ How to scrape Facebook posts
- Open Facebook Posts Scraper and click Try for free.
- Put your Pages into Facebook Page URLs, one per line.
- Set Posts per Page. Leave it at 20 unless you want fewer.
- Click Start.
- Download the dataset as JSON, CSV or Excel, or pull it from the Apify API.
Run it with empty input and you get one labelled sample row, which is not charged, so you can see the shape before you spend anything.
💰 How much does it cost to scrape Facebook posts?
$0.65 per 1,000 posts. That is the free plan's price; paid plans pay a little less: $0.64 on Starter, $0.63 on Scale and $0.62 on Business. On the free plan, the $5 Apify gives you each month covers about 7,500 posts.
You pay for posts that come back with data. The sample row, every diagnostic row, posts dropped by your date filters and the same Page listed twice are not charged, and neither is a Page that turns out to have no public posts. A post from its own link costs the same as any other post, and the captions box does not change the price.
📥 What you give it
{"startUrls": ["https://www.facebook.com/NASA", "BBCNews"],"resultsLimit": 20,"onlyPostsNewerThan": "7 days"}
| Field | Default | What it is |
|---|---|---|
startUrls | none | Page links, one per line. A bare handle like NASA works, and so does a profile.php?id= link. A link to one post (facebook.com/NASA/posts/...) or one video (.../videos/...) returns that post alone, billed as one post. A link to a single photo gets a free row, and share, reel and watch links are refused the same way. First 50 per run, and the same Page written two ways is read once. |
resultsLimit | empty, runs as 20 | Posts per Page, newest first. 1 to 20, and 20 is all a public Page carries. |
onlyPostsNewerThan | none | Drop posts older than this. A date (2026-08-01), a full timestamp, or a window like 7 days or 30 minutes. Dropped posts are never charged. Anything else, yesterday for one, stops the run before a Page is read and charges nothing for posts. |
onlyPostsOlderThan | none | The other end of the window, same formats and the same refusal. Use both together to pull one month. |
includeCaptions | off | Adds the text of Facebook's own captions, and their language, to video posts that have them. A captioned video takes a moment longer; videos without captions keep both columns empty. |
proxyUrls | none | Optional. One URL per line if you want the traffic to leave through servers you already pay for. |
📤 What you get back
A real row from a run on 24 October 2026. The post text is cut short, two links are trimmed, and the commenter's name and picture are left out here:
{"ok": true,"charged": true,"recordType": "post","inputUrl": "https://www.facebook.com/NASA","pageName": "NASA - National Aeronautics and Space Administration","pageId": "100044561550831","pageUrl": "https://www.facebook.com/NASA/","pageIsVerified": true,"pageFollowers": 28743583,"pageLikes": null,"postId": "1658860588942644","postUrl": "https://www.facebook.com/NASA/videos/1557618349384047/","text": "The aircraft lineup just keeps getting bigger. ✈️MAX POWER, a new aerospace expo, is set for Nov. 7-8 ...","textLength": 332,"time": "2026-10-16T19:37:44.000Z","timestamp": 1792179464,"reactionsCount": 2105,"topReactions": [{ "type": "Like", "count": 1878 },{ "type": "Love", "count": 178 },{ "type": "Care", "count": 25 },{ "type": "Wow", "count": 17 },{ "type": "Angry", "count": 3 },{ "type": "Haha", "count": 2 },{ "type": "Sad", "count": 2 }],"commentsCount": 82,"sharesCount": 180,"postType": "video","media": [{"type": "video","id": "1557618349384047","url": "https://www.facebook.com/NASA/videos/1557618349384047/","thumbnailUrl": "https://lookaside.fbsbx.com/...","durationMs": 17770,"style": "Video"}],"mediaCount": 1,"isReel": false,"isSponsored": false,"linkUrl": null,"linkTitle": null,"scrapedAt": "2026-10-24T22:54:42.475Z","videoViews": 119622,"liveViewerCount": 0,"videoUrl": "https://lookaside.fbsbx.com/...","linkDescription": null,"linkSource": null,"linkImage": null,"reactionLikeCount": 1878,"reactionLoveCount": 178,"reactionCareCount": 25,"reactionHahaCount": 2,"reactionWowCount": 17,"reactionSadCount": 2,"reactionAngryCount": 3,"textLinks": ["https://www.nasa.gov/maxpower/"],"hashtags": [],"taggedAccounts": [{ "name": "NASA's Kennedy Space Center", "id": "100053414617500", "url": "https://www.facebook.com/NASAKennedy/" }],"pageHandle": "NASA","feedbackId": "ZmVlZGJhY2s6MTY1ODg2MDU4ODk0MjY0NA==","isReshare": false,"sharedPost": null,"topComment": {"text": "I'm curious what it would look like and what it would be like to create an object in the near future ...","time": "2026-10-18T01:18:48.000Z","timestamp": 1792286328,"url": "https://www.facebook.com/NASA/videos/1557618349384047/?comment_id=2993136914359141","replyCount": 0,"likeCount": 2,"authorName": "...","authorUrl": null,"authorPicture": "..."},"captionsText": null,"captionsLanguage": null}
| Field | How to read it |
|---|---|
postId, postUrl | Your key, and the permalink. Reels come back as /reel/, videos as /videos/, ordinary posts as /posts/pfbid. |
text | The full message as posted, not a preview. Line breaks and emoji are kept exactly. On a reshare with nothing added, it holds the original post's text. |
time, timestamp | The real posting time in ISO and in epoch seconds, read from the post rather than from a "2 days ago" label. |
postType | video, photo, link or status. A post sharing an outside article is link, with linkUrl and linkTitle filled. |
media | Each photo or video with an id, a permalink, a thumbnail, the alt text Facebook holds for screen readers, durationMs on videos, and width and height of the full-size photo. |
videoViews, liveViewerCount | null on posts without a video. Views keep climbing while a video is live on the Page. |
videoUrl | The video file. It is a lookaside.fbsbx.com link that may not play if you paste it into a browser tab; fetch it from code. |
reactionLikeCount to reactionAngryCount | The same numbers as topReactions, one column each. A type with no reactions is 0; null only if Facebook's breakdown did not add up to the total. |
linkDescription, linkSource, linkImage | Filled on link posts. Facebook often leaves the description empty, so it can be null while the site and image are there. |
textLinks | The real addresses linked in the text, not Facebook's redirect links. |
taggedAccounts | Each account tagged in the text, with its name, id and link as Facebook prints them. |
topComment | The one comment Facebook shows under the post, or null. likeCount is Facebook's rounded figure, so 1.2K comes back as 1200. authorUrl is null when Facebook hides the profile link. |
isReshare, sharedPost | sharedPost holds the original's link, author and time when the Page reshared a post, else null. |
captionsText, captionsLanguage | Only with includeCaptions on, and only on videos with Facebook captions. Otherwise null. |
pageHandle | The Page's name in its link, NASA here. null for a Page known only by number. |
pageFollowers, pageLikes | Whichever of the two Facebook publishes on that Page. The other comes back null, which is honest rather than missing. |
sharesCount | null where the count is not published. |
| A post read from its own link | pageFollowers, pageLikes and pageIsVerified are null. A video read from its link has no sharesCount, and its time is the video's own publish time, which can be a few seconds before the post's. |
🧾 Reading the output
Three kinds of row can land in your dataset.
| Row | How to spot it | Billed |
|---|---|---|
| A post | ok: true and charged: true | yes |
| The sample row | _sample: true | no |
| A diagnostic | _diagnostic: true and an errorCode | no |
Filter on charged == true and you have your data. That flag is what separates real rows from the
sample and the diagnostics, not a receipt.
errorCode | What happened |
|---|---|
BAD_INPUT | That link could not be read as a Page or a post, or a date field held something that is not a date. Group, event, watch, share and single-photo links land here too. |
NOT_FOUND | No public Page or post at that link. |
NO_RESULTS | The Page came back but published no posts, or none inside your date window. A post link that showed no post, or a post outside the window, lands here too. |
NOT_SERVED | Facebook did not show this Page's posts on any of the four tries this run, or a linked post on either of its two. Re-run it later. Runs before 13 October 2026 wrote BLOCKED here. |
NETWORK | Facebook could not be reached. |
TIME_BUDGET | The run ran out of time before reaching that Page or link. |
PROXY_INPUT_ADJUSTED | A connection setting this actor does not use was dropped. The run carried on. |
CHARGE_ERROR | A billing event could not be recorded. Told to you rather than hidden. |
UNEXPECTED_ERROR | Anything else, with the message attached. |
A run ends as Succeeded unless something broke on our side. Running out of time before any post came back
gives TIME_BUDGET rows and an amber status. Only an UNEXPECTED_ERROR before the first post ends it as Failed.
One quirk of the Console's Overview table: it shows the Page and post columns, so the engagement counts and the media look missing there. Open the row itself or download the JSON and they are all present.
💡 What people use it for
- Pulling twenty Pages every morning and diffing on
postIdto see only what is new. - Reporting: reaction, comment and share counts land as plain numbers, so engagement rate is a spreadsheet formula rather than a cleaning job.
- Deciding what to publish by reading what a whole category of Pages posted this week, sorted by
reactionsCount. - Keeping an archive of a Page you own, permalinks and media links included, so the record survives a deleted post.
From a Page's week to what people said about it, in three steps:
- Run this on a Page with
onlyPostsNewerThanset to7 days. - Sort on
commentsCountand copy thepostUrlof the top posts. - Paste them into Facebook Comments Scraper and read the comments themselves.
🚧 What it does not do
- No deep history. Twenty posts per Page is the ceiling, and the date filters work inside those twenty. If you need last year, this is the wrong tool.
- Public Pages only. Private timelines, groups, events and anything behind a login come back as an uncharged diagnostic row.
- Age-restricted and country-restricted Pages show a signed-out visitor no timeline at all. Those return an uncharged row, and re-running will not change it.
- No comment threads and no reactor identities. You get the counts and the one comment Facebook shows under each post. The full threads are a separate actor, linked below.
- Pinned posts can be missing. Facebook leaves them out of the public timeline, so a Page whose newest content is pinned may show it lower down or not at all.
- Counts are a snapshot at read time and keep moving on a live post.
- Nothing is translated. The text comes back in the language it was written in.
- It is not an official Facebook tool. Dami's Studio is independent and is not affiliated with or endorsed by Facebook or Meta, or by any other company named on this page.
🧭 Which Facebook scraper do you need?
| If you want | Use |
|---|---|
| Recent posts from a Page | This one |
| The comments under a post you have the link for | Facebook Comments Scraper |
| Posts from a public group | Facebook Groups Scraper |
| Reels from a Page | Facebook Reels Scraper |
| The website, e-mail and phone on a Page | Facebook Page Contact Info Scraper |
| The ads a Page is running | Meta Ad Library Scraper |
| Recent posts from an Instagram account | Instagram Scraper |
❓ Questions people ask
Do I need a Facebook account to scrape posts?
No. You need no Facebook account of your own for public Pages.
Can I get more than 20 posts from one Page?
Not from a public Page. That is what it carries, and nothing in the input raises it.
Can I scrape a single Facebook post?
Yes. Put the post's link (facebook.com/<Page>/posts/...) or a video's link in Facebook Page URLs
and you get one row for that post, at the price of one post.
Why did a Page return nothing?
Either it publishes no posts, everything it has is outside your date window, or it is restricted to signed-in visitors. The diagnostic row says which.
Why do the numbers differ from what I see on Facebook?
Counts keep moving on a live post, and the row holds them as they were when it was read. If a post seems missing, open the Page in a private browser window: what a signed-out visitor sees there is what this actor reads.
Can I call it from code or connect it to an AI assistant?
The API tab has code for Python, JavaScript and the
CLI. MCP clients like Claude and ChatGPT use
https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/facebook-posts-scraper; coding assistants can load our
skill file. All
three bill your Apify account at the same price.
Is scraping Facebook legal?
This reads public Pages only, never private content. Results can still contain personal data, which GDPR and similar laws cover, so have a reason for collecting it. Apify's write-up on the legality of web scraping is a good starting point, and we are not lawyers.
🆘 If something breaks
Open the Issues tab on the actor page. Paste the Page link you used and the run ID, and the log is enough for us to see what happened.