Facebook Posts Scraper - Page Posts, No Login
Pricing
from $0.95 / 1,000 posts
Facebook Posts Scraper - Page Posts, No Login
Facebook posts scraper for public pages, no login: each page's posts newest first, back through its history or inside a date window. Rows carry text, date, reactions by type, comments, shares, video plays, photos, videos, links and page facts. CSV, Excel or API; pay per post and page.
Pricing
from $0.95 / 1,000 posts
Rating
0.0
(0)
Developer
Automation Craft
Maintained by CommunityActor stats
0
Bookmarked
3
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
Facebook Posts Scraper - Page Posts, No Login
Facebook posts scraper for public pages, with no login, no cookies and no Facebook account: give page URLs or page names and get each page's posts newest first, as many as you ask for, back through the page's history, or only the posts of a date window you choose. Every row carries the post's text, time, reactions by type, comments, shares, video plays and media links, with the page's name and its followers and category where Facebook shows them. Pay per post and per page read, posts from $0.95 per 1,000.
Built for brand and competitor tracking, news and media monitoring, social media reporting, research and AI data sets, and for scheduled runs in n8n, Make or Zapier. Name a memory and schedule the run: each run then delivers and bills only the posts it has not delivered before, and the stretches of each page's timeline it already read are skipped without a request. Rows carry what Facebook shows a visitor who is not logged in; use them under the rules that apply to you.
At a glance
- History and windows. Ask for the newest N posts of a page, back through its history, or for a date window with both ends (to the minute, UTC, or "7 days", "12 hours"). The window is applied by Facebook itself, so a window years back is reached in one call, at no extra charge.
- Page facts on every row: the page's name and verified badge, and its exact follower count and category whenever Facebook shows the page or its About tab, beside the page row itself.
- Reactions by type (like, love, care, haha, wow, sad, angry), comments, shares, video views and plays and the video's length, photos and videos with their links and alt text, link previews, events and shared posts.
- Each post billed once per run, and once per memory name across runs. A page that does not exist or is restricted is a free status row that keeps your input.
- A coverage row per page says how many posts were read, delivered and charged, and why the walk stopped.
Quick start
- Open the Actor and paste page URLs (
https://www.facebook.com/nike), page names (nike),profile.php?id=URLs or page ids into Facebook pages, up to 500 a run. Public figures' profiles work the same way. - Set Newest posts per page (the form starts at 10; 20 when the field is left out; up to 100,000). Add a date window if you like (Posted on or after, Posted on or before).
- Run, then download the rows from the Output tab (views Posts and Pages) as JSON, CSV or Excel, or read them through the API.
- For a monitor: give a Memory name and schedule the run (see "Monitor pages for new posts" below).
An empty input ({}) runs a sample: the 10 newest posts of the NASA page. It is a paid run like any other.
What you get
One post row per post (type: "post"). The fill rates count 448 distinct posts of 30 pages (news, brands, creators, public figures, institutions, a bakery) read in the final test runs of 2026-10-12.
| Field | What it holds | Filled |
|---|---|---|
postId, url, createdAt, createdAtUnix | The post's id, its link and its creation time (UTC) | 100% |
text | The post's text in full, line breaks kept | 98.4% (posts without text have none) |
hashtags, mentions | Hashtags in the text; tagged pages and people with id and link | 24.3%, 3.8% (where the text has them) |
postType | photo, album, video, reel, link, event, share, text or unavailable_attachment (an attachment Facebook no longer shows) | 100% |
reactionCount, reactions | All reactions, and each type (like, love, care, haha, wow, sad, angry); the types add up to the total on every post measured | 100% (a post without reactions has an empty breakdown) |
commentCount, shareCount | Comments and shares as Facebook counts them | 100% |
videoViewCount, videoPlayCount, videoDurationSeconds | On videos and reels | 100% of videos and reels |
media, mediaCount, mediaListed | Photos and videos: imageUrl, videoUrl (HD) and videoUrlSd, width, height, durationSeconds, altText (Facebook's own description, on 98% of photos) | 100% of photo, album, video and reel posts |
link | A link preview: url, title, description, domain, imageUrl | every link post |
event, sharedPost | An event post's event; a share's original post (id, link, author, text) | where present |
authorId, authorName, authorUrl | Who posted it | 100% |
pageId, pageName, pageUrl, pageUsername | The page on every row | 100% |
pageVerified | The page's verified badge | 99.8% |
pageFollowers, pageCategory | The page's exact follower count and category, when Facebook showed the page or its About tab; a page it showed only through its plugin has them empty (its page row carries the rounded count) | on 12 and 17 of the 112 page reads of the final runs (100 came through the plugin) |
storyId, feedbackId, input, scrapedAt | Facebook's own story and feedback ids, the input value that led to the row, the time of the run | 100% |
The page row
One page row per page read (type: "page", the Page event): pageId (the id the timeline uses), classicPageId, name, url, username, category, followers (exact, as the page shows it), talkingAbout, wereHere, verified, about (the page's own sentence), profilePictureUrl, input. When Facebook shows a visitor neither the page nor its About tab, the page row comes from the page's own plugin: name and verified badge, the category and picture when the plugin shows them (most often it does not), with Facebook's rounded follower count in followersRounded (for example 39,000,000 for "39M") and followers empty; the posts are read the same way. The same page given twice in one run (a name and an id) is read once; the second form gets a coverage row with stopReason: "already_read".
Coverage, status and summary rows (free)
- Coverage (
type: "coverage"), one per page:postsRead,postsDelivered,postsCharged,known(already in your memory),countedFromMemoryandstretchesSkipped(memory runs),repeated,newestPostAt,oldestPostAt,reachedEndOfTimeline,stopReason(max_posts_per_page,end_of_timeline,window_start_reached,page_not_available,max_posts,charge_limit,work_allowance,rate_limitedand others) andcomplete. - Status (
type: "status"):page_not_available(no public page at that address: it does not exist, was renamed, is private, or is restricted by age or country for logged out visitors),page_without_timeline,lookup_failed(a page that kept showing Facebook's login page on every exit tried, its About tab included, or a call that did not answer; run it again later),post_link_not_readandnot_a_page(links to single posts, reels, groups or events, named by their position in your list),invalid,skipped(pages not started because the run stopped),memory_free,memory_full. - Summary (
type: "summary"), the last row: every counter, the residential bytes per delivered post, the work allowance, the memory and the billing the platform confirmed.
Example post row
A photo post of the NASA page (text and image link shortened):
{"type": "post","postId": "1653935226101847","url": "https://www.facebook.com/NASA/posts/pfbid02xHAgShj5aCv1X8KBJp7eoryK9hMo9gnmCneQEKUjHhP1HVHiMAKwchRj2kdVnUful","createdAt": "2026-10-11T16:30:00.000Z","createdAtUnix": 1791736200,"text": "If you see this, the stars are smiling upon you today 😊\n\nWhile observing the universe, NASA's Hubble Space Telescope caught a galaxy cluster smiling for the camera. ...","hashtags": [],"mentions": [{"id": "100064496992557","name": null,"url": "https://www.facebook.com/NASAHubble","type": "profile"}],"postType": "photo","reactionCount": 2902,"reactions": {"like": 1989,"love": 794,"wow": 46,"care": 45,"haha": 27,"angry": 1},"commentCount": 133,"shareCount": 368,"videoViewCount": null,"videoPlayCount": null,"videoDurationSeconds": null,"media": [{"type": "photo","id": "1653935202768516","url": "https://www.facebook.com/photo/?fbid=1653935202768516&set=a.416661013162614","imageUrl": "https://scontent-dfw6-2.xx.fbcdn.net/v/t39.99422-6/840265965_..._n.png?...","videoUrl": null,"videoUrlSd": null,"width": 1280,"height": 1263,"durationSeconds": null,"altText": "May be an image of outer space"}],"mediaCount": 1,"mediaListed": 1,"link": null,"event": null,"sharedPost": null,"authorId": "100044561550831","authorName": "NASA - National Aeronautics and Space Administration","authorUrl": "https://www.facebook.com/NASA","pageId": "100044561550831","pageName": "NASA - National Aeronautics and Space Administration","pageUrl": "https://www.facebook.com/NASA/","pageUsername": "NASA","pageFollowers": 28717137,"pageCategory": "Government organization","pageVerified": true,"input": "https://www.facebook.com/NASA","scrapedAt": "2026-10-11T20:22:17.581Z"}
How deep it goes
Measured on Apify runs of 2026-10-11:
- 300 posts of one page in one run (a creator page, mostly videos and reels): 300 delivered, each once, in under 5 minutes. Facebook now and then serves a visitor a timeline that ends early; when it says the timeline ended before your number of posts, the Actor asks once more below the oldest post it read, through a fresh exit, and goes on if more posts come.
- Back in time in one call: a window ending on 2014-12-31 on a brand page returned the 20 newest posts posted on or before that day (December 2014 back to March 2013) at once, without reading the ten years in between.
- A date window: the last 3 days of a news page gave 101 posts, and the walk stopped at the window's start.
- The newest post is in the page itself: when Facebook serves the page, it carries the page's newest post, so a page read for its newest post only (a monitor of many pages) needs no timeline call, and a page whose newest post is older than your window costs none either. When Facebook serves only the page's About tab or its plugin (it often does to a visitor who is not logged in), the page row comes from there and one timeline call reads the newest posts.
- Memory: a second run with nothing new made no timeline request on a page Facebook showed itself (one on a page shown through its About tab or plugin); a deeper run skipped the remembered stretch and read on below it.
- Global pages: a global brand name that Facebook sends to a regional page (
nintendoto Nintendo of America) is read as that regional page, and the page row says which.
How much does it cost to scrape Facebook posts?
Pay per event: you pay for the posts and pages delivered, never for a page that does not exist, a call that failed, a repeat or a post your memory already holds.
| Event | Free | Bronze | Silver | Gold |
|---|---|---|---|---|
Post (post), per 1,000 posts | $1.90 | $1.50 | $1.20 | $0.95 |
Page (page), per 1,000 pages | $2.00 | $1.50 | $1.20 | $1.00 |
Actor start (apify-actor-start), once per run | $0.0065 | $0.0065 | $0.0065 | $0.0065 |
Platinum and Diamond plans pay the Gold price. There is no discount on the Actor start event. The Store pricing card shows these same prices per 1,000 events: "$0.95 / 1,000" on the Post row means one post costs a little under a tenth of a cent on the Gold plan. The date window costs nothing extra.
Worked examples on the Free plan: the prefill (10 posts of one page) costs $0.0065 + $0.002 + 10 x $0.0019 = $0.0275; 1,000 posts of one page cost $0.0065 + $0.002 + $1.90 = $1.91; a scheduled run over 20 pages that finds 1 new post on each costs $0.0065 + 20 x $0.002 + 20 x $0.0019 = $0.0845. On the Gold plan the same three runs cost $0.017, $0.958 and $0.046.
The work allowance
Work that earns nothing (pages that do not exist, pages that keep showing the login page, refused calls, windows with no posts, known posts read again) is bounded by an allowance in real cost that grows with every post and page the run bills. A run of many pages that do not exist stops after a handful of them, with a free skipped row for the rest. A walk that delivers posts is not cut by it while Facebook's answers weigh what they weigh today (12 to 18 KB per post on the pages measured); a page whose posts weigh more than about 20 KB each would stop with work_allowance in its coverage row after the posts already delivered, each charged once, and nothing else. A run over many pages on a day Facebook shows its login page to most visitors spends more per page (more tries per page, slower exits); when that reaches the allowance, the run stops after the pages it could pay for, each charged as usual, and the pages not started get a free skipped row. Pages are read in the order of your list, so start the next run with those pages, or split a long list into several runs.
Input
| Field | What it does |
|---|---|
pages | Page URLs, page names, profile.php?id= URLs or page ids, one page per line (a line with two pages is not read: a free row names its position), up to 500. Also read: startUrls (with { "url": ... } objects), pageUrls, urls. |
maxPostsPerPage | How many of each page's newest posts are read inside the window (default 20, up to 100,000). Posts already in your memory count toward it and are free. Also read: resultsLimit. |
maxPosts | A cap of post rows for the whole run, across every page (no cap by default). |
postedAfter, postedBefore | The date window, inclusive, UTC: YYYY-MM-DD, YYYY-MM-DDTHH:MM, today, yesterday, "7 days", "3 months", "12 hours". A date means the start of that day for postedAfter and its end for postedBefore. Also read: onlyPostsNewerThan, onlyPostsOlderThan. |
memoryName, resetMemory | A memory for monitors (below); resetMemory: true forgets it before the run. |
A value sent as null or "" counts as left out. Two keys of one meaning (for example pages and startUrls) sent together refuse the input, with a free row that says why. Proxy settings and cookies are not used: the Actor reads pages from the Apify datacenter pool and posts through Apify residential exits on its own.
Example: { "pages": ["https://www.facebook.com/nike", "NASA"], "maxPostsPerPage": 50, "postedAfter": "30 days" }
Monitor pages for new posts
Give a Memory name (memoryName) and schedule the run. Every post delivered under that name is remembered and never delivered or charged again under it. The memory also remembers which stretches of each page's timeline it delivered in full: a later run reads only what is newer than the newest remembered post (asked with Facebook's own window, so only the new posts travel), skips the remembered stretch without a request, and reads on below it only when the page's number asks for more. A run that finds nothing new costs the start fee and one Page event per page; it makes no timeline request for a page Facebook shows itself (the page carries its newest post) and one small request for a page Facebook shows only through its About tab or plugin.
- Use one memory name per schedule; the memory belongs to this Actor.
- Two runs on one memory name at the same time: the second one runs free and remembers nothing.
- A memory that cannot be read or saved makes the run free (every row delivered, nothing charged after the start event) and says so in a status row.
- A date window that cuts a remembered stretch counts only the remembered posts inside the window toward Newest posts per page (the memory keeps each post's time).
- A post a page backdates into a stretch your memory already covers is not picked up by later memory runs (pages rarely backdate posts).
What this Actor does NOT do
- No login, no cookies, no Facebook account: posts and pages that need a login (private profiles, private or closed groups, age or country restricted pages) are not read; such a page gets a free
page_not_availablerow. - No single post URLs: give the page's URL instead (a post link gets a free row that says so).
- No comment text, only comment counts; no list of who reacted.
- No groups, event lists, post search or ads.
- No pinned posts: Facebook's timeline leaves the pinned post out and no answer marks a post as pinned.
- No video transcripts and no text read from images; Facebook's own alt text is delivered where it exists.
- An album lists the items Facebook shows on the timeline (five on the pages measured);
mediaCountsays how many it holds. - Counts (reactions, comments, shares, plays) are the ones Facebook shows at the moment of the run.
- The exact follower count and the category are empty on a page Facebook shows a visitor only through its plugin; the page row then carries the rounded count (
followersRounded). - No follower history across runs: the page row carries the count of the day.
- No ad library status of the page (not on the page a logged out visitor sees).
API examples
Run and get the rows (replace <APIFY_TOKEN>):
curl -X POST "https://api.apify.com/v2/acts/automation_craft~facebook-posts-scraper/run-sync-get-dataset-items?token=<APIFY_TOKEN>" \-H "Content-Type: application/json" \-d '{"pages":["https://www.facebook.com/nike"],"maxPostsPerPage":20}'
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<APIFY_TOKEN>' });const run = await client.actor('automation_craft/facebook-posts-scraper').call({ pages: ['NASA'], maxPostsPerPage: 20, memoryName: 'nasa-daily' });const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items.filter((r) => r.type === 'post'));
from apify_client import ApifyClientclient = ApifyClient("<APIFY_TOKEN>")run = client.actor("automation_craft/facebook-posts-scraper").call(run_input={"pages": ["NASA"], "postedAfter": "7 days"})posts = [r for r in client.dataset(run["defaultDatasetId"]).iterate_items() if r["type"] == "post"]
FAQ
Can I scrape a Facebook page's posts without logging in or giving cookies?
Yes. This Actor reads public pages as a visitor who is not logged in: no account, no cookies and no login. Pages and posts that Facebook shows only to logged in users are not read, and such a page gets a free status row.
How do I get all of a Facebook page's posts, including images and videos?
Set Newest posts per page high enough (up to 100,000): the walk goes newest first back through the page's history. Every row carries the photo and video links (media) with their sizes and alt text, and video rows carry plays, views and length.
How do I export Facebook page posts to CSV or Excel?
Run the Actor, open the Output tab and download the Posts view as CSV or Excel: one row per post, with the reaction types as their own columns. The same rows are available as JSON through the API.
How much does it cost to scrape 1,000 Facebook posts, and am I charged for failed pages?
1,000 posts of one page cost $1.91 on the Free plan and $0.958 on the Gold plan, start fee and Page event included. A page that does not exist or is restricted, a failed call, a repeat and a post your memory already holds are not charged.
Can I scrape posts from a past month only?
Yes. Set Posted on or after and Posted on or before (for example 2024-03-01 and 2024-03-31): Facebook applies the window itself, so the walk starts at the end of the window at once, without reading the newer posts, and the date window costs nothing extra.
Why does this Actor run with limited permissions?
It runs with the least privilege Apify offers: it reads and writes only its own run's storages and, when you give a memory name, one named key-value store it creates itself for that memory. It cannot see your other Actors, datasets or account data.
More data tools by Automation Craft
- Meta Ads Library Scraper - Ad Library, All Filters
- Facebook Ads Library Scraper - Ad Library & Spy
- Instagram Ads Library Scraper - Creatives, Video
- Meta Ad Spend Scraper: Advertiser Spend by Country
- Threads Scraper: Posts, Search, Tags, Replies
- Threads Profile Scraper: Followers, Bio, Posts
- TikTok Video Scraper: Post Stats, Transcripts
- Substack Scraper: Posts, Notes and Profiles
- Google News Scraper: Search, Topics, Decoded URLs
Changelog
- 0.1 (2026-10-11): first build.