# Facebook Video & Reels Downloader — MP4, HD (`memo23/facebook-video-downloader`) Actor

Download Facebook videos and Reels as MP4 in HD or SD — from share links, reel links, watch links or page video URLs. Or set metadataOnly for owner, title, quality and thumbnail without the file. Share links are resolved to their real reel URL. No login needed.

- **URL**: https://apify.com/memo23/facebook-video-downloader.md
- **Developed by:** [Muhamed Didovic](https://apify.com/memo23) (community)
- **Categories:** Social media, Videos, Agents
- **Stats:** 17 total users, 17 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $30.00 / 1,000 video downloadeds

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?

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 Video & Reels Downloader

Give it Facebook video or Reel URLs, get back the MP4 plus the metadata around it. Share links, `/reel/` links, `/watch/` links and page video URLs all work, and a share link is resolved to its real reel URL before anything else happens. No login, no cookies for public content, no browser.

### Why Use This Scraper?

- **Share links are resolved, not rejected.** `facebook.com/share/r/XXXX/` is what people actually copy off the app, and it is not the canonical URL. This resolves it — measured on a live run, `share/r/CYg8uitszPX6gRoK/` came back as `facebook.com/reel/8422069481202628`.
- **Metadata without the download.** Set `metadataOnly` and you get owner, title, quality and thumbnail without paying for bandwidth you do not want.
- **Highest available quality is detected**, not assumed — the run reports what it found (`1936p` on the test clip) rather than silently handing you SD.
- **The run says what happened.** Every run ends with a summary naming `requested`, `succeeded`, `failed` and the exact `failedInputs`, so a partial batch is visible instead of something you discover by counting rows.
- **Cookies only when Facebook demands them.** Public videos need none. `facebookCookies` exists for the content that does, rather than being required up front.
- **A size ceiling before any bytes move.** `maxFileSizeMb` defaults to 100. An unexpectedly long video is skipped rather than silently eating the run's budget.
- **One video, one charge.** Paste the same video as a reel link and a share link and you are billed once, not twice — de-duplication happens on the resolved video id, not on the text you typed. The duplicate row carries `duplicateOf` so you can still see which of your inputs it came from.

### Overview

One row per input URL. Give it fifty links and you get fifty rows, each carrying `inputUrl` so a batch stays attributable to what you submitted.

### Supported Inputs

| Input | Example |
|---|---|
| Share link | `/share/r/`, `/share/v/`, `/share/p/` and the bare `/share/<token>/` |
| Reel link | `https://www.facebook.com/reel/8422069481202628` |
| Watch link | `/watch/?v=`, `/watch/?video_id=`, `video.php?id=` |
| Page video | `/<page>/videos/<id>/` and `/<page>/reels/videos/<id>/` |
| Short domains | `fb.watch/<token>`, `fb.com/...`, `fb.me/...` |
| Any subdomain | `m.`, `web.`, `touch.`, `business.`, `mbasic.`, locale hosts like `en-gb.` |
| Post permalinks | `story.php`, `permalink.php`, `/<page>/posts/<id>` and group posts |
| Wrapped links | `l.php?u=...` and `flx/warn?u=...` are unwrapped automatically |

Tracking noise (`?mibextid=`, `?rdid=`, `?fs=`, `?locale=`) is stripped, duplicate slashes are
collapsed, and `pfbid` ids are accepted alongside numeric ones.

### Use Cases

- **Content archiving** — keep permanent MP4 copies of Reels before they are edited or deleted.
- **Creative research** — pull a competitor's Reels and study hooks, pacing and captions offline.
- **Ad and campaign records** — retain what a brand actually published, with owner and title attached.
- **Feeding transcription or vision models** — hand the MP4 straight to a downstream pipeline.

### How It Works

Each URL is normalised first, so a share link becomes its canonical reel or video URL. The video's metadata is read, the best available rendition is picked, and unless `metadataOnly` is set the file is fetched and stored. Downloads run in parallel up to `maxConcurrency`, and a URL that fails is named in the run summary rather than dropped silently.

Pure HTTP with built-in proxies. No browser and no Facebook account for public content.

### Input Configuration

| Field | Type | Default | Notes |
|---|---|---|---|
| `videoUrls` | array | required | Facebook video or Reel URLs. Share, reel, watch and page-video forms all accepted. |
| `metadataOnly` | boolean | `false` | Skip the download and return metadata only. |
| `maxFileSizeMb` | integer | `100` | Skip any video larger than this, checked before a byte moves. Stops one long video consuming a whole run's budget. |
| `facebookCookies` | string | **optional** | Leave empty for public videos and Reels — everything above works without it. Netscape-format cookies only unlock content Facebook refuses to serve logged out. |
| `maxConcurrency` | integer | `3` | Parallel downloads. |
| `proxy` | object | — | Proxy configuration. |

#### Example input

```json
{
  "videoUrls": [
    "https://www.facebook.com/share/r/CYg8uitszPX6gRoK/",
    "https://www.facebook.com/reel/8422069481202628"
  ],
  "metadataOnly": false,
  "maxFileSizeMb": 100,
  "maxConcurrency": 3
}
```

### Output Overview

One flat row per URL, 12 fields. In `metadataOnly` mode `downloadUrl` and `fileSizeBytes` are `null` by design, since nothing was fetched.

### Output Sample

A real row from a live run, in `metadataOnly` mode:

```json
{
  "videoId": "8422069481202628",
  "inputUrl": "https://www.facebook.com/share/r/CYg8uitszPX6gRoK/",
  "resolvedUrl": "https://www.facebook.com/reel/8422069481202628",
  "title": "THE PAUSECAST PODCAST 🇮🇳",
  "ownerName": "THE PAUSECAST PODCAST 🇮🇳",
  "durationSec": null,
  "publishedAt": null,
  "viewCount": null,
  "quality": "1936p",
  "fileSizeBytes": null,
  "downloadUrl": null,
  "thumbnailUrl": "https://scontent.fdub1-4.fna.fbcdn.net/v/t51.71878-15/…"
}
```

### Key Output Fields

| Field | Notes |
|---|---|
| `videoId` | Facebook's own numeric id. |
| `inputUrl` / `resolvedUrl` | What you submitted, and what it actually pointed at. A share link differs from both. |
| `title` / `ownerName` | Video title and the account that posted it. |
| `quality` | The rendition selected, e.g. `1936p`. |
| `downloadUrl` / `fileSizeBytes` | The stored MP4 and its size. `null` in `metadataOnly` mode. |
| `thumbnailUrl` | Cover image. |
| `durationSec` / `publishedAt` / `viewCount` | Populated where Facebook exposes them; `null` rather than a guessed value when it does not. |

### FAQ

**Do I need to log in?**
No. Every example in this README was run with no cookies and no account. `facebookCookies` is optional and exists only for private, followers-only or group videos that Facebook will not serve to a logged-out request. Leave it empty and nothing is sent.

**Does it handle the share links I copy from the app?**
Yes, and that is the point — `facebook.com/share/r/...` is resolved to the canonical reel URL before the video is read.

**Can I get the data without downloading the file?**
Yes. `metadataOnly: true` returns owner, title, quality and thumbnail and skips the bandwidth.

**Why are some fields null?**
Facebook does not expose duration, publish date or view count on every video. They are left `null` rather than filled with a guess.

**What happens if one URL in my batch fails?**
The run continues and finishes, and the summary names the failed inputs explicitly.

**I pasted the same video twice in different formats — am I charged twice?**
No. A reel link and the share link that points at it resolve to the same video id, and billing
is keyed on that id. The second one returns the same data with a `duplicateOf` field naming the
input it matched.

**Does it accept the link my phone gives me?**
Yes. `fb.watch/...`, `m.facebook.com/...`, share links and links carrying `?mibextid=` tracking
all normalise to the canonical video before anything is fetched.

**Does it find Reels for me?**
No. This takes URLs you already have. To discover a page's Reels first, pair it with a Reels scraper and feed the URLs in.

### Support

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

### Additional Services

Need a custom scraper, a scheduled feed, or this data delivered somewhere specific? Get in touch through the Apify Store profile.

### Explore More Scrapers

- **[Instagram Video Downloader](https://apify.com/memo23/instagram-video-downloader)** — Reels and carousels, permanently re-hosted
- **[YouTube Video Downloader](https://apify.com/memo23/youtube-video-downloader)** — the same job on YouTube
- **[Facebook Marketplace Scraper](https://apify.com/memo23/facebook-marketplace-scraper-ppe)** — listings with photos, location and vehicle data
- **[Facebook Comments Scraper](https://apify.com/memo23/facebook-comments-scraper)** — comment threads on any public post

### 🤖 For AI Agents & LLM Apps

**Purpose:** Turn Facebook video and Reel URLs into MP4 files plus structured metadata. Handles share links by resolving them to canonical URLs first.

**Minimal tested input:**

```json
{ "videoUrls": ["https://www.facebook.com/share/r/CYg8uitszPX6gRoK/"], "metadataOnly": true }
```

**Output:** array of flat objects, one per input URL. Fields: `videoId`, `inputUrl`, `resolvedUrl`, `title`, `ownerName`, `durationSec`, `publishedAt`, `viewCount`, `quality`, `fileSizeBytes`, `downloadUrl`, `thumbnailUrl`.

**Agent-relevant behaviour:** `maxFileSizeMb` (default 100) rejects oversized videos before download, so a skipped row is a size decision rather than a failure. Join results back on `inputUrl`, not `resolvedUrl`, since a share link resolves to something different. `metadataOnly: true` is the cheap path when you only need the data. Null duration, publish date and view count mean Facebook did not expose them, not that the run failed. The run summary reports `requested / succeeded / failed / failedInputs`.

**Billing:** per delivered row. A run that returns nothing charges for nothing.

### ⚠️ Disclaimer

This Actor reads publicly available Facebook content. You are responsible for using the output lawfully, including under copyright, the GDPR, the CCPA and Facebook's terms where they apply to you. Downloaded video remains the property of its creator — this is a tool for accessing content you already have the right to use, not a licence to redistribute it. Nothing here is legal advice.

### SEO Keywords

facebook video downloader, facebook reels downloader, download facebook video mp4, facebook reel to mp4, facebook video scraper, facebook share link resolver, download fb reels hd, facebook video metadata, facebook watch downloader, facebook page video download, bulk facebook video download, facebook video api, facebook reels archive, facebook content archiving, apify facebook video downloader

# Actor input Schema

## `videoUrls` (type: `array`):

Facebook video or Reel URLs. Supported: share links (facebook.com/share/r/… and /share/v/…), reel links (/reel/…), watch links (/watch?v=…), page video links (/{page}/videos/…), and fb.watch short links.

## `metadataOnly` (type: `boolean`):

Skip the file download and return only video metadata (id, title, owner, duration, publish date, thumbnail). Much cheaper — useful for pre-checking a list before downloading.

## `maxFileSizeMb` (type: `integer`):

Skip any video larger than this, before a single byte is downloaded. Protects a run from one unexpectedly long video consuming the whole budget. Default 100 MB. Ignored when Metadata only is on.

## `facebookCookies` (type: `string`):

OPTIONAL. Public videos download without this. Supply cookies.txt content (Netscape format) from a logged-in Facebook session to download private, followers-only, group, or otherwise login-gated videos that you can see while logged in. Export with a browser extension like 'Get cookies.txt'.

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

A residential proxy is built in at no extra setup — leave the default. Supply your own proxy URLs only if you want to route traffic through your own provider.

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

How many videos to process at the same time (1–5).

## Actor input object example

```json
{
  "videoUrls": [
    "https://www.facebook.com/share/r/CYg8uitszPX6gRoK/"
  ],
  "metadataOnly": false,
  "maxFileSizeMb": 100,
  "proxy": {
    "useApifyProxy": false
  },
  "maxConcurrency": 3
}
```

# 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 = {
    "videoUrls": [
        "https://www.facebook.com/share/r/CYg8uitszPX6gRoK/"
    ],
    "proxy": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("memo23/facebook-video-downloader").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 = {
    "videoUrls": ["https://www.facebook.com/share/r/CYg8uitszPX6gRoK/"],
    "proxy": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("memo23/facebook-video-downloader").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 '{
  "videoUrls": [
    "https://www.facebook.com/share/r/CYg8uitszPX6gRoK/"
  ],
  "proxy": {
    "useApifyProxy": false
  }
}' |
apify call memo23/facebook-video-downloader --silent --output-dataset

```

## MCP server setup

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

```

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/SeeTKRMLgpRBJtGuK/builds/BeLHdZJI6HsxwCVxF/openapi.json
