# Facebook Reels Play Count Scraper (`social_developer/facebook-playcount-scraper`) Actor

Scrapes exact play counts for Facebook video / reel / watch URLs. Uses Apify datacenter proxies for IP rotation.

- **URL**: https://apify.com/social_developer/facebook-playcount-scraper.md
- **Developed by:** [Celine](https://apify.com/social_developer) (community)
- **Categories:** Social media
- **Features:** Limited permissions
- **Stats:** 412 total users, 140 monthly users, 100.0% runs succeeded, 2 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $0.00005 / actor start

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 Video Play Count Scraper — Apify Actor

An [Apify Actor](https://docs.apify.com/platform/actors) that extracts the exact `play_count`
for Facebook video / reel / watch URLs, using **Apify datacenter proxies** for IP rotation.

It is a port of the original local CLI scraper (`facebook_playcount_scraper.py`) to the
Apify platform, so the detection logic (video-id extraction + HTML parsing) is unchanged.

***

### ⭐ Need more than play counts? Meet the full social scraping toolkit

This actor is laser-focused on **exact Facebook play counts**. If you need richer engagement data or want to cover Instagram too, these sibling Actors from the same author plug into the exact same workflow — paste links in, get clean JSON out, no login required, MCP-ready for AI agents. 👇

<table>
<tr>
<td width="50%" valign="top">

#### 📘 Facebook Posts & Reels Scraper

**➡️ [Open on Apify](https://console.apify.com/actors/Gxlh7dfGl46sVup4S/)**

Go beyond play counts. Paste any public Facebook **post / reel / photo / video / share** URL and get the **full engagement picture**:

- ❤️ reactions, 💬 comments, 🔁 shares, ▶️ video views
- 📝 caption, 👤 author, 🕒 timestamp, 🖼️ thumbnail
- 🔗 handles `/reel/`, `/share/p|r|v/`, `/watch/`, `/photo`, `fb.watch`
- 🛡️ resilient Playwright workers + cookie support

> **Upgrade path:** use *this* play-count actor for pure view numbers at scale, and the Posts & Reels Scraper when you also need reactions, comments & shares.

</td>
<td width="50%" valign="top">

#### ⚡ Instagram Post & Reel Scraper

**➡️ [Open on Apify](https://console.apify.com/actors/GLcl7jwhshuWdvkiD/)**

Take the same paste-a-link workflow to **Instagram**. Fast, cheap, and built for scale:

- 👀 `videoPlayCount` (views/plays), likes, comments
- 📝 caption, hashtags, mentions, music, owner
- 💰 lightweight HTTP — cheapest way to get IG link metrics
- 🤖 MCP-ready for Cursor / Claude / GPT agents

> **Cross-platform:** already tracking Facebook video views here? Add Instagram metrics with one more Actor and cover both platforms from one toolkit.

</td>
</tr>
</table>

**One author, one workflow, every platform:**

| Actor | Best for | Open |
|---|---|---|
| ▶️ **Facebook Video Play Count Scraper** *(this actor)* | Exact Facebook play counts at scale | You're here |
| 📘 **Facebook Posts & Reels Scraper** | Reactions, comments, shares, plays + caption/author | [Open →](https://console.apify.com/actors/Gxlh7dfGl46sVup4S/) |
| ⚡ **Instagram Post & Reel Scraper** | Fast, cheap Instagram link metrics | [Open →](https://console.apify.com/actors/GLcl7jwhshuWdvkiD/) |
| 🎬 **YouTube Video & Shorts Scraper** | Fast YouTube views, likes, comments from URL | [Open →](https://console.apify.com/actors/dq0gHM2cIZyblDr1L/) |

***

### What it does

1. Takes a list of Facebook URLs (via `startUrls` or a pasted `urlsText` block).
2. Extracts the numeric video id from each URL (`?v=`, `/videos/…`, `/reel/…`, `/watch/…`).
3. **Reel URLs are auto-converted** before scraping: `/reel/{id}` → `https://www.facebook.com/watch/?v={id}`. Watch URLs are used as-is.
4. Fetches the page HTML (optionally through Apify proxy), rotating the IP on every retry.
5. Parses the exact `play_count` for the target video id from the embedded JSON payloads.
6. Pushes one record per URL to the actor's default dataset.

#### Output record shape

```json
{
    "url": "https://www.facebook.com/watch/?v=1234567890",
    "video_id": "1234567890",
    "play_count": 482311,
    "status": "ok"
}
```

`status` is one of:

- `ok` — play count found.
- `invalid_video_id` — URL did not contain a recognisable video id.
- `play_count_not_found` — page fetched, but no matching play count in HTML.
- `request_failed: …` — all retries failed. The suffix indicates the last error
  (e.g. `http_429`, `timeout`, `request_failed: ConnectError`).

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `startUrls` | array of `{url}` | — | Facebook URLs to scrape. |
| `urlsText` | string | — | Alternative to `startUrls`, one URL per line. |
| `maxConcurrency` | int | `12` | Parallel fetches. |
| `requestTimeoutSecs` | int | `20` | Per-request HTTP timeout. |
| `maxRetriesPerUrl` | int | `3` | Retries per URL, each with a fresh proxy IP. |
| `useProxy` | bool | `true` | Toggle proxy usage. Set `false` to run with no proxy (direct actor IP). |
| `proxyConfiguration` | object | `{ useApifyProxy: true, apifyProxyGroups: [] }` | Apify proxy config (ignored when `useProxy` is `false`). |

Example input lives at [`.actor/input.example.json`](./.actor/input.example.json).

### IP rotation

The actor calls `Actor.create_proxy_configuration(actor_proxy_input=…)` and then
requests a **new proxy URL per attempt** with a unique `session_id`, so every retry
is guaranteed to go through a different upstream Apify datacenter IP:

```python
proxy_url = await proxy_configuration.new_url(
    session_id=f"fb_{abs(hash(url))}_{attempt}"
)
```

That session id is also what Apify uses to pin a given IP — by bumping the attempt
counter, we explicitly break stickiness after a failure, which is the usual pattern
for recovering from rate-limits/soft-blocks on datacenter proxies.

If you want residential proxies instead, edit the input and pass:

```json
"proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["RESIDENTIAL"]
}
```

### Local development

Requires Python 3.11 and the Apify CLI.

```bash
## from the project root
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

## install Apify CLI (one-time, via npm)
npm install -g apify-cli

## run the actor locally using the example input
apify run --purge --input-file=.actor/input.example.json
```

Results land in `storage/datasets/default/`.

### Deploy to the Apify platform

```bash
apify login        # paste your Apify API token
apify push         # builds the Docker image and pushes the actor
```

`apify push` uses `.actor/actor.json` + `.actor/Dockerfile` to build the actor on
Apify, and `.actor/input_schema.json` to render the input form in the Apify Console.

After the push you can either:

- Run it from the Apify Console UI.
- Trigger it from the API:

  ```bash
  curl -X POST "https://api.apify.com/v2/acts/<USERNAME>~facebook-playcount-scraper/runs?token=$APIFY_TOKEN" \
       -H "Content-Type: application/json" \
       -d @.actor/input.example.json
  ```

### Project layout

```
.
├── .actor/
│   ├── actor.json            # actor metadata + dataset view
│   ├── Dockerfile            # build config (apify/actor-python:3.11)
│   ├── input_schema.json     # UI / API input schema
│   └── input.example.json    # sample input for `apify run`
├── src/
│   ├── __main__.py           # `python -m src` entrypoint
│   ├── main.py               # Apify actor logic + proxy rotation
│   └── parser.py             # video-id + play_count extraction
├── facebook_playcount_scraper.py  # original standalone CLI (kept for reference)
├── requirements.txt
├── .dockerignore
├── .gitignore
└── README.md
```

### Push to GitHub

```bash
git init
git add .
git commit -m "Apify actor: facebook play count scraper with DATACENTER proxy rotation"
git branch -M main
git remote add origin https://github.com/celine/facebook-playcount-scraper.git
git push -u origin main
```

***

### 🚀 Explore the rest of the toolkit

Scraping social media? Don't stop at play counts:

- 📘 **[Facebook Posts & Reels Scraper](https://console.apify.com/actors/fRmlsQqW3Klcf6HB8/)** — reactions, comments, shares & plays from any Facebook link.
- ⚡ **[Instagram Post & Reel Scraper](https://console.apify.com/actors/GLcl7jwhshuWdvkiD/)** — fast, cheap Instagram views, likes & comments from a URL.
- 🎬 **[YouTube Video & Shorts Scraper](https://console.apify.com/actors/dq0gHM2cIZyblDr1L/)** — YouTube views, likes, comments, channel & more from a URL.

All share the same no-login, paste-a-link, MCP-ready design. 💚

# Actor input Schema

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

List of Facebook video / reel / watch URLs to scrape play counts for. Reel links like https://www.facebook.com/reel/123456789 are automatically converted to https://www.facebook.com/watch/?v=123456789 before scraping.

## `urlsText` (type: `string`):

Alternative to startUrls. Plain-text list of URLs, one per line. Useful for pasting large batches.

## `maxConcurrency` (type: `integer`):

Number of URLs to fetch in parallel.

## `requestTimeoutSecs` (type: `integer`):

HTTP request timeout per URL.

## `maxRetriesPerUrl` (type: `integer`):

How many times to retry a URL with a fresh proxy IP before giving up.

## `useProxy` (type: `boolean`):

Enable Apify proxy routing. Turn this OFF to run directly from the actor IP (no proxy).

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

Apify proxy settings. Defaults to Apify datacenter proxies (auto-selected per plan) for IP rotation. On paid plans you can explicitly set `apifyProxyGroups: ["DATACENTER"]`, and `["RESIDENTIAL"]` is also supported.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.facebook.com/watch/?v=1234567890"
    }
  ],
  "maxConcurrency": 12,
  "requestTimeoutSecs": 20,
  "maxRetriesPerUrl": 3,
  "useProxy": true,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": []
  }
}
```

# 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/watch/?v=1234567890"
        }
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": []
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("social_developer/facebook-playcount-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/watch/?v=1234567890" }],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": [],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("social_developer/facebook-playcount-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/watch/?v=1234567890"
    }
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": []
  }
}' |
apify call social_developer/facebook-playcount-scraper --silent --output-dataset

```

## MCP server setup

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