# Facebook Posts Scraper - Page Posts, No Login (`automation_craft/facebook-posts-scraper`) Actor

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.

- **URL**: https://apify.com/automation_craft/facebook-posts-scraper.md
- **Developed by:** [Automation Craft](https://apify.com/automation_craft) (community)
- **Categories:** Social media, Marketing, Automation
- **Stats:** 4 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.95 / 1,000 posts

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### 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.

| 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), `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):

```json
{
  "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.

| 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_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>`):

```bash
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}'
```

```javascript
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'));
```

```python
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

- [Meta Ads Library Scraper - Ad Library, All Filters](https://apify.com/automation_craft/meta-ads-library-scraper)
- [Facebook Ads Library Scraper - Ad Library & Spy](https://apify.com/automation_craft/facebook-ads-library-scraper)
- [Instagram Ads Library Scraper - Creatives, Video](https://apify.com/automation_craft/instagram-ads-library-scraper)
- [Meta Ad Spend Scraper: Advertiser Spend by Country](https://apify.com/automation_craft/meta-ad-spend-scraper)
- [Threads Scraper: Posts, Search, Tags, Replies](https://apify.com/automation_craft/threads-scraper)
- [Threads Profile Scraper: Followers, Bio, Posts](https://apify.com/automation_craft/threads-profile-scraper)
- [TikTok Video Scraper: Post Stats, Transcripts](https://apify.com/automation_craft/tiktok-video-scraper)
- [Substack Scraper: Posts, Notes and Profiles](https://apify.com/automation_craft/substack-scraper)
- [Google News Scraper: Search, Topics, Decoded URLs](https://apify.com/automation_craft/google-news-scraper)

### Changelog

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

# Changelog

This Actor's version history is a separate document: https://apify.com/automation_craft/facebook-posts-scraper/changelog.md

# Actor input Schema

## `pages` (type: `array`):

Public Facebook pages to read, one per line: a page URL (facebook.com/nike), a page name (nike), a profile.php?id= URL or a page id. Public figures' profiles work the same way. Up to 500 per run. Each page read gives a page row (the Page event: name, followers, category and verified badge, as Facebook shows them) and its posts. A page that does not exist or is restricted gets a free status row. Links to single posts, reels, groups or events are not read (a free row says so).

## `maxPostsPerPage` (type: `integer`):

How many of each page's newest posts are read inside the date window, newest first, back through the page's history when you ask for enough. Posts already in your memory count toward this number and are free. Default 20 when left out, at most 100,000.

## `maxPosts` (type: `integer`):

The cap of post rows for the whole run, across every page. No cap when left out: the per page number and your charge limit bound the run.

## `postedAfter` (type: `string`):

Keep posts from this moment on (UTC): YYYY-MM-DD, YYYY-MM-DDTHH:MM, today, yesterday, "7 days", "3 months" or "12 hours" (counted back from the run's start). The window is applied by Facebook itself and checked again on every row, at no extra charge.

## `postedBefore` (type: `string`):

Keep posts up to this moment (UTC), in the same forms. A date means the end of that day. Use it to read a page's history from a point in the past: the walk starts there at once, without reading the newer posts.

## `memoryName` (type: `string`):

A short name (letters, digits, spaces, . \_ , : # ( ) -). Posts delivered under this name are never delivered or charged again in later runs with the same name, and the stretches of each page's timeline already read are skipped without a request. Use one name per schedule. The memory belongs to this Actor.

## `resetMemory` (type: `boolean`):

Forget every post the memory holds before this run (it needs a memory name). Only a fresh run resets; a run the platform restarts never resets again.

## Actor input object example

```json
{
  "pages": [
    "https://www.facebook.com/NASA"
  ],
  "maxPostsPerPage": 10
}
```

# Actor output Schema

## `items` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "pages": [
        "https://www.facebook.com/NASA"
    ],
    "maxPostsPerPage": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation_craft/facebook-posts-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "pages": ["https://www.facebook.com/NASA"],
    "maxPostsPerPage": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("automation_craft/facebook-posts-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "pages": [
    "https://www.facebook.com/NASA"
  ],
  "maxPostsPerPage": 10
}' |
apify call automation_craft/facebook-posts-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation_craft/facebook-posts-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/G8cdQZJ6HXz657tIe/builds/eVbq5Bk2a2Vkenf5J/openapi.json
