Facebook Posts Scraper - Page Posts, Photos & Reactions avatar

Facebook Posts Scraper - Page Posts, Photos & Reactions

Pricing

from $0.62 / 1,000 posts

Go to Apify Store
Facebook Posts Scraper - Page Posts, Photos & Reactions

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

Dami's Studio

Maintained by Community

Actor stats

0

Bookmarked

76

Total users

39

Monthly active users

4.2 hours

Issues response

10 hours ago

Last modified

Security

Limited permissions

Share

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.

InputPage links or handles, or links to single posts and videos, up to 50 per run
OutputOne 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
Ceiling20 posts per Page, newest first
Account neededNone
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 getField
The post's id and permalinkpostId, postUrl
The full texttext, textLength
When it was postedtime, timestamp
Reactions, by type, plus comments and sharesreactionsCount, topReactions, commentsCount, sharesCount
One column per reaction typereactionLikeCount, reactionLoveCount, reactionCareCount, reactionHahaCount, reactionWowCount, reactionSadCount, reactionAngryCount
What kind of post it ispostType, isReel, isSponsored
Every photo and video, with alt text, and each photo's width and heightmedia, mediaCount
Views on a video, live viewers, and a link to the video filevideoViews, liveViewerCount, videoUrl
The outbound link on a link post, and the card's description, site and imagelinkUrl, linkTitle, linkDescription, linkSource, linkImage
Links, hashtags and tagged accounts in the post texttextLinks, hashtags, taggedAccounts
The comment Facebook shows first: text, time, replies, likes, who wrote ittopComment
The original post when a Page reshares one: link, author, timeisReshare, sharedPost
Facebook's own captions on a video (optional)captionsText, captionsLanguage
The Page it came frompageName, pageId, pageUrl, pageHandle, pageIsVerified, pageFollowers, pageLikes, pageProfilePicture
The post's id for Facebook's reactions and commentsfeedbackId
The Page or post link you asked forinputUrl

▶️ How to scrape Facebook posts

  1. Open Facebook Posts Scraper and click Try for free.
  2. Put your Pages into Facebook Page URLs, one per line.
  3. Set Posts per Page. Leave it at 20 unless you want fewer.
  4. Click Start.
  5. 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"
}
FieldDefaultWhat it is
startUrlsnonePage 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.
resultsLimitempty, runs as 20Posts per Page, newest first. 1 to 20, and 20 is all a public Page carries.
onlyPostsNewerThannoneDrop 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.
onlyPostsOlderThannoneThe other end of the window, same formats and the same refusal. Use both together to pull one month.
includeCaptionsoffAdds 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.
proxyUrlsnoneOptional. 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
}
FieldHow to read it
postId, postUrlYour key, and the permalink. Reels come back as /reel/, videos as /videos/, ordinary posts as /posts/pfbid.
textThe 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, timestampThe real posting time in ISO and in epoch seconds, read from the post rather than from a "2 days ago" label.
postTypevideo, photo, link or status. A post sharing an outside article is link, with linkUrl and linkTitle filled.
mediaEach 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, liveViewerCountnull on posts without a video. Views keep climbing while a video is live on the Page.
videoUrlThe 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 reactionAngryCountThe 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, linkImageFilled on link posts. Facebook often leaves the description empty, so it can be null while the site and image are there.
textLinksThe real addresses linked in the text, not Facebook's redirect links.
taggedAccountsEach account tagged in the text, with its name, id and link as Facebook prints them.
topCommentThe 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, sharedPostsharedPost holds the original's link, author and time when the Page reshared a post, else null.
captionsText, captionsLanguageOnly with includeCaptions on, and only on videos with Facebook captions. Otherwise null.
pageHandleThe Page's name in its link, NASA here. null for a Page known only by number.
pageFollowers, pageLikesWhichever of the two Facebook publishes on that Page. The other comes back null, which is honest rather than missing.
sharesCountnull where the count is not published.
A post read from its own linkpageFollowers, 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.

RowHow to spot itBilled
A postok: true and charged: trueyes
The sample row_sample: trueno
A diagnostic_diagnostic: true and an errorCodeno

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.

errorCodeWhat happened
BAD_INPUTThat 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_FOUNDNo public Page or post at that link.
NO_RESULTSThe 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_SERVEDFacebook 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.
NETWORKFacebook could not be reached.
TIME_BUDGETThe run ran out of time before reaching that Page or link.
PROXY_INPUT_ADJUSTEDA connection setting this actor does not use was dropped. The run carried on.
CHARGE_ERRORA billing event could not be recorded. Told to you rather than hidden.
UNEXPECTED_ERRORAnything 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 postId to 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:

  1. Run this on a Page with onlyPostsNewerThan set to 7 days.
  2. Sort on commentsCount and copy the postUrl of the top posts.
  3. 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 wantUse
Recent posts from a PageThis one
The comments under a post you have the link forFacebook Comments Scraper
Posts from a public groupFacebook Groups Scraper
Reels from a PageFacebook Reels Scraper
The website, e-mail and phone on a PageFacebook Page Contact Info Scraper
The ads a Page is runningMeta Ad Library Scraper
Recent posts from an Instagram accountInstagram 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.

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.