Facebook Posts Scraper⚡
Pricing
from $2.50 / 1,000 post scrapeds
Facebook Posts Scraper⚡
📊 Scrape posts from any public Facebook Page or Profile. Get full post data: text, media, reaction counts, comment count, share count, photos, videos (HD+SD URLs), links, timestamps & more. Date filtering, multi-profile support, can scrape all posts from a Page or Profile⚡Facebook Posts Scraper⚡
Pricing
from $2.50 / 1,000 post scrapeds
Rating
0.0
(0)
Developer
Premium Scraper
Actor stats
0
Bookmarked
3
Total users
2
Monthly active users
4 days ago
Last modified
Categories
Share
Facebook Posts Scraper — High-Volume Facebook Timeline Data Extractor ⚡
Facebook Posts Scraper is a production-grade Apify Actor that collects posts from any public Facebook Page or Profile at scale. Every post is returned as a complete JSON record containing all raw fields Facebook's returns, plus three convenience fields added by Facebook Posts Scraper on top.
✨ Features
- Deep pagination — Facebook Posts Scraper collects up to 50,000 posts per profile automatically
- Full raw data — Every field Facebook's returns is preserved, zero filtering
- Zero delay — No artificial waits between pagination requests
- Date filtering — Filter posts by date range ("Posts newer than" / "Posts older than") — applied server-side via Facebook's, not post-scrape filtering
- Spending-limit safe — Scraping stops immediately the moment Apify's spending limit is reached, regardless of
posts_countor number of profiles - Multi-profile — Process multiple Pages and Profiles in a single run
- Smart deduplication — Duplicate posts are automatically removed
- Pay-Per-Event — You pay only for posts actually scraped and pushed to the dataset
📥 Input
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
username | string[] | No | — | One or more Facebook usernames, e.g. Cristiano, nike |
facebook_urls | object[] | No | — | One or more Facebook profile/page URLs |
posts_count | integer | No | 50 | Number of posts to collect per profile (1–50,000) |
At least one of username or facebook_urls is required. Facebook Posts Scraper normalizes all input formats automatically.
🔍 Date Filters (optional — each active filter adds extra per-post charge)
Both date filters are off by default. When no filters are active, you pay only the base per-post price. Enabling a date filter adds a small extra surcharge per post scraped.
| Filter | Type | Default | Extra charge? | What it does |
|---|---|---|---|---|
posts_newer_than | date (calendar picker) | — | ⚡ Yes, per post | Only return posts created after this date. Uses Facebook's native afterTime variable — server-side filtering, no wasted pagination. |
posts_older_than | date (calendar picker) | — | ⚡ Yes, per post | Only return posts created before this date. Uses Facebook's native beforeTime variable — server-side filtering, no wasted pagination. |
Supported URL Formats
| Input type | Example |
|---|---|
| Username only | Cristiano |
| Full profile URL | https://www.facebook.com/Cristiano |
| People URL | https://www.facebook.com/people/Page-Name/123456789/ |
| Short path | people/Page-Name/123456789 |
| With trailing section | https://www.facebook.com/Cristiano/posts/ (section path auto-stripped) |
📤 Output
Each post output by Facebook Posts Scraper is a JSON object in the dataset. Fields fall into two categories:
Convenience Fields (Added by the Scraper)
These fields are computed and added on top of the raw Facebook data:
| Field | Type | Description |
|---|---|---|
number | integer | Sequential position of the post in this run, starting from 1 |
profile_link | string | The source profile URL that was scraped |
created_at | string | ISO 8601 UTC timestamp of post creation, e.g. 2026-03-15T08:19:46Z — computed from creation_time, which for deferred nodes is nested inside comet_sections |
message_text | string | Plain text content of the post — surfaced from comet_sections.content.story.message.text because Facebook does not include a top-level message key in deferred Story nodes |
Raw Facebook Fields (Returned As-Is from GraphQL)
All fields below come directly from Facebook's API and are never modified.
| Field | Type | Always Present | Description |
|---|---|---|---|
post_id | string | ✅ | Unique numeric post identifier |
permalink_url | string | ✅ | Full URL to the post on Facebook |
__typename | string | ✅ | Facebook's internal node type — always "Story" for timeline posts |
id | string | ✅ | Facebook's internal node ID (different from post_id, used in graph queries) |
cache_id | string | ✅ | Internal cache key for the node |
creation_time | integer | ✅ | Unix timestamp (seconds) of when the post was created |
actors | array | ✅ | Array of poster objects. Each actor contains: id (numeric string), name, url (profile link), __typename (User or Page), is_verified, short_name, preferred_name, profile_picture (object with uri, width, height) |
feedback | object | ✅ | Engagement container. Fields: id, can_viewer_comment, can_viewer_react, reactors (object with count), reaction_count (object with count + reaction_list array), comment_count (object with total_count), share_count (object with count), top_reactions (array — each item has reaction type and count), subscription_count |
attachments | array | ✅ | Media attachments. Each element contains styles.attachment.media — structure varies by media type (see Media Types below) |
comet_sections | object | ✅ | Facebook's UI rendering tree as raw JSON. Contains nested content, context_layout, metadata, feedback, sponsor sections. For deferred Story nodes, the post message and creation_time are inside this structure |
is_reshare | boolean | Conditional | Present only when true. Facebook omits this key entirely when the post is not a reshare |
encrypted_tracking | string | ✅ | Opaque encrypted string used by Facebook's analytics and feed ranking systems |
serialized_frtp_identifiers | string | ✅ | Serialized feed ranking, targeting, and personalization identifiers |
__isNode | string | Some nodes | Internal interface marker, typically "Story" |
__isEntity | string | Some nodes | Internal interface marker |
sponsored_data | object | Ads only | Present only on sponsored/advertisement posts |
Media Types Inside attachments[].styles.attachment.media
__typename | Fields |
|---|---|
Photo | id, __typename, image (object with uri — full image URL, width, height), large_image, accessibility_caption |
Video | id, __typename, playable_url (SD stream), browser_native_hd_url (HD download), browser_native_sd_url (SD download), duration_in_ms, width, height, owner (object with name, id) |
ExternalUrl | __typename, url (destination link), title, description, favicon_url |
Field Availability Notes
message_textis always surfaced at top level by the scraper. For most deferred Story nodes (the majority of paginated results), Facebook nests text insidecomet_sections.content.story.message.text.feedbackcounts (reaction_count,comment_count,share_count) may benullfor some posts — this is a Facebook API restriction on the public timeline endpoint, not a scraper issue.is_reshareis structurally absent when false — Facebook omits the key entirely for non-reshared posts.comet_sectionsis the most data-rich field. It is deeply nested and contains the full post message, author info, metadata, and engagement UI tree.- All Facebook fields are preserved — no keys are removed, renamed, or modified.
Budget / Maximum Cost Control
Set a Maximum Cost Per Run in the Apify Console to cap total spending. Facebook Posts Scraper enforces this limit via Apify's native charge signal:
- After every post is pushed,
Actor.charge(event_name='post', count=1)is called - When the spending limit is reached, Apify returns
event_charge_limit_reached = True - Facebook Posts Scraper stops immediately — no more pagination, no further profiles processed
- All posts already pushed to the dataset are retained — nothing is lost
- The
posts_countinput and number of profiles are both overridden by the spending limit — the limit always wins
Example: Your price = $0.003/post, user sets max cost = $1.50 → Apify stops charging after 500 posts. Even if posts_count = 10000 or 5 profiles are configured, Facebook Posts Scraper stops at 500 posts.
❓ FAQ
Why are some posts missing reaction_count, comment_count, or share_count?
Facebook's public timeline endpoint does not always include engagement counts in deferred Story nodes. The feedback object is still present — it contains can_viewer_react, reactors, and top_reactions — but numeric counts may be null. This is a platform restriction, not a scraper issue.
What is the comet_sections field?
Facebook's internal UI component tree. It is returned as a deeply nested JSON object and holds the rendering instructions for the post, including the post message text and creation_time for most deferred nodes. The scraper reads these and surfaces them as message_text and created_at at the top level.
Why is is_reshare missing on some posts?
Facebook only includes is_reshare in the raw node when it is true. When a post is not a reshare, the key is structurally absent. This is Facebook's API behavior, not a bug.
Why is message_text empty for some posts?
Some posts have no text — only photos, videos, link attachments, or check-ins. For reshares, the original post text may be nested deeper inside comet_sections.
How does date filtering work?
Facebook's GraphQL API natively supports afterTime and beforeTime variables (Unix timestamps). Facebook Posts Scraper converts your YYYY-MM-DD input to a Unix timestamp and passes it directly to the API. This means filtering happens server-side — Facebook only returns posts within your date range. When a date filter is active, the initial HTML post is skipped because HTML-embedded posts don't have reliable timestamps for client-side filtering.
Can I combine date filtering with posts_count?
Yes. For example, posts_newer_than = 2025-06-01 + posts_count = 100 returns up to 100 posts that were created after June 1, 2025. Both constraints apply together.
Do date filters cost extra?
Yes. Each active date filter (posts_newer_than, posts_older_than) adds a small per-post surcharge on top of the base post price. The exact price for each filter event is configured on the Apify Monetization page. If no filters are used, you pay only the base per-post price.
Can I scrape multiple profiles in one run?
Yes. Facebook Posts Scraper processes all profiles sequentially in the same run. Add multiple entries to username or facebook_urls. The spending limit applies across all profiles combined — if the limit is hit mid-run, no further profiles are started.
What happens when the spending limit is reached? Facebook Posts Scraper stops immediately on the current profile the moment Apify returns the charge limit signal. All posts already collected are in the dataset. No further profiles are processed. The actor exits cleanly with a log of total posts pushed.
Does it support both personal profiles and business pages? Yes. Facebook Posts Scraper auto-detects the profile type and extracts the numeric page ID for both personal profiles and business Pages.
📧 Custom Solutions?
Need custom fields, higher volume, scheduled runs, or integrations with your existing pipeline?
✉️ Contact premiumscraper@gmail.com
🔒 Privacy & Compliance
- This Facebook Posts Scraper only accesses publicly available Facebook data
- No Facebook login, cookies, or API token is required
- No private messages, friend lists, or non-public content is ever accessed
- User spending limits are fully respected — the actor stops processing if your configured budget is reached
- Always ensure your use of scraped data complies with applicable laws and platform terms of service