# Facebook Photos Scraper — Pages & Photo URLs, No Login (`memo23/facebook-photos-scraper`) Actor

Scrape public Facebook Page photos without logging in. Paste a Page URL or a photo permalink and get the full-size image, Facebook photo link, OCR/alt text, dimensions and page identity. Eight photos per request. Your limit is enforced before each call, so you are never charged past it.

- **URL**: https://apify.com/memo23/facebook-photos-scraper.md
- **Developed by:** [Muhamed Didovic](https://apify.com/memo23) (community)
- **Categories:** Social media, AI
- **Stats:** 20 total users, 18 monthly users, 87.1% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.99 / 1,000 photos

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 Photos Scraper — Pages & Photo URLs, No Login

Turn any public Facebook Page into a stream of photo rows. Paste a Page URL or a single photo permalink and get the full-size image, Facebook photo link, OCR/alt text, and page identity — no login.

One row per photo. Your limit is the last photo you pay for.

### Why Use This Scraper?

- Public Pages and photo permalinks in the same run
- Full-size image URL plus Facebook's own photo page
- OCR / alt text Facebook already attaches (`accessibility_caption`)
- Hard cap before each GraphQL page — extras in the last batch are dropped, not charged
- Date window sent as Facebook's own `created_time_start` / `created_time_end`
- Residential proxy included; leave the proxy field empty
- Same photos walk as the official Apify actor, at $0.99 / 1,000 photos (theirs is $3 / 1,000)

### Overview

Built for researchers, journalists, brand teams, and agencies who need the photos a public Facebook Page actually published — not the posts around them.

Every input becomes a **photo** row (`dataType: "photo"`). A Page URL walks the photos tab. A `/photo/?fbid=…` URL fetches that one image. Mixing both is fine: permalinks run first, then each Page.

This actor does not scrape albums-of-others (`photos_of`), private profiles, or anything behind a login wall.

### Supported Inputs

| Input | Example | What happens |
|---|---|---|
| Page URL | `https://www.facebook.com/nasa` | Walks the public photos tab |
| Page handle | `nasa` | Same as the Page URL |
| Photos tab | `https://www.facebook.com/nasa/photos` | Same walk; tab suffix is stripped to the Page |
| Photo permalink | `https://www.facebook.com/photo/?fbid=1629624498532920` | One photo, one request |
| `photo.php` | `https://www.facebook.com/photo.php?fbid=…` | Same as permalink |

**Not supported:** private profiles, login-only pages, personal `photos_of` albums, Facebook Groups, Reels-as-video, post URLs (use [Facebook Page Posts Scraper](https://apify.com/memo23/facebook-page-posts-scraper)).

### Use Cases

| Who | What they take |
|---|---|
| Brand / social | Every public photo a competitor Page posted |
| Journalism / research | Image URLs + Facebook's own alt/OCR text |
| Creative / moodboards | Full-size CDN links, no browser click-through |
| Agencies | A CSV of `facebookUrl` + `image` + `ocrText` per client Page |

### How It Works

1. Open the Page (or the photo permalink) logged out.
2. Read the `photos_by` collection id Facebook already put in the HTML.
3. POST `ProfileCometAppCollectionPhotosRendererPaginationQuery` to `/api/graphql/` — 8 photos per page, cursor from `page_info.end_cursor`.
4. Map each edge to one row: `id`, `image`, `facebookUrl`, `ocrText`, page identity.
5. Stop at `resultsLimit`. Charge one `photo` event per row pushed.

### Input Configuration

| Field | Type | Default | What it does |
|---|---|---|---|
| `startUrls` | array | required | Page URLs, handles, and/or photo permalinks |
| `resultsLimit` | integer | `50` | Hard cap across the whole run |
| `onlyNewerThan` | date | — | `created_time_start` on the GraphQL query |
| `onlyOlderThan` | date | — | `created_time_end` on the GraphQL query |
| `proxy` | object | empty | Leave empty. Residential is included. |

**50 photos from one Page**

```json
{
  "startUrls": [{ "url": "https://www.facebook.com/nasa" }],
  "resultsLimit": 50
}
```

**One photo permalink**

```json
{
  "startUrls": [{ "url": "https://www.facebook.com/photo/?fbid=1629624498532920" }],
  "resultsLimit": 1
}
```

**Date window**

```json
{
  "startUrls": [{ "url": "https://www.facebook.com/nasa" }],
  "resultsLimit": 100,
  "onlyNewerThan": "2026-01-01",
  "onlyOlderThan": "2026-06-01"
}
```

### Output Overview

Each dataset item is one photo. The four fields the official Apify actor shows (`facebookUrl`, `image`, `dataType`, `ocrText`) are always present. Extra fields carry page identity and a thumbnail when Facebook sent one.

### Output Samples

Page walk (`https://www.facebook.com/nasa`):

```json
{
  "dataType": "photo",
  "id": "1629528928542477",
  "facebookId": "100044561550831",
  "facebookUrl": "https://www.facebook.com/photo.php?fbid=1629528928542477&set=pb.100044561550831.-2207520000&type=3",
  "url": "https://www.facebook.com/photo.php?fbid=1629528928542477&set=pb.100044561550831.-2207520000&type=3",
  "image": "https://scontent.xx.fbcdn.net/v/t39.99422-6/…",
  "imageHeight": 1707,
  "imageWidth": 1920,
  "thumbnail": "https://scontent.xx.fbcdn.net/v/t39.99422-6/…",
  "ocrText": "NASA Deputy Administrator Matt Anderson, center, Ambassador of Djibouti to the United States, Mohamed Siad Douale, left, and Assistant Secretary of State for African Affairs, Frank Garcia, right, pose for a group photograph…",
  "pageUrl": "https://www.facebook.com/nasa",
  "pageName": "NASA - National Aeronautics and Space Administration",
  "pageId": "100044561550831",
  "inputUrl": "https://www.facebook.com/nasa",
  "pageAdLibrary": null
}
```

`ocrText` is Facebook's `accessibility_caption`. The placeholder *"No photo description available."* is stored as `null`.

### Key Output Fields

**Identity**

| Field | Meaning |
|---|---|
| `id` | Photo fbid |
| `facebookId` | Same fbid (official-actor alias) |
| `facebookUrl` / `url` | Facebook photo page |
| `dataType` | Always `"photo"` |

**Image**

| Field | Meaning |
|---|---|
| `image` | Full-size CDN URL (`viewer_image`) |
| `imageHeight` / `imageWidth` | Pixels when Facebook sent them |
| `thumbnail` | Grid thumbnail (`image.uri`) |
| `ocrText` | Alt / OCR caption, or `null` |

**Page**

| Field | Meaning |
|---|---|
| `pageUrl` / `pageName` / `pageId` | The Page the photo belongs to |
| `inputUrl` | What you pasted |
| `pageAdLibrary` | Ads Library stub when the Page HTML had one |

### Pricing

| Event | When | Price |
|---|---|---|
| Actor start | Once per run, per GB of memory | $0.005 |
| Photo | Each photo row pushed | $0.00099 |

Free Apify accounts are capped at 10 photos from 1 Page. You are not charged for extras Facebook returns past your `resultsLimit`.

### FAQ

**Do I need a Facebook login?**
No. The walk is logged out (`__user=0`). Private or restricted Pages fail with a login-wall error.

**Why did I get 48 photos when I asked for 50?**
Facebook serves 8 photos per GraphQL page. The run stops at your cap; if the last full page lands at 48 and the next page is empty or the cursor stalls, you keep 48.

**Is `ocrText` real OCR?**
It is Facebook's own accessibility caption — the same string the official Apify actor writes to `ocrText`. It is not a second-pass OCR model.

**Can I scrape a single photo URL?**
Yes. `/photo/?fbid=…` and `photo.php?fbid=…` are first-class inputs.

**Does this walk albums?**
It walks the Page's `photos_by` tab (photos the Page posted). Not `photos_of` and not a named album URL.

### Support

Open an issue on the actor's Issues tab on Apify. Include the input URL and the run ID.

### Additional Services

Need a different export shape, a scheduled Page list, or photos plus the parent post text in one dataset? Say what the job is — custom work is available.

### Explore More Scrapers

- [Facebook Page Posts Scraper](https://apify.com/memo23/facebook-page-posts-scraper) — feed, permalinks, reels, reactions
- [Facebook Comments Scraper](https://apify.com/memo23/apify-facebook-comments-ppr)
- [Facebook Reels Scraper](https://apify.com/memo23/facebook-reels-scraper)

### 🤖 For AI Agents & LLM Apps

**Purpose:** scrape public Facebook Page photos or a single photo permalink. No login.

**Minimal input**

```json
{
  "startUrls": [{ "url": "https://www.facebook.com/nasa" }],
  "resultsLimit": 50
}
```

**Output fields (flat):** `dataType`, `id`, `facebookId`, `facebookUrl`, `url`, `image`, `imageHeight`, `imageWidth`, `thumbnail`, `ocrText`, `pageUrl`, `pageName`, `pageId`, `inputUrl`, `pageAdLibrary`

**Billing:** `apify-actor-start` $0.005 + one `photo` event at $0.00099 per dataset row. Free Apify accounts are capped at 10 photos from 1 Page.

**Behavior:** 8 photos per GraphQL request. Date filters are query arguments, not a client-side filter. Login walls fail the Page, not the run (other URLs still run). An empty dataset fails the run.

### ⚠️ Disclaimer

This Actor is an independent tool and is not affiliated with, endorsed by, or sponsored by Meta Platforms, Inc. or Facebook. All trademarks mentioned are the property of their respective owners.

The scraper accesses only publicly available Facebook Page photos — no authenticated endpoints, paid features, or content behind the Facebook login wall. Users are responsible for ensuring their use complies with Facebook's Terms of Service, applicable data-protection law (GDPR, CCPA, etc.), and any contractual obligations of their own organization.

### SEO Keywords

facebook photos scraper, facebook page photos scraper, scrape facebook photos, facebook image scraper, facebook photo url extractor, facebook ocr text scraper, facebook accessibility caption, facebook page image downloader, facebook photo permalink scraper, facebook scontent scraper, facebook photos tab scraper, facebook public photos, facebook photo dataset, facebook competitor photos, facebook brand image monitor, facebook page media export, facebook photo csv, facebook photo json, facebook photo api alternative, nasa facebook photos

# Actor input Schema

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

Public Facebook Pages to walk (https://www.facebook.com/<page>, a bare handle like `nasa`, or `profile.php?id=<id>`), and/or photo permalinks (`/photo/?fbid=...`, `photo.php?fbid=...`). Mix them in one run — photo URLs are fetched first, one request each.

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

Hard cap across the whole run. Facebook returns eight photos at a time; extras in the last batch are discarded rather than delivered and charged.

## `onlyNewerThan` (type: `string`):

Optional cutoff, e.g. <code>2026-01-01</code>. Sent as Facebook's own created\_time\_start on the photos query.

## `onlyOlderThan` (type: `string`):

Upper bound of the date window, e.g. 2026-06-01. Sent as created\_time\_end.

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

Leave empty. Residential proxy is included and is not billed to you. Set this only if you want to route through your own proxies instead.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.facebook.com/nasa"
    }
  ],
  "resultsLimit": 50,
  "proxy": {}
}
```

# 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/nasa"
        }
    ],
    "resultsLimit": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("memo23/facebook-photos-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/nasa" }],
    "resultsLimit": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("memo23/facebook-photos-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/nasa"
    }
  ],
  "resultsLimit": 50
}' |
apify call memo23/facebook-photos-scraper --silent --output-dataset

```

## MCP server setup

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