# Facebook Reviews Scraper — Every Review, Verdict, No Login (`memo23/facebook-reviews-scraper`) Actor

Every review on any public Facebook page, newest first: text, recommends or doesn't, Facebook's review tags, reviewer name and profile, date, reactions and comments, plus the page's overall recommend rate. Follows the cursor for all of them, not just page one. No login, no cookies, no browser.

- **URL**: https://apify.com/memo23/facebook-reviews-scraper.md
- **Developed by:** [Muhamed Didovic](https://apify.com/memo23) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 reviews

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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 Reviews Scraper

Every review on any public Facebook page, newest first — the text, whether the reviewer recommends the page or not, Facebook's review tags, the reviewer's name and profile, the date, reactions and comments — plus the page's overall recommend percentage on every row. Follows the cursor for all of them. No login, no cookies, no browser.

### Why Use This Scraper?

- **All of them, not the first page.** Facebook server-renders three reviews and loads the rest on scroll. Reading the page and stopping is why other review scrapers return "only the first 2 of 59". This one walks Facebook's own pagination query until it has what you asked for — measured 30 of 30 on a page with 201, 30 of 30 on a page with 76, ids unique, dates back to 2019.
- **Recommends or doesn't, on every row.** Facebook replaced star ratings with a recommend verdict in 2018. `recommends` is `true`/`false` on every review, from Facebook's own rendered verdict.
- **Facebook's review tags.** `Child-friendly`, `Fast delivery`, `Cosy atmosphere` — the structured tags reviewers pick, where present.
- **The page's own summary on each row.** `94% recommend (201 reviews)`, parsed into `pageRecommendPercent` and `pageReviewCount`, so a batch across pages needs no second lookup.
- **Stop at a date.** `onlyReviewsNewerThan` halts paging at the first older review, so you are not charged for history you did not ask for.
- **A page with no reviews says so.** `no_reviews`, `not_found`, `login_wall` — as a row, not charged, rather than a silently shorter dataset.

### Overview

One row per review, 23 fields. Ask for 50 reviews across three pages and you get up to 150 rows, each carrying `pageUrl`, `pageName` and `inputUrl`.

### Supported Inputs

| Input | Example |
|---|---|
| Reviews tab URL | `https://www.facebook.com/copperkettleyqr/reviews` |
| Page URL | `https://www.facebook.com/copperkettleyqr` |
| Vanity name | `copperkettleyqr` — in the `pages` field |
| Numeric id | `100064027242849` — in the `pages` field, or `profile.php?id=…` as a URL |
| Any host or tab | `m.facebook.com`, `/about`, `/photos` — normalised |

### Use Cases

- **Reputation monitoring** — every negative review on your own or a client's pages, with the text and the date, on a schedule.
- **Competitor research** — what customers praise and complain about across a set of local businesses.
- **Lead qualification** — recommend rate and review volume for every page a search returned.
- **Sentiment datasets** — review text with a binary label, tags and engagement, at scale.

### How It Works

Each input is normalised to the page and its About tab is streamed — about 100 KB — for the page id, name, category and the overall recommend summary. The reviews connection is then paged through Facebook's own refetch query, three reviews per request, following the cursor until `resultsLimit`, the date cut-off, or the end. Responses are the multi-line format Facebook streams to its own client — the first review on line one, the rest as their own lines, the cursor last — and are read as such. The recommend verdict is Facebook's rendered title for the review, pinned to English by the request's `Accept-Language`.

Pure HTTP over a residential proxy. No browser, no login.

### Input Configuration

| Field | Type | Default | Notes |
|---|---|---|---|
| `startUrls` | array | — | Page or reviews-tab URLs. |
| `pages` | array | — | Vanity names or numeric ids. Either field, or both; de-duplicated on the page. |
| `resultsLimit` | integer | `50` | Reviews per page, newest first. |
| `onlyReviewsNewerThan` | string | — | `YYYY-MM-DD`. Paging stops at the first older review. |
| `language` | string | `en-US` | `Accept-Language` for the page fetch. The verdict is always read in English. |
| `proxy` | object | — | Non-paying sample runs only. Paying runs use a built-in residential proxy. |

#### Example input

```json
{
  "startUrls": [{ "url": "https://www.facebook.com/copperkettleyqr/reviews" }],
  "resultsLimit": 100,
  "onlyReviewsNewerThan": "2025-01-01"
}
```

### Output Overview

One flat row per review. A page that yields none produces `{ inputUrl, error, message }` and is not charged.

### Output Sample

A real row from a live run — a negative review, chosen on purpose:

```json
{
  "reviewId": "10159367163365044",
  "url": "https://www.facebook.com/jayna.nicholson/posts/pfbid0FDW1nctxFdgK9T2Rzx9Vannn68uxzLE4WRhfGLgvL98AdEjrhJKX42BfeFTDHPPhl",
  "text": "Normally the food from here is really good but we got pizza last night and it was somewhere in the range of sub par to just really not good. The whole thing was barely cooked and was so soggy. The crust was literally wet. Maybe it’s because it’s the deluxe 🤷‍♀️ \nAnyway, I don’t think we’ll be getting pizza from here again. Definitely not worth the price.",
  "recommends": false,
  "verdictText": "Jay Enn doesn't recommend The Copper Kettle Restaurant.",
  "tags": [],
  "createdAt": "2024-04-11T17:40:55.000Z",
  "createdTimestamp": 1712857255,
  "reviewerName": "Jay Enn",
  "reviewerId": "pfbid0CdLWRx8qk8cuqmSdwKbWkZ72kYoKST7ZefipmWrcdRTGvnN6MmX9qZHpUU9kqUE6l",
  "reviewerUrl": null,
  "reactionsCount": 1,
  "commentsCount": 3,
  "photoUrls": [],
  "pageUrl": "https://www.facebook.com/copperkettleyqr",
  "pageName": "The Copper Kettle Restaurant",
  "pageId": "100064027242849",
  "pageCategory": "Pizza place",
  "pageRatingText": "94% recommend (201 reviews)",
  "pageRecommendPercent": 94,
  "pageReviewCount": 201,
  "inputUrl": "https://www.facebook.com/copperkettleyqr/reviews",
  "scrapedAt": "2026-09-17T12:46:30.484Z"
}
```

### Key Output Fields

| Field | Notes |
|---|---|
| `reviewId` / `url` | Facebook's post id for the review and its permalink. |
| `text` | The review. |
| `recommends` | `true` / `false`, from Facebook's verdict. `verdictText` is the sentence it came from. |
| `tags` | Facebook's review tags where the reviewer picked any — `Child-friendly`, `Fast delivery`. Empty otherwise. |
| `createdAt` / `createdTimestamp` | ISO 8601 and epoch seconds. |
| `reviewerName` / `reviewerId` / `reviewerUrl` | The reviewer. The URL is built from the id when Facebook lists no vanity name. |
| `reactionsCount` / `commentsCount` | Engagement on the review. |
| `photoUrls` | Photos attached to the review, signed CDN links. |
| `pageName` / `pageId` / `pageUrl` / `pageCategory` | The page. |
| `pageRatingText` / `pageRecommendPercent` / `pageReviewCount` | `94% recommend (201 reviews)` and its parts. |
| `error` / `message` | Present only on a page-level row: `no_reviews`, `no_reviews_in_range`, `not_found`, `login_wall`, `blocked`, `invalid_url`. |

### FAQ

**Do I need a Facebook account or cookies?**
No. Every figure in this README came from logged-out requests with no cookies of any kind.

**Why is there no star rating?**
Facebook removed stars in 2018. A review is a recommend or a don't-recommend, and that is what `recommends` carries. `pageRecommendPercent` is the page-level equivalent of a rating.

**Can I get every review on a page?**
Yes — set `resultsLimit` above the page's `pageReviewCount`. Facebook serves three per request, so a page with 200 reviews takes about 70 requests, which is a minute or two.

**Why do some reviews have no `tags` or `photoUrls`?**
Most reviewers don't add them. Empty arrays mean none were attached, not that extraction failed.

**Am I charged for a page with no reviews?**
No. You get one row saying so, and it is free.

### Support

Open an issue on the Actor's Issues tab. Bug reports with a run id and the page URL get looked at first.

### Explore More Scrapers

- **[Facebook Page Contact Details](https://apify.com/memo23/facebook-page-contact-detail-scraper)** — email, phone, address, hours for any page
- **[Facebook Pages & Contacts](https://apify.com/memo23/facebook-pages-and-contacts-scraper)** — find pages by keyword and city, with contacts
- **[Facebook Comments Scraper](https://apify.com/memo23/facebook-comments-scraper)** — comment threads on any public post
- **[Facebook Reels Scraper](https://apify.com/memo23/facebook-reels-scraper)** — every reel on a page with play counts

### 🤖 For AI Agents & LLM Apps

**Purpose:** Return every review on public Facebook pages — text, a binary recommend label, tags, reviewer, date, engagement — with the page's overall recommend rate, from page URLs (`startUrls`) or vanity names and ids (`pages`).

**Minimal tested input:**

```json
{ "startUrls": [{ "url": "https://www.facebook.com/copperkettleyqr/reviews" }], "resultsLimit": 30 }
```

**Output:** array of flat objects, one per review. Fields: `reviewId`, `url`, `text`, `recommends`, `verdictText`, `tags`, `createdAt`, `createdTimestamp`, `reviewerName`, `reviewerId`, `reviewerUrl`, `reactionsCount`, `commentsCount`, `photoUrls`, `pageUrl`, `pageName`, `pageId`, `pageCategory`, `pageRatingText`, `pageRecommendPercent`, `pageReviewCount`, `inputUrl`, `scrapedAt`.

**Agent-relevant behaviour:** `recommends` is the label; there is no numeric rating per review on Facebook. Rows arrive newest first per page. A row carrying `error` is a page-level failure, not a review. `pageReviewCount` is Facebook's own total, so `resultsLimit >= pageReviewCount` means all of them. `photoUrls` expire within hours.

**Billing:** per review row. Page-level failure rows are free.

### ⚠️ Disclaimer

This Actor reads only publicly available Facebook reviews — no login, no cookies, no private content. Reviews are their authors' words. You are responsible for using the output lawfully, including under the GDPR, the CCPA and Facebook's terms where they apply to you. Nothing here is legal advice.

### SEO Keywords

facebook reviews scraper, scrape facebook reviews, facebook page reviews, facebook recommendations scraper, facebook business reviews, facebook review data, facebook reviews export, facebook reviews to csv, facebook reviews api, facebook reviews sentiment, facebook negative reviews, facebook page rating, facebook review monitoring, facebook reviews no login, apify facebook reviews scraper

# Actor input Schema

## `startUrls` (type: `array`):

Page URLs or /reviews URLs — https://www.facebook.com/copperkettleyqr/reviews. For vanity names or numeric ids use the "Pages" field below. Duplicates across both fields are fetched and billed once.

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

Vanity names or numeric ids, one per line — "copperkettleyqr", "100064027242849". Merged with the URLs above.

## `resultsLimit` (type: `integer`):

How many reviews to return for EACH page, newest first. Facebook serves 3 per request; the run follows the cursor until it has this many or the page runs out. Default 50.

## `onlyReviewsNewerThan` (type: `string`):

Optional cut-off, YYYY-MM-DD. Reviews arrive newest first, so paging stops at the first review older than this and you are not charged for anything past it.

## `language` (type: `string`):

Accept-Language for the page fetch. The recommend/doesn't-recommend verdict is always read in English regardless.

## `proxy` (type: `object`):

Non-paying sample runs only. Paying runs always use a built-in residential proxy, because Facebook serves a login wall to datacenter IPs.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.facebook.com/copperkettleyqr/reviews"
    }
  ],
  "pages": [],
  "resultsLimit": 50,
  "language": "en-US",
  "proxy": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `results` (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 = {
    "startUrls": [
        {
            "url": "https://www.facebook.com/copperkettleyqr/reviews"
        }
    ],
    "pages": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("memo23/facebook-reviews-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 = {
    "startUrls": [{ "url": "https://www.facebook.com/copperkettleyqr/reviews" }],
    "pages": [],
}

# Run the Actor and wait for it to finish
run = client.actor("memo23/facebook-reviews-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 '{
  "startUrls": [
    {
      "url": "https://www.facebook.com/copperkettleyqr/reviews"
    }
  ],
  "pages": []
}' |
apify call memo23/facebook-reviews-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,memo23/facebook-reviews-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/mhHQeq6EcbmdFcM1G/builds/1p8bZa8aaggJ5HvtZ/openapi.json
