Facebook Posts Scraper
Pricing
from $0.65 / 1,000 post scrapeds
Facebook Posts Scraper
Scrape recent public posts from any Facebook Page: text, exact post time, permalink, photos and videos, reaction, comment and share counts, plus page identity. no login needed from you, no browser.
Pricing
from $0.65 / 1,000 post scrapeds
Rating
0.0
(0)
Developer
Dami's Studio
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
Paste public Facebook Page URLs and get their recent posts back as clean, flat rows: the full post text, the exact time it was posted, its permalink, every photo and video attached to it, and the reaction, comment and share counts — plus who the Page is. No login, no cookies, no Facebook account, no browser, and nothing for you to configure.
- Up to 50 Pages in a single run, one row per post.
- Reaction counts broken down by type (Like, Love, Wow, Care, Haha, Sad, Angry), not just a single total.
- Photos, videos, albums and Reels come back with their ids, permalinks, thumbnails and alt text.
- Date filtering is included at no extra charge — it is a field on the input, not a paid add-on.
- Runs with empty input return a labelled sample row, free, so you can see the shape first.
- A Page that is blocked, private or misspelled produces an uncharged diagnostic row, never a failed run.
Price
$0.65 per 1,000 posts ($0.00065 each), plus a $0.0015 start fee per run (billed per gigabyte of run memory, so exactly that on the default 1 GB).
It is the same rate on every plan, free or paid. There are no volume tiers, no minimum spend, no subscription and no add-on fees. What you read here is what you pay on day one and on day four hundred.
One run tops out at 1,000 posts — 50 Pages at 20 posts each — so larger totals are several runs and pay the start fee once per run.
| Posts | Runs | Total cost |
|---|---|---|
| 100 | 1 | $0.0665 |
| 1,000 | 1 | $0.6515 |
| 10,000 | 10 | $6.515 |
| 100,000 | 100 | $65.15 |
What is actually charged
- One
post-scrapedevent per post row written to the dataset. Nothing else is metered per row. - Free: the sample row an empty run returns, and every diagnostic row — a blocked target, a dead URL, a search that matched nothing. Those rows all carry
"charged": false. - Posts dropped by your date filter are never charged — the filter runs before billing, and using it costs nothing extra.
- Duplicate posts inside a single run are dropped before they are charged.
- A Page that returns nothing produces one free diagnostic row and no post charges.
- A run that finds nothing costs the start fee and nothing more.
- Rows never leave the dataset without a charge, and are never charged without a row. The billed event is the named
post-scraped. Nothing is priced against the built-inapify-default-dataset-item, which bills every row pushed to the dataset — sample and diagnostic rows included.
Input
{"startUrls": ["https://www.facebook.com/NASA","https://www.facebook.com/BBCNews"],"resultsLimit": 20,"onlyPostsNewerThan": "30 days"}
| Field | What it does |
|---|---|
startUrls | Public Facebook Page URLs, one per line. A bare handle (NASA), a /pg/ URL, a /p/ URL and a profile.php?id= URL all work. Up to 50 Pages per run. |
resultsLimit | How many recent posts to take from each Page, newest first. Default 20, which is also the ceiling — see Limitations. Keep it low while testing; you pay per post. |
onlyPostsNewerThan | Optional. Drop posts older than this. Accepts 2026-08-01, a full ISO timestamp, an epoch, or a relative window such as 7 days. Free. |
onlyPostsOlderThan | Optional. Drop posts newer than this. Same formats. Free. |
proxyUrls | Leave empty. Fill it in only if you want the traffic to leave through proxy servers you already pay for, as http://user:pass@host:port. |
sessionCookies | Leave empty. Runs are logged out by default and that is enough for public Pages. Supply your own c_user/xs cookie only if you want a Page that walls logged-out visitors retried on your own account, under your own rate limit. |
Run it with empty input and you get one clearly labelled sample row, free, so you can see the output shape before you spend anything.
Output
One row per post. A real row from a real run:
{"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": null,"pageLikes": 28696238,"pageProfilePicture": "https://lookaside.fbsbx.com/lookaside/crawler/media/?media_id=100044561550831","postId": "1602283071267063","postUrl": "https://www.facebook.com/NASA/posts/pfbid0zJ6mq7LDUr5ZxqeqrrPDCWnv87PJXe1qg9YoKpQNyULieuLXMdJjXJ2DEUAcTwfyl","text": "Our photographers were on hand in Maine and Spain to capture the Aug. 12 solar eclipse. Check out a few of their photos here and see the rest on Flickr: https://www.flickr.com/photos/nasahqphoto/","textLength": 195,"time": "2026-08-13T18:17:19.000Z","timestamp": 1786645039,"reactionsCount": 25128,"topReactions": [{"type": "Like","count": 17443},{"type": "Love","count": 6977},{"type": "Wow","count": 347},{"type": "Care","count": 327}],"commentsCount": 337,"sharesCount": 2729,"postType": "photo","media": [{"type": "photo","id": "1602282937933743","url": "https://www.facebook.com/photo.php?fbid=1602282937933743&set=a.416661013162614&type=3","thumbnailUrl": "https://lookaside.fbsbx.com/lookaside/crawler/media/?media_id=1602282937933743","altText": "In this eclipse photo, the Moon is passing fully in front of the Sun, creating a perfectly black disc surrounded by the Sun's shining yellow corona.","style": "Album"}],"mediaCount": 4,"isReel": false,"isSponsored": false,"linkUrl": null,"linkTitle": null,"scrapedAt": "2026-08-15T22:31:07.182Z"}
Field notes
inputUrl— the Page URL you asked for, so you can group rows by Page after merging several runs.postUrl— the post permalink. Reels come back as/reel/…, videos as/videos/…, ordinary posts as/posts/pfbid….time— the exact posting time in ISO 8601 UTC, taken from the post itself rather than a "2 days ago" label.timestampis the same moment in epoch seconds.reactionsCount— total reactions of all types at read time.topReactionsbreaks the same total down by reaction type.commentsCount— the public comment count. The comments themselves are not returned — this Actor scrapes posts.sharesCount— shares at read time. Null when Facebook does not publish a share count for that post.postType— one ofvideo,photo,linkorstatus, derived from what is actually attached.media— an array. Photos and videos carry an id, a permalink, a thumbnail and, when Facebook supplies one, the alt text written for screen readers. Videos also carrydurationMs.isSponsored— true when the post is a paid placement rather than an organic one.pageFollowers— null on many Pages — Facebook only publishes a follower count on some of them.pageLikesis the more widely available figure.
Every real row carries "charged": true. Sample rows carry "_sample": true and diagnostic rows carry "_diagnostic": true with an errorCode you can filter on, and neither is ever billed.
How it works
- It reads the public, logged-out version of the Page that Facebook publishes for indexing, and lifts the posts out of the structured data already inside that page. No headless browser, no rendering, no scrolling, no account and no cookies.
- One request per Page delivers the whole batch of recent posts, which is why the price can be this low: the cost of a run barely moves with the number of posts you take from a Page.
- The response is read only as far as the posts, then cut off — the rest of a Facebook page is player state this Actor has no use for.
- Traffic leaves through a large pool of rotating addresses. Facebook throttles per address, so a refusal is answered by moving to a fresh one and asking again, up to eight times per Page, with the request identity varied each time.
- Nothing is charged until a post row is safely written to your dataset.
What people use it for
- Brand and market monitoring — pull the recent posts of twenty Pages every morning and diff on
postIdto see only what is new. - Social media reporting — reaction, comment and share counts land as plain numbers, so engagement rates are a spreadsheet formula rather than a data-cleaning project.
- Content research — read what a whole category of Pages posted this week, sorted by
reactionsCount, before deciding what to publish yourself. - Feeding a dashboard or a warehouse: rows are flat and typed, so they load without a transformation step.
- Archiving a Page you own or follow, including the permalinks and media URLs, so the record survives a deleted post.
- Lightweight sentiment and topic analysis —
textis the full post message, not a truncated preview, so it goes straight into an NLP pipeline.
Reading the output
Every run writes three kinds of row, and they are easy to tell apart:
- Real rows carry
"charged": trueand"recordType": "post". These are the rows you paid for, one billed event each. - The sample row carries
"_sample": trueand"charged": false. There is exactly one, it only appears when the input had no Page URLs, and it exists so you can look at the output shape before you spend anything. - Diagnostic rows carry
"_diagnostic": true,"charged": falseand anerrorCodeyou can switch on:NOT_FOUNDwhen there is no public Page at that URL,BLOCKEDwhen Facebook served a login interstitial from every address tried,NO_RESULTSwhen the Page rendered but published no posts,BAD_INPUTwhen a URL could not be read as a Page,TIME_BUDGETwhen the run ran out of time before reaching a Page, andNETWORKwhen Facebook could not be reached. Each carries theinputUrlit belongs to and a plain-English explanation.
If you only want the data, filter on charged == true. The count of those rows always equals the number of events you were billed for, so the dataset is its own invoice.
Limitations
- The public Page render carries the 20 most recent posts, and that is the hard ceiling per Page per run. This Actor goes wide rather than deep: 50 Pages of 20 posts in one run, not 1,000 posts from one Page. If you need deep history, this is not the tool.
- Because of that ceiling, the date filters narrow the recent posts a Page publishes — they cannot reach further back than those posts. Asking for last year on a Page that posts daily will correctly return nothing.
- Public Pages only. Personal profiles with a private timeline, Groups, Events and anything behind a login are out of scope and produce an uncharged
NOT_FOUNDorBLOCKEDrow. - Some Pages are age-restricted or country-restricted and show a logged-out visitor no timeline at all. Those return an uncharged diagnostic row rather than posts, and no amount of retrying changes it.
- Comments themselves are not returned, only the comment count. The same goes for the identities of people who reacted.
- Reaction, comment and share counts are a snapshot at read time and keep moving on a live post.
- Pinned posts are excluded by Facebook from the public timeline render, so a Page whose newest content is pinned may show it lower down or not at all.
sharesCountandpageFollowersare null on some Pages because Facebook does not publish them there. Nulls are honest, not missing data.- Facebook throttles per address. Under heavy parallel load a Page can come back as
BLOCKED; re-running a few minutes later normally clears it, and nothing is charged for the attempt. - The text is returned as posted. It is not translated, and emoji and line breaks are preserved exactly.
Questions
Do I need a Facebook account or cookies?
No. Runs are logged out and read only what Facebook shows the public web, which is also why private content is out of reach. There is an optional sessionCookies field for callers who want a Page that walls logged-out visitors retried on their own account, but it stays off unless you fill it in.
Can I get more than 20 posts from one Page?
Not from this Actor. Facebook publishes the 20 most recent posts to a logged-out visitor and nothing further without an account, and this Actor will not pretend otherwise. Running it on a schedule and deduplicating on postId builds deep history over time, one cheap run at a time.
What happens if a Page is blocked or does not exist?
You get one uncharged diagnostic row for that Page explaining which of the two it was, and the run carries on to your other Pages. You are never billed for a Page that returned nothing.
Does the date filter cost extra?
No. It is a plain input field, it runs before anything is billed, and posts it removes are never charged. Filtering to last week is strictly cheaper than not filtering.
Will the run fail if something goes wrong?
No. A blocked, empty or broken target produces an uncharged diagnostic row and the run still finishes as succeeded. A failed run would still bill you the start fee, which would mean paying to be told something went wrong.
Can I run this on a schedule?
Yes, and it is the intended way to use it. Nothing in the run holds state between runs. Schedule the same Page list daily and deduplicate on postId to see only new posts.
How do I get exactly the rows I paid for?
Filter the dataset on "charged": true. Sample and diagnostic rows are always false, and the number of charged rows always equals the number of billed events.
Do I need to supply a proxy?
No. The run brings its own egress and its cost is already inside the price you see. The proxyUrls field exists only for callers who specifically want traffic to leave through servers they own.