Facebook Posts Scraper - Page Posts, No Login avatar

Facebook Posts Scraper - Page Posts, No Login

Pricing

from $0.95 / 1,000 posts

Go to Apify Store
Facebook Posts Scraper - Page Posts, No Login

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

Automation Craft

Maintained by Community

Actor stats

0

Bookmarked

3

Total users

1

Monthly active users

3 days ago

Last modified

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

  1. 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.
  2. 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).
  3. Run, then download the rows from the Output tab (views Posts and Pages) as JSON, CSV or Excel, or read them through the API.
  4. 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.

FieldWhat it holdsFilled
postId, url, createdAt, createdAtUnixThe post's id, its link and its creation time (UTC)100%
textThe post's text in full, line breaks kept98.4% (posts without text have none)
hashtags, mentionsHashtags in the text; tagged pages and people with id and link24.3%, 3.8% (where the text has them)
postTypephoto, album, video, reel, link, event, share, text or unavailable_attachment (an attachment Facebook no longer shows)100%
reactionCount, reactionsAll reactions, and each type (like, love, care, haha, wow, sad, angry); the types add up to the total on every post measured100% (a post without reactions has an empty breakdown)
commentCount, shareCountComments and shares as Facebook counts them100%
videoViewCount, videoPlayCount, videoDurationSecondsOn videos and reels100% of videos and reels
media, mediaCount, mediaListedPhotos 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
linkA link preview: url, title, description, domain, imageUrlevery link post
event, sharedPostAn event post's event; a share's original post (id, link, author, text)where present
authorId, authorName, authorUrlWho posted it100%
pageId, pageName, pageUrl, pageUsernameThe page on every row100%
pageVerifiedThe page's verified badge99.8%
pageFollowers, pageCategoryThe 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, scrapedAtFacebook's own story and feedback ids, the input value that led to the row, the time of the run100%

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), countedFromMemory and stretchesSkipped (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_limited and others) and complete.
  • 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_read and not_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 (nintendo to 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.

EventFreeBronzeSilverGold
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

FieldWhat it does
pagesPage 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.
maxPostsPerPageHow 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.
maxPostsA cap of post rows for the whole run, across every page (no cap by default).
postedAfter, postedBeforeThe 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, resetMemoryA 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_available row.
  • 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); mediaCount says 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 ApifyClient
client = 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

Changelog

  • 0.1 (2026-10-11): first build.