Facebook Posts Scraper avatar

Facebook Posts Scraper

Pricing

from $3.00 / 1,000 posts

Go to Apify Store
Facebook Posts Scraper

Facebook Posts Scraper

Scrape posts from public Facebook Pages and profiles without login, by date window, with a per-URL coverage report. $3 per 1,000 posts.

Pricing

from $3.00 / 1,000 posts

Rating

5.0

(1)

Developer

Daniel G

Daniel G

Maintained by Community

Actor stats

0

Bookmarked

13

Total users

9

Monthly active users

2 days ago

Last modified

Categories

Share

Scrape posts from public Facebook Pages and profiles, plus single post, reel and video URLs, without login. Set a date window and receive a per-URL coverage report describing whether each feed was read completely. Each returned post costs $0.003 ($3 per 1,000); from October 21, 2026, each Page or profile checked also costs $0.003. A $0.00005 start fee applies per run.

What it returns

Each dataset item is one post. Optional fields may be omitted.

NameTypeMeaning
facebookUrlstringSupplied Page, profile, post or video URL.
inputUrlstringOriginal input URL.
postIdstringFacebook post ID.
urlstringPost permalink.
topLevelUrlstringURL built from author and post IDs.
timestringISO 8601 publication time.
timestampnumberPublication time, Unix seconds.
textstring or null, optionalPost text; videos can have empty or null text.
userobjectAuthor's id, name, profileUrl and profilePic; values can be null.
pageNamestringName from the URL or resolved author name.
facebookIdstring or nullResolved Facebook ID.
likesnumber or nullReaction count.
commentsnumber or nullComment count.
sharesnumber or nullShare count.
topReactionsCountnumber or nullReaction types represented.
viewsCountnumber or null, optionalVideo views when exposed.
mediaarray, optionalPhotos or videos with available thumbnails and media fields.
sharedPostobject or null, optionalShared post when exposed.
linkstring, optionalAttached URL.
isVideoboolean, optionalWhether the row contains video.

Example row (shortened text and placeholder details):

{"facebookUrl":"https://www.facebook.com/PAGE","inputUrl":"https://www.facebook.com/PAGE","postId":"POST_ID","pageName":"PAGE","url":"https://www.facebook.com/reel/POST_ID/","time":"2026-10-06T13:22:32.000Z","timestamp":1791292952,"user":{"id":"AUTHOR_ID","name":"Author","profileUrl":"https://www.facebook.com/AUTHOR_ID","profilePic":"https://example.com/profile.jpg"},"likes":62,"comments":1,"shares":3,"topReactionsCount":4,"topLevelUrl":"https://www.facebook.com/AUTHOR_ID/posts/POST_ID","facebookId":"AUTHOR_ID","collaborators":[],"paidPartnership":false,"topComments":[],"text":"Example post text…","media":[{"thumbnail":"https://example.com/thumbnail.jpg","__typename":"Video","url":"https://www.facebook.com/reel/POST_ID/","id":"VIDEO_ID"}],"isVideo":true}

Input

FieldDefaultMeaning
startUrlsRequiredArray of objects containing a Facebook url.
resultsLimit20Maximum posts per URL; integer from 1–10,000.
onlyPostsNewerThanNo lower boundInclusive publication-time lower bound.
onlyPostsOlderThanNo upper boundExclusive publication-time upper bound.
captionTextfalse in the input editorCompatibility boolean; ignored.

The half-open window is [onlyPostsNewerThan, onlyPostsOlderThan). Both bounds accept ISO dates, ISO datetimes or relative values such as 7 days, 12 hours, 2 weeks and 1 month, measured back from run initialization. Dates mean midnight UTC; datetimes without a timezone use UTC. Omit either bound; the lower bound must precede the upper bound. The window also filters single posts and videos.

Last seven days of one Page:

{"startUrls":[{"url":"https://www.facebook.com/NASA/"}],"onlyPostsNewerThan":"7 days"}

One UTC day from several Pages:

{"startUrls":[{"url":"https://www.facebook.com/NASA/"},{"url":"https://www.facebook.com/EuropeanSpaceAgency/"}],"onlyPostsNewerThan":"2026-10-01","onlyPostsOlderThan":"2026-10-02"}

Supported URLs

Example paths use https://www.facebook.com; replace placeholder IDs/codes.

URL formExampleNotes
Page or profile/NASA/, /profile.php?id=123, /people/Name/123Reads the timeline. Numeric paths work.
Post/NASA/posts/123, /NASA/posts/pfbidCODE, /permalink.php?story_fbid=123&id=456, /photo/?fbid=123Returns only the requested post; a reel's /posts/ URL also works.
Reel/reel/123Likes, comments and shares; viewsCount is null.
Watch/watch/?v=123Likes, comments and viewsCount; shares is null. /watch?v=123 also works.
Video/NASA/videos/123Same counts as watch; title-slug URLs such as /NASA/videos/title/123 work.
Group post/groups/GROUP/posts/123, /groups/GROUP/permalink/123Public groups only.
Share/share/r/CODE, /share/v/CODE, /share/p/CODEFollows redirects to the final URL.

Missing count fields are null, never estimated. Absent single-video media fields are also null. An absent post or video returns no row or post charge; its report uses stopReason: "not_found" and status: "unavailable".

How coverage is checked

Each accessible Page or profile feed is read at least twice using different IP addresses, with a third read when the first two differ. In-window results are merged by post ID. The first read stops after six consecutive posts older than the window start; later reads stop after three. Pinned posts and duplicates do not advance that streak.

complete and empty are reported only after two reads agree, or after a third read when the first two differ. All reads are merged by post ID, so a post found by any read is returned.

StatusMeaning
completePosts returned; verification finished and traversal reached the date boundary or feed end.
emptySame traversal conditions, with no posts in the window.
partialCoverage limited by the post limit, charge cap, free plan limit or failed verification; possibly no rows.
unavailableTarget missing or hidden from logged-out visitors.
failedCoverage could not be established and no posts were returned.

Single-post URLs use one read. An available post outside the window returns no row and reports empty.

stopReason identifies the boundary (passed_window_start, end_of_feed), limit (max_posts, charge_cap, free_plan_limit), failure (timeout, rate_limited, error) or visibility issue (not_found, private, login_wall, age_gated, restricted, not_visible_or_missing).

The default key-value store's OUTPUT record contains the normalized window and reports in targets, with a COVERAGE log line per URL.

Report fieldMeaning
walksNumber of reads attempted.
walksDisagreedWhether the first two reads differed.
postsAddedByVerificationAdditional posts found before applying the results limit.
outOfOrderPostsOlder posts followed by an in-window or newer post during the first read.
boundaryPostFirst post in the first read's final older streak.
profileChargedWhether the profile event was charged.

Reports also include postsEmitted, newestPostAt, oldestPostAt, skipped, feedPagesRead, requestsFailed, retries and errors. Compatibility fields firstPageFetches and firstPageDisagreed mirror walks and walksDisagreed.

Read /records/OUTPUT in the default store or through /v2/actor-runs/{runId}/key-value-store/records/OUTPUT.

Pricing

  • post: $0.003 per returned post ($3 per 1,000).
  • profile: $0.003 per Page or profile checked, starting October 21, 2026, for complete, empty or partial results. Unavailable and failed URLs are free; single posts and videos pay only the post event.
  • apify-actor-start: $0.00005 per run. There is no minimum post count.

From October 21, one profile checked for one day with four posts costs $0.015 in events, plus the start fee. Reaching your charge limit stops emission and crawling with charge_cap; coverage is partial.

Limits

Runs by users on Apify's free plan are limited to 3 URLs and 20 results per run.

Only public content visible without login is available. Hidden or restricted Pages and age-gated posts cannot be returned. Comments and group feeds are not collected; topComments is always empty. Reels that appear on a timeline are returned like other posts.

The Actor keeps a small cache of Page/profile IDs in the runner's account (facebook-posts-scraper-cache), and deleting it only makes the next run slower.

A reel page can report a creation time a few minutes different from the feed's. Refresh counts by matching postId. captionText is accepted but does nothing.

Use via API

Send JSON to the synchronous dataset-items endpoint:

curl -X POST 'https://api.apify.com/v2/acts/LordFloofington~facebook-posts-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN' \
-H 'Content-Type: application/json' \
--data '{"startUrls":[{"url":"https://www.facebook.com/NASA/"}],"onlyPostsNewerThan":"7 days","resultsLimit":20}'

Compliance

Users are responsible for complying with Facebook's terms and applicable law when using this Actor.