Alfalfa

Facebook Posts API: public page posts as JSON, without the Graph API

Meta's Graph API returns posts only for pages you manage, after app review. This endpoint returns the public posts of any page or profile, the way a signed-out visitor sees them, as JSON with reactions, comment and share counts, media and dates. It behaves like a REST API: one call in, records out, with an API token, pagination and webhooks.

Updated September 2026. Endpoint hosted on Apify; an Apify account and API token are the only requirements.

What the Graph API gives you today

The /{page-id}/posts and /feed edges still exist, but reading them needs a Page access token for a page you administer, and reading other pages needs the Page Public Content Access feature, which is granted after app review and mostly to established apps. Comment counts and reactions come with more permissions still. For competitor pages, media pages or research across many pages, the Graph API is not an option in practice.

The endpoint

One HTTP call. The synchronous form waits for the run and returns the records in the same response (fine for up to a few minutes of work); the asynchronous form returns a run id at once and you read the dataset when it has finished, with webhooks if you want a callback.

Synchronous

curl -X POST "https://api.apify.com/v2/acts/alfalfa~facebook-posts-scraper/run-sync-get-dataset-items?token=$APIFY_TOKEN&format=json" \
  -H 'Content-Type: application/json' \
  -d '{"startUrls": [{"url": "https://www.facebook.com/humansofnewyork"}], "resultsLimit": 50, "onlyPostsNewerThan": "30 days"}'

Asynchronous

# start the run (returns immediately with the run id and dataset id)
curl -X POST "https://api.apify.com/v2/acts/alfalfa~facebook-posts-scraper/runs?token=$APIFY_TOKEN" \
  -H 'Content-Type: application/json' -d '{"startUrls": [{"url": "https://www.facebook.com/humansofnewyork"}], "resultsLimit": 50, "onlyPostsNewerThan": "30 days"}'
# read the results when the run has finished (JSON, CSV or XLSX; paginate with offset and limit)
curl "https://api.apify.com/v2/datasets/<defaultDatasetId>/items?token=$APIFY_TOKEN&format=json&offset=0&limit=1000"

Python

from apify_client import ApifyClient  # pip install apify-client

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("alfalfa/facebook-posts-scraper").call(run_input={
  "startUrls": [
    {
      "url": "https://www.facebook.com/humansofnewyork"
    }
  ],
  "resultsLimit": 50,
  "onlyPostsNewerThan": "30 days"
})
items = list(client.dataset(run.default_dataset_id).iterate_items())
print(len(items), items[0])

JavaScript

import { ApifyClient } from 'apify-client'; // npm install apify-client

const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });
const run = await client.actor('alfalfa/facebook-posts-scraper').call({"startUrls": [{"url": "https://www.facebook.com/humansofnewyork"}], "resultsLimit": 50, "onlyPostsNewerThan": "30 days"});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.length, items[0]);

Request fields

FieldTypeMeaning
startUrlsarrayPage or profile URLs, as {"url": ...} objects or plain strings.
resultsLimitintegerMaximum posts per page.
onlyPostsNewerThanstringYYYY-MM-DD, ISO date-time, or relative such as 30 days; stops paging when older posts appear.
onlyPostsOlderThanstringUpper bound, same formats.
captionTextbooleanAdd the video transcript to video posts ($2 per 1,000 video posts looked up).
maxConcurrencyintegerPages processed in parallel, default 5.

Response fields

One JSON object per record. Field names are the ones the official Apify Actor uses, so code written for it works unchanged.

FieldMeaning
postId, url, facebookUrl, pageNamePost ID and URL, the page it belongs to.
time, timestampWhen it was posted, ISO 8601 and Unix time.
text, link, previewTitle, previewDescriptionThe post text and the link preview when there is one.
likes, comments, shares, reactionLikeCount ... reactionAngryCountEngagement, with the reaction split.
media, isVideo, viewsCount, captionTextPhotos and videos with URLs, video views, optional transcript.
topComments, sharedPost, user, collaborators, paidPartnershipTop comments, the original of a shared post, the author, co-authors, paid-partnership label.

Limits, pagination, scheduling

Pricing

$2 per 1,000 posts, no start fee, date filters free. Platform usage and residential proxies are included; you pay only for records written to the dataset. The Apify free plan includes $5 of usage a month, enough to try it properly.

Questions people ask

Does the Facebook Graph API still let me read posts of any page?

Only pages you administer, with a Page access token. Other pages need the Page Public Content Access feature after app review, which most developers do not get. This endpoint reads the public page instead and needs no Facebook account at all.

Is it a real API?

It is an Apify Actor called through the Apify REST API: POST the input, get JSON back, or start a run and read the dataset later. Tokens, pagination, webhooks and schedules work like any other API.

Can I get only new posts every day?

Yes. Set onlyPostsNewerThan to yesterday and schedule the run; the response contains only the posts published since then.

What does it cost?

$2 per 1,000 posts with platform usage included and no start fee; the official Apify posts scraper charges $5 plus a start fee and a fee per filter.

Open the Actor on Apify All five endpoints