# Facebook Media Downloader – Video, Reel & Photo Links (`khadinakbar/facebook-media-downloader`) Actor

Download public Facebook videos, Reels, Watch pages, and photos by URL. Returns direct CDN links plus metadata; optionally saves bounded files to run storage. Cookieless, no login. MCP-ready. $0.005/media.

- **URL**: https://apify.com/khadinakbar/facebook-media-downloader.md
- **Developed by:** [Khadin Akbar](https://apify.com/khadinakbar) (community)
- **Categories:** Social media, Videos, MCP servers
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 facebook media resolveds

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?

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 Media Downloader – Video, Reel & Photo Links

Turn a public Facebook **video, Reel, Watch, or photo URL** into **one dataset row** with a direct CDN download link, thumbnail, author, caption, and dimensions when Facebook exposes them. Optionally copy a bounded progressive file into this run's key-value store. Cookieless. MCP-ready.

This Actor is the **URL-in → media-out** tool for known public posts. Prefer [Facebook Video Downloader](https://apify.com/khadinakbar/facebook-video-downloader) when you only need Reels or Watch videos and want that video-only listing; use this Actor when the same job must also include public photos.

### Best fit for this Actor

- You already have a public Facebook Reel, Watch, video, or photo URL and need a direct downloadable link.
- You want cookieless, MCP-ready resolution rather than a page crawl or engagement scrape.
- You need photos and videos in one SKU with predictable Pay per event pricing.

Start with a single URL for agent calls. Continue with a small batch when you are archiving a known list. For page follower counts after you resolve media, continue with [Facebook Followers Scraper](https://apify.com/khadinakbar/facebook-followers-scraper).

### Sibling routing

- Video-only SKU → [Facebook Video Downloader](https://apify.com/khadinakbar/facebook-video-downloader) when you only need Reels/Watch/video and prefer that listing
- Page follower counts → [Facebook Followers Scraper](https://apify.com/khadinakbar/facebook-followers-scraper) when the next step is page metrics rather than media files
- Supported scope here: public video, Reel, Watch, and photo URLs that resolve while logged out
- Route Stories, private posts, Marketplace items, and album crawls to dedicated products instead of this downloader

### Workflow story: from a pasted Reel to a durable link

A social archivist drops a public Reel URL into this Actor. The managed provider chain resolves the public post, and one row lands with an MP4 CDN link, caption, author, and duration. She exports JSON into her archive sheet. When she needs a durable copy later, she re-runs with **Save media files to storage** enabled so a bounded file stays in the run's key-value store.

### Quick start input

```json
{
    "mediaUrls": [
        "https://www.facebook.com/reel/1535656380759655/"
    ]
}
```

`mediaUrls` is the only required field. Accepts `facebook.com`, `m.facebook.com`, and `fb.watch` links for public video, Reel, Watch, and photo URLs.

### Input reference

| Field | Type | What it controls |
|---|---|---|
| `mediaUrls` | array (required) | Public Facebook media URLs |
| `maxMedia` | integer | Budget cap on saved/billed media records (1–1000, default 20) |
| `mediaTypes` | array | Optional keep-filter: `video`, `reel`, `watch`, `photo` |
| `providerOrder` | enum | Managed provider priority (`scrapecreators-first` default) |
| `downloadToStorage` | boolean | Copy progressive MP4/image into run storage |
| `maxFileSizeMB` | integer | Cap per stored file (1–500 MB, default 200) |

### What data you receive

One dataset item represents **one public media asset**.

| Field | What it answers |
|---|---|
| `downloadUrl`, `hdDownloadUrl`, `hlsManifestUrl`, `mimeType` | **Where** to fetch the media |
| `mediaType`, `mediaId`, `durationSeconds`, `width`, `height` | **What** kind of asset it is |
| `title`, `caption`, `thumbnailUrl` | **Context** around the post |
| `authorName`, `authorUrl` | **Who** published it |
| `storedFileUrl` | **Durable copy** when file save is enabled |
| `sourceUrl`, `provider`, `scrapedAt`, `postedAt` | **Provenance** |

```json
{
    "mediaId": "1535656380759655",
    "sourceUrl": "https://www.facebook.com/reel/1535656380759655/",
    "mediaType": "reel",
    "mimeType": "video/mp4",
    "downloadUrl": "https://video.xx.fbcdn.net/o1/v/t2/example.mp4",
    "hdDownloadUrl": null,
    "storedFileUrl": null,
    "caption": "Public reel caption",
    "authorName": "Example Creator",
    "durationSeconds": 23.3,
    "provider": "scrapecreators",
    "scrapedAt": "2026-09-22T12:00:00.000Z"
}
```

Download the dataset as JSON, CSV, Excel, or HTML. Every terminal run also writes `OUTPUT` and `RUN_SUMMARY` with `outcome` (`COMPLETE` / `PARTIAL` / `VALID_EMPTY` / `INVALID_INPUT` / `UPSTREAM_FAILED` / `CONFIG_ERROR`). Inspect that outcome, then read the dataset.

### API example

```bash
curl "https://api.apify.com/v2/acts/khadinakbar~facebook-media-downloader/runs?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "mediaUrls": ["https://www.facebook.com/reel/1535656380759655/"],
    "maxMedia": 1,
    "downloadToStorage": false
  }'
```

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('khadinakbar/facebook-media-downloader').call({
    mediaUrls: ['https://www.facebook.com/photo.php?fbid=1635563591272344'],
    maxMedia: 1,
    mediaTypes: ['photo'],
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

### Best results guidance

- Provide a public URL you can open while logged out.
- Prefer Reel / Watch / photo.php / `/videos/` URLs over ambiguous share wrappers.
- CDN links expire. Use `downloadToStorage` promptly when you need a durable file.
- Validate `OUTPUT.outcome` before treating an empty dataset as a product issue: missing public posts report `VALID_EMPTY` with zero `media-resolved` charges.

### Why AI agents and MCP clients choose this Actor

- **One required input.** `mediaUrls` is the only required field.
- **Predictable cost.** Saved media uses the `media-resolved` Pay per event unit; see the live Pricing tab.
- **Structured output.** Stable keys plus a published dataset schema.
- **Honest outcomes.** Inspect `OUTPUT` for `INVALID_INPUT`, `VALID_EMPTY`, or `UPSTREAM_FAILED`, then read the dataset.

> Resolve these public Facebook media URLs into direct download links with media type, caption, author, and provenance. Return the dataset rows and the run outcome.

MCP tool name: `apify--facebook-media-downloader`. Hosted setup lives at [mcp.apify.com](https://mcp.apify.com). After the call, read the dataset, keep `sourceUrl` / `provider` / `scrapedAt`, and respect the run cost cap.

### Pricing — Pay per event + platform usage

| Event | Price | When charged |
|---|---|---|
| `apify-actor-start` | $0.00005 | Once per valid run start |
| `media-resolved` | $0.005 | Each validated public media row with a usable direct link |
| `media-file-saved` | $0.005 | Each optional file successfully stored |

Platform compute and proxy usage are passed through to the caller (`Pay per event + usage`). Invalid inputs and empty public results are not charged the primary media event. See the Actor **Pricing** tab for the live table.

### Builder's note

First-hand implementation note from live provider probes: Facebook's logged-out HTML is a moving target for direct scrapers. During live probes, ScrapeCreators `GET /v1/facebook/post` returned progressive MP4 fields for Reels and `image_url` for photo.php IDs, with SociaVault as the same-shape fallback. The extractor therefore prefers structured `video.sd_url` / `video.hd_url` and top-level `image_url` before walking nested blobs, and it records provider `not_found` as `VALID_EMPTY` so agents can branch cleanly when a URL is gone.

### Legal / responsible use

Only download media you have the right to use. Respect Meta's terms, copyright, and applicable privacy laws. This Actor returns publicly reachable media links for authorized archival, research, and personal use cases. It does not bypass privacy settings.

Facebook and Meta are trademarks of their owners. This independent Actor is not affiliated with, associated with, or endorsed by Facebook or Meta Platforms, Inc.

### FAQ

**Do I need a Facebook login?** No. Cookies and passwords are not accepted.

**Does it include Stories?** Stories belong on a dedicated Stories product; this Actor covers public video, Reel, Watch, and photo URLs.

**Why is a row missing HD?** Facebook often exposes only one progressive quality to public no-login views.

**Related Actors**

- Prefer [Facebook Video Downloader](https://apify.com/khadinakbar/facebook-video-downloader) for a video-only Store listing and pricing shape
- Continue with [Facebook Followers Scraper](https://apify.com/khadinakbar/facebook-followers-scraper) when you need page follower counts after media resolve

# Changelog

This Actor's version history is a separate document: https://apify.com/khadinakbar/facebook-media-downloader/changelog.md

# Actor input Schema

## `mediaUrls` (type: `array`):

Use this when you have public Facebook video, Reel, Watch, photo, or post URLs and need direct downloadable media links. Example: https://www.facebook.com/reel/1535656380759655/ or https://www.facebook.com/photo.php?fbid=1635563591272344. Accepts facebook.com, fb.watch, and m.facebook.com. Not for private posts, Stories, Marketplace, or page album crawls.

## `maxMedia` (type: `integer`):

Use this to set a hard run-wide cap on saved and billed media records. Defaults to 20; range 1-1000. One Facebook URL can yield more than one media asset. Not a per-URL cap.

## `mediaTypes` (type: `array`):

Optional filter of media kinds to keep after resolve. Leave empty to keep every public video, Reel, Watch, and photo asset the providers return. Use photo to keep still images only, or video/reel/watch for motion media.

## `providerOrder` (type: `string`):

Use this when you need to select the managed public-data provider order. Defaults to ScrapeCreators then SociaVault fallback. Provider-only choices help diagnose upstream availability. This is not a Facebook login, cookie, or proxy setting.

## `downloadToStorage` (type: `boolean`):

Use this when you need the actor to copy an available progressive MP4 or image into this run's key-value store. Defaults to false; direct CDN links are always returned. HLS-only, DRM, expired, or oversized media remain link-only. Only download media you are authorized to save. CDN links expire — save promptly when you need a durable copy.

## `maxFileSizeMB` (type: `integer`):

Use this to cap each optional file written to storage. Defaults to 200 MB; range 1-500 MB. Media exceeding this cap is not downloaded but its direct link remains in the dataset. Only applies when Save media files is enabled.

## Actor input object example

```json
{
  "mediaUrls": [
    "https://www.facebook.com/reel/1535656380759655/",
    "https://www.facebook.com/photo.php?fbid=1635563591272344"
  ],
  "maxMedia": 20,
  "mediaTypes": [],
  "providerOrder": "scrapecreators-first",
  "downloadToStorage": false,
  "maxFileSizeMB": 200
}
```

# Actor output Schema

## `media` (type: `string`):

Normalized public Facebook media results with direct CDN links, optional stored file URL, thumbnail, author, caption, dimensions, and provider.

## `output` (type: `string`):

Stable terminal summary for agents and API consumers.

## `runSummary` (type: `string`):

Detailed run diagnostics, provider attempts, stop reason, and warnings.

# 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 = {
    "mediaUrls": [
        "https://www.facebook.com/reel/1535656380759655/"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("khadinakbar/facebook-media-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 = { "mediaUrls": ["https://www.facebook.com/reel/1535656380759655/"] }

# Run the Actor and wait for it to finish
run = client.actor("khadinakbar/facebook-media-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 '{
  "mediaUrls": [
    "https://www.facebook.com/reel/1535656380759655/"
  ]
}' |
apify call khadinakbar/facebook-media-downloader --silent --output-dataset

```

## MCP server setup

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