# Facebook Review Scraper By Multiple Pages (`scrapedrift/facebook-review-scraper`) Actor

Facebook Review Scraper: Scrape reviews from multiple Facebook pages, including ratings, reviewer names, dates, review text, page details, and engagement data. Compare customer feedback, sentiment, and reputation across businesses for market and competitor research.

- **URL**: https://apify.com/scrapedrift/facebook-review-scraper.md
- **Developed by:** [ScrapeDrift](https://apify.com/scrapedrift) (community)
- **Categories:** Social media, Developer tools, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.99 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Facebook Review Scraper By Multiple Pages

Scrape Facebook reviews from **one or many Facebook pages in a single run**. Point it at a page's `/reviews` URL and it returns each reviewer's name, review text, profile picture, review link, and a unique review ID — and, unlike a single-page Facebook review scraper, it can pull the same fields from a whole list of pages at once, tagging every review with the exact page it came from.

This is a Facebook page review scraper, Facebook review extractor, and Facebook review data export tool built around Facebook's own internal GraphQL review-feed API (no login required), with automatic pagination, proxy rotation, and soft-block retries so runs stay reliable when scraping Facebook reviews at scale — across a single business page or a whole competitor set.

### What it does

- Accepts a **primary Facebook page reviews URL** plus an optional list of **additional page reviews URLs**, and scrapes all of them in one run.
- For each page it resolves a fresh `doc_id`, page ID, and session token directly from that page's own HTML/JS — every page gets its own pagination session, so results from different pages never bleed into each other.
- Paginates through each page's review feed via Facebook's internal `ratings_list_feed_units` GraphQL query until the review cap is hit or Facebook reports no more pages.
- Detects soft blocks (an HTTP 200 response whose payload carries GraphQL `errors` instead of review data) and retries automatically on a fresh proxy IP, instead of silently reporting "no more reviews."
- Applies your chosen Apify Proxy configuration to every request (page HTML, JS bundle lookup, and GraphQL calls), rotating to a fresh IP on connection failures before any rows have been written for that page, so a proxy hiccup never produces duplicate rows.
- Optionally removes duplicate reviews (same `story_id`) that show up more than once across the pages scraped in the same run.

### Input

| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| `startUrl` | string | Yes | `https://www.facebook.com/buladiradda/reviews` | Primary Facebook page reviews URL to scrape (e.g. `https://www.facebook.com/<page>/reviews`). |
| `additionalStartUrls` | array of strings | No | `[]` | Extra Facebook page reviews URLs to scrape in the same run, alongside the primary URL. Each gets its own review budget. |
| `maxReviews` | integer | No | `100` | Maximum number of reviews to scrape from **each** page. This cap is per page, not shared — 3 pages capped at 50 each can return up to 150 reviews total. |
| `dedupeAcrossPages` | boolean | No | `true` | When on, drops a review whose `story_id` was already pushed earlier in the run (e.g. the same page listed twice). When off, every review is pushed even if it repeats. |
| `proxyConfiguration` | object | No | `{"useApifyProxy": true}` | Apify Proxy configuration, applied to every request across every page scraped in the run. |

#### Example input

```json
{
  "startUrl": "https://www.facebook.com/target/reviews",
  "additionalStartUrls": [
    "https://www.facebook.com/nike/reviews"
  ],
  "maxReviews": 50,
  "dedupeAcrossPages": true,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

### Output

Each scraped review is written to the dataset as one record:

| Field | Type | Description |
|---|---|---|
| `name` | string | The reviewer's display name. |
| `profile_pic` | string (image URL) | URL to the reviewer's profile picture. |
| `message` | string | The review text content. |
| `story_id` | string | Facebook's internal ID for this review, useful for de-duplication. |
| `story_url` | string (link) | Direct link back to the review post. |
| `sourcePageUrl` | string (link) | The exact input URL (primary or one of the additional URLs) this review was scraped from — lets you tell reviews from different pages apart in a multi-page run. |

#### Example output record

```json
{
  "name": "Julia Odan",
  "profile_pic": "https://scontent.xx.fbcdn.net/.../profile.jpg",
  "message": "Great customer service and fast shipping.",
  "story_id": "UzpfSTEwMDAyMDgzMTgyMzg1MjoxMTg5NTQyMDg4NDE2ODQxOjExODk1NDIwODg0MTY4NDE=",
  "story_url": "https://web.facebook.com/username/posts/pfbid0abc123",
  "sourcePageUrl": "https://www.facebook.com/target/reviews"
}
```

Export results as JSON, CSV, or Excel directly from the Apify dataset.

### Use cases

- **Multi-page reputation monitoring** — track reviews across several of your own business pages, or across multiple locations of the same brand, without running the actor separately for each URL.
- **Competitor review comparison** — scrape your page and a competitor's page in the same run, and use `sourcePageUrl` to keep the two review sets apart in one dataset.
- **Bulk Facebook review data extraction** for sentiment analysis, review moderation, or feeding a business-intelligence dashboard.
- **Clean, deduplicated datasets** — `dedupeAcrossPages` keeps a multi-page run from double-counting a review that appears under more than one page URL.

### How it works

The actor reads Facebook's own internal review-feed data for each target URL. For every target URL it:

1. Loads the page's reviews HTML to resolve that page's numeric page ID and harvest a fresh session token.
2. Reads the first page of reviews directly from the data Facebook already embeds in that same page load (a server-rendered preload of the review feed), so the first batch of reviews doesn't depend on a separate API round-trip succeeding.
3. Locates the current `doc_id` for the reviews-feed query from the page's own async JS bundle, then continues paging through `ratings_list_feed_units.reviews_feed` via Facebook's `ProfileCometReviewsFeedRefetchQuery` GraphQL endpoint (`https://web.facebook.com/api/graphql/`) using the opaque `cursor` Facebook returns — starting from a fresh first page for every target URL.
4. Stops once the per-page review cap is reached or Facebook reports no further pages.

No Facebook login or cookies are required — this actor only reads pages Facebook already serves publicly.

### Notes

- Only public review data that Facebook renders in the page's own reviews feed is collected — private, restricted, or login-only content is not accessible.
- Review coverage depends on what Facebook exposes for a given page; some pages may have Reviews turned off entirely and will return zero rows.

# Actor input Schema

## `startUrl` (type: `string`):

The URL of the Facebook page reviews section to scrape first (e.g., https://www.facebook.com/buladiradda/reviews). This is the base input's own 'startUrl' key.

## `additionalStartUrls` (type: `array`):

Extra Facebook page-reviews URLs to scrape in the SAME run, in addition to the Primary Page Reviews URL above. Each URL is scraped with its own fresh doc\_id/page\_id/cursor. 'Max Reviews Per Page' applies PER PAGE — it is NOT split/shared across pages, so 3 pages with a cap of 50 can return up to 150 reviews total.

## `maxReviews` (type: `integer`):

Maximum number of reviews to scrape from EACH page (the Primary URL and every entry in Additional Page Review URLs each get their own budget of this many reviews — the cap is per page, not shared across pages).

## `dedupeAcrossPages` (type: `boolean`):

When ON, a review whose story\_id has already been pushed earlier in this run is dropped before it reaches the dataset (this can genuinely happen if the same page URL is listed twice, or if Facebook cross-links the same review across pages). When OFF, every scraped review row is pushed unfiltered, even exact repeats.

## `proxyConfiguration` (type: `object`):

Proxies to use so requests to Facebook succeed reliably. Applied to every page-HTML, JS-bundle, and GraphQL request for every target URL.

## Actor input object example

```json
{
  "startUrl": "https://www.facebook.com/target/reviews",
  "additionalStartUrls": [],
  "maxReviews": 100,
  "dedupeAcrossPages": true,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `reviews` (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 = {
    "startUrl": "https://www.facebook.com/target/reviews"
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapedrift/facebook-review-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 = { "startUrl": "https://www.facebook.com/target/reviews" }

# Run the Actor and wait for it to finish
run = client.actor("scrapedrift/facebook-review-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 '{
  "startUrl": "https://www.facebook.com/target/reviews"
}' |
apify call scrapedrift/facebook-review-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scrapedrift/facebook-review-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/vz9JaSaXD5xZMfv2v/builds/FW8DYzpJ7DZANQ6Q7/openapi.json
