# Facebook Photos Scraper: Albums, Dates, No Login (`automation_craft/facebook-photos-scraper`) Actor

Scrape the photos of public Facebook pages and profiles, no login, from page, album, photo or share links. Rows: full size image, alt text, posting date, caption, exact reactions, comments and shares, album and post. Tagged photos and every album. JSON, CSV, API. Pay per photo.

- **URL**: https://apify.com/automation_craft/facebook-photos-scraper.md
- **Developed by:** [Automation Craft](https://apify.com/automation_craft) (community)
- **Categories:** Social media, Marketing, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.94 / 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.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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: Albums, Dates, No Login

**Facebook Photos scraper** for the photos of public Facebook pages and profiles, with no login, no cookies and no Facebook account: give page links, usernames, numeric ids, album links, photo links, share links or a link to a text file or Google Sheet, and get each photo as a row with its full size image link, size and Facebook's own alt text, and its details: the time it was posted, its caption, exact reaction counts by type, comments, shares, its post, its uploader and its album. One row per page adds the page's followers and about line; one row per album adds its title, description, item count and engagement. Pay per photo, from $0.94 per 1,000.

Built for social media and brand teams, agencies auditing client pages, competitor and campaign research, archivists, researchers building image data sets, and scheduled runs in n8n, Make or Zapier. Rows carry what Facebook shows a visitor who is not logged in; use them under the rules that apply to you.

#### At a glance

- Three ways to read a page: its **Photos tab** (Facebook's own list, newest first), its **tagged photos**, and **every album** (each album as a row, then every photo of each album: the complete set of the page's public photos).
- **Every photo with its details** at the photo price: posting time, caption with hashtags and mentions, exact reactions with the split by type (like, love, care, haha, wow, sad, angry), comments, shares, post id and link, uploader and album id. Turn details off for the fastest image only rows.
- **Facebook's own date window**: only photos posted between two days, sent to Facebook itself, so a past month is reached at once.
- **Links of every kind**: pages, profiles, numeric ids, `photo.php?fbid=` and `/photo/?fbid=` links, album links, and Facebook share links.
- Filters: words in the caption, hashtags or alt text (to keep or to leave out), a minimum number of reactions, a minimum image width. Photos a filter leaves out are free.
- **Comments** (add-on): each delivered photo's and album's comments, oldest first, newest first or most relevant, with replies if you like.
- **Stored image copies** (add-on): each full size image kept as a file, in the run's storage or in a named store of yours that stays until you delete it, with a link that keeps working after Facebook's own image link expires.
- Free page details: category, address, phone, e-mail, websites, hours, price range, rating, and from the Meta Ad Library whether the Page runs ads now.

### Quick start

1. Open the Actor and type one or more values in **Facebook pages, profiles, albums or photos**, one per line, for example `https://www.facebook.com/natgeo` or just `natgeo`.
2. Choose **Which photos of a page**: the Photos tab (the form's choice), tagged photos, every album, or several.
3. Set **Photos per page** (the form starts at 10).
4. Optional: a date window, words, **Minimum reactions**, **Minimum width**, the **Comments** or **Stored image copies** add-ons, **Page details**.
5. Click **Start**. Download the rows as JSON, CSV or Excel, or read them through the API.

An input with no value at all returns a free sample: the newest 3 photos of facebook.com/natgeo, with only the start fee charged.

### What you get

Every run writes rows of six types to its dataset. The Actor's **Photos** view shows the image itself next to the page, the photo link, the time, the caption, the alt text, the counts and the size; the **Albums** view shows the album rows.

#### Photo rows

| Field | What it is | Filled |
|---|---|---|
| `photoId`, `url` | Facebook's photo id and the photo's own link (`facebook.com/photo/?fbid=<id>`, no page or person part) | always |
| `imageUrl`, `imageWidth`, `imageHeight`, `orientation`, `aspectRatio` | the full size image on Facebook's file host and its size | always |
| `imageUrlExpiresAt` | when Facebook's own image link stops working (use the Stored image add-on for a copy of your own) | always |
| `thumbnailUrl` | Facebook's small crop of the image | on the Photos and tagged tabs |
| `altText`, `altTextIsPlaceholder` | Facebook's own description of the image ("May be an image of mountain and nature"); the flag is true for its placeholder "No photo description available." | always |
| `publishedAt`, `ageHours` | when the photo was posted (UTC) and its age at the run | with details (the default) |
| `caption`, `hashtags`, `mentions`, `linksInCaption` | the photo's text exactly as Facebook serves it, with its hashtags, mentioned pages and people, and the links written in it | with details, when the post has text |
| `reactionCount`, `reactionsByType` | exact reactions and their split by type | with details |
| `commentCount`, `shareCount`, `engagementCount`, `engagementRate` | exact comments and shares; reactions plus comments plus shares, and that sum over the page's followers | with details |
| `postId`, `postUrl`, `postType` | the post the photo was published in (single photo post or a photo of several) | with details (`postUrl` for a Page's photos, or with personal data on) |
| `ownerName`, `ownerId`, `ownerType` | who posted the photo | with details (`ownerId` for a Page's photos, or with personal data on) |
| `albumId`, `albumTitle` | the photo's album (`albumTitle` in the albums mode and for album links) | with details, and in the albums mode |
| `source` | `photos`, `tagged`, `album`, `photo_link` or `share_link` | always |
| `detailsStatus` | `ok`, `not_requested` (details off) or `failed` (Facebook did not give them: the row is free) | always |
| `pageName`, `pageType`, `pageId`, `pageUsername`, `pageUrl`, `pageVerified`, `pageFollowers` | the page the photo was read from (a person's id, username and link only with personal data on) | for pages |
| `storedImageUrl`, `storedImageKey`, `storedImageBytes`, `storedImageStatus` | the stored copy of the image (Stored image add-on) | with the add-on |

Measured over 208 photos of 7 pages of different kinds on 2026-10-24 (a media brand, a sportswear brand, a news outlet, a space agency, a creator, a public figure's profile and a small bakery; own photos from 2026 and 2019 and tagged photos): posting time, reactions, comments, shares, post id, uploader, album and full size image on 208 of 208; reactions by type on 188 (the other 20 have no reaction); a caption on 139 (many pages post photos without text: 11 of 32 of the sportswear brand's photos have one, 31 of 32 of the media brand's).

#### Album rows (the albums mode and album links)

`albumId`, `url` (`facebook.com/media/set/?set=a.<id>`), `title`, `description`, `hashtags`, `itemCount` (Facebook's count, which includes items a visitor who is not logged in cannot see), `createdAt` (the time of the album's own post, for albums posted as a post), `postId`, `reactionCount`, `reactionsByType`, `commentCount`, `shareCount`, `coverImageUrl`, the page's facts.

#### Page rows

One per page: name, type (page or person), id, username, link, verified mark, exact followers, talking about, were here, about line, picture; with **Page details**: category, address, phone, e-mail, websites, business hours, price range, rating, and whether the Page runs ads now with its active ads count, its Ad Library link, its creation date, its name changes and the countries of the people who manage it. The row comes after the page's photos. Page details are read for a Page that delivered a photo in the run; `pageDetailsStatus` says `ok`, `not_a_page` (a person's profile), `no_photos` (the page delivered no photo) or `not_read` (Facebook did not answer, or the run's allowance for options had no room left: on runs of many pages with one or two photos each, the last pages can come back without them).

#### Comment rows (Comments add-on)

`commentId`, `commentedType` (photo or album), `photoId` or `albumId`, `itemUrl`, `text`, `createdAt`, `authorName`, `authorIsPage` (a person's id and link only with personal data on), `reactionCount`, `reactions`, `replyCount`, `parentCommentId` and `depth` for replies, `commentUrl`.

#### Coverage, status and summary rows (free)

- A **coverage** row per value of the input: what was read for each photo source (calls, photos read and delivered, whether Facebook's end was reached, the sliding pages repaired), the albums read, and why the walk ended.
- **Status** rows: a page, album, photo or share link Facebook does not show, values that are not usable, an add-on that could not be read, the sample. All free.
- A **summary** row last: the run's counters, the events charged, the requests made.

#### How fast

Measured on Apify with the datacenter proxy on 2026-10-24 and 2026-10-25 (whole runs, start included, three runs of each at different hours): 10 photos with their details in 9 to 16 seconds; 69 to 83 photos in a run stopped after 60 seconds; 56 photos of one month in 73 to 89 seconds; 79 photos without details in 9 to 17 seconds; an album link with 16 photos in 13 to 26 seconds; 1,000 photos of one page in 11 to 31 minutes with their details and 2 to 6 minutes without them. Details are read 3 at a time; each photo costs one small extra call. Facebook answers slower at some hours.

### How much does it cost to scrape Facebook photos?

Pay per event: you pay for what is delivered, never for misses.

| Event | Free | Bronze | Silver | Gold |
|---|---|---|---|---|
| Photo, per 1,000 | $1.32 | $1.20 | $1.09 | $0.94 |
| Page, per 1,000 pages | $1.55 | $1.40 | $1.28 | $1.10 |
| Album, per 1,000 albums | $1.99 | $1.82 | $1.65 | $1.42 |
| Comment (add-on), per 1,000 | $0.27 | $0.24 | $0.22 | $0.19 |
| Stored image (add-on), per 1,000 | $0.99 | $0.98 | $0.97 | $0.95 |
| Actor start, per run | $0.008 | $0.008 | $0.008 | $0.008 |

Platinum and Diamond plans pay the Gold price. The Actor start is charged by Apify once per run (per GB of memory: this Actor runs at 256 MB) and has no plan discount. The Store pricing card shows these same prices per 1,000 events: "$0.94 / 1,000" on the Photo row means one photo costs less than a tenth of a cent.

- **Photo**: one photo row delivered for the first time in the run, with its details when they are on. A photo met twice (on two tabs, in two albums, by two links) is charged once.
- **Page**: one page row, after the page's photos, charged once when the page delivered at least one charged photo; a page that delivers no charged photo gets its row free. Never charged for photo, album or share links.
- **Album**: one album row (the albums mode, album links).
- **Comment** and **Stored image**: only when you turn the add-on on; a stored image is charged only when the image was stored.
- Free: photos a filter leaves out, repeats, pages, albums or photos that are missing or not public, refused calls, invalid input, page details, the coverage, status and summary rows, and a photo whose details Facebook did not give (delivered with `detailsStatus: failed`).

Examples at the Gold price: 100 photos of one page with their details cost $0.008 + $0.0011 + 100 x $0.00094 = $0.103; 1,000 photos cost about $0.95; the 20 albums of a page with 50 photos each cost $0.008 + $0.0011 + 20 x $0.00142 + 1,000 x $0.00094 = $0.98.

#### The work allowance

Work that ends without a charged row (photos a filter leaves out, missing pages, refused calls) is bounded in every run by an allowance that grows with the events charged, so a filter nothing passes stops early, free, with a status row instead of reading a page's whole history.

### Input

| Field | What it does |
|---|---|
| **Facebook pages, profiles, albums or photos** (`pages`) | One per line: a page or profile link, username or numeric id; an album link; a photo link; a share link. Up to 500. Also read as `startUrls`, `profileUrls`, `facebook_urls`, `username`, `pageNames`, `pageIds`, `pageId` or `profileId`. |
| **Values from a file or Google Sheet link** (`pagesListUrl`) | One https link to a public text or CSV file, or a Google Sheet shared with anyone with the link. |
| **Which photos of a page** (`photoSources`) | `photos` (the Photos tab, newest first), `tagged`, `albums` (every album, complete); one or several. Also read as `photoType` (`photos_by`, `photos_of`). |
| **Photos per page** (`maxPhotosPerPage`) | For each page and each source (50 when empty). Also read as `resultsLimit`, `maxPhotos`, `photos_count`, `maxPhotosPerProfile`. |
| **Photos in the whole run** (`maxItems`) | A bound on the run's photos. Also read as `maxResults`. |
| **Albums per page** (`maxAlbumsPerPage`), **Photos per album** (`maxPhotosPerAlbum`) | For the albums mode (50 and 1,000 when empty); 0 photos per album delivers the album rows alone. |
| **Posted on or after** (`onlyPhotosNewerThan`), **Posted on or before** (`onlyPhotosOlderThan`) | A date window: YYYY-MM-DD, an ISO time, `today`, `yesterday`, or `30 days`, `2 weeks`, `3 months`, `1 year` back from the run's start (UTC days, both ends included); `sinceDays` takes a number. |
| **Text contains** (`includeKeywords`), **Text does not contain** (`excludeKeywords`) | Whole words or phrases on the caption, the hashtags and the alt text, case and accents ignored. |
| **Minimum reactions** (`minReactions`), **Minimum width** (`minWidth`) | Leave out photos below either. |
| **Photo details** (`includeDetails`) | On by default. Off: the faster tab rows only (id, link, image, size, alt text). The albums mode and links always read the details. |
| **Comments** (`includeComments`), **Comments per photo or album** (`maxCommentsPerItem`), **Comment order** (`commentsOrder`), **Replies** (`includeReplies`, `maxRepliesPerComment`) | The Comments add-on. |
| **Stored image copies** (`storeImages`), **Store for the images** (`imageStoreName`) | The Stored image add-on, and the name of a key-value store of yours to keep the images in (created by the first run that names it, kept until you delete it, used again by later runs that give the same name; empty: the run's own storage, kept as long as your plan keeps run data). A store of that name this Actor did not create (another Actor's, for example) cannot be opened under its limited permissions: the images then go to the run's own storage and a status row says so. Also read as `keyValueStorePrefix`. |
| **Page details** (`includePageDetails`) | Free; Pages only, for a Page that delivered a photo (its row then carries them, after its photos). |
| **Include personal data** (`includePersonalData`) | Off by default; see Personal data. |
| **Row format** (`outputFormat`) | `full` or `compact` (24 fields). |
| **Pages at once** (`maxConcurrency`), **Pause between calls** (`requestDelayMs`), **Stop after** (`maxRunSeconds`), **Proxy** (`proxyConfiguration`) | Run settings. Apify's datacenter proxy by default; your own proxy links or no proxy are possible. |

Example input:

```json
{
  "pages": ["https://www.facebook.com/natgeo", "https://www.facebook.com/media/set/?set=a.10151666622313445"],
  "photoSources": ["photos", "tagged"],
  "maxPhotosPerPage": 100,
  "onlyPhotosNewerThan": "3 months"
}
```

#### The Photos tab and the albums mode

The Photos tab is Facebook's own list of a page's photos, newest first, and the fastest way to the latest photos and to a date window. On some pages Facebook starts serving the tab in pieces that overlap (most of a page repeats the page before); the Actor detects that and goes on from the oldest photo it was given, so it keeps going, but such a walk can pass over older photos. For a page's complete public photo set use **Every album**: each album is read to its end (a media brand's main album of 6,129 photos in one walk), and a photo that sits in two albums is delivered once.

### Limits

- What Facebook shows a visitor who is not logged in. A private profile, a page that shows its photos only to logged in visitors, and photos with a restricted audience are not read; a free status row says so.
- Album counts include items a visitor who is not logged in cannot see (a sportswear brand's "Profile pictures" counts 29 and shows 6).
- The image links on Facebook's file host expire (`imageUrlExpiresAt`); the Stored image add-on keeps a copy: in the run's own storage for as long as your plan keeps run data, or for good in a named store you give (`imageStoreName`).
- A photo near a date window's edge can fall outside it by its own time: it is left out free.

### Personal data

Off by default (`includePersonalData`). With it off: a person's profile (a public figure's included) keeps its name and loses its id, username, link and picture; the uploader of a photo that is not the Page itself (tagged photos, photo and album links, a person's own photos) keeps its name and loses its id and post link; people mentioned in captions and commenters keep their names without ids or links; phone numbers and e-mail addresses written in captions and comments are not listed as fields. Captions, album descriptions and comments are delivered exactly as Facebook serves them. With it on, those fields are filled. You are responsible for a lawful use of personal data (GDPR included).

### What this Actor does NOT do

- No login, cookies or private content: it reads what a visitor who is not logged in sees.
- No "only new photos since the last run" or monitor mode: schedule the Actor with Apify's scheduler and keep the photos you have by their `photoId`.
- No text read out of the images, no image labels or logo detection with an outside vision service: Facebook's own alt text is on every row.
- No posts, reels or videos: those are the jobs of our Facebook Posts, Reels and Video Search listings.
- No tags of people in a photo.

### API examples

Run it and get the rows (replace `<TOKEN>`):

```bash
curl -X POST "https://api.apify.com/v2/acts/automation_craft~facebook-photos-scraper/run-sync-get-dataset-items?token=<TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"pages": ["natgeo"], "maxPhotosPerPage": 20}'
```

Node.js:

```js
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<TOKEN>' });
const run = await client.actor('automation_craft/facebook-photos-scraper').call({ pages: ['natgeo'], photoSources: ['albums'], maxAlbumsPerPage: 5 });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.filter((x) => x.type === 'photo').length);
```

Python:

```python
from apify_client import ApifyClient
client = ApifyClient("<TOKEN>")
run = client.actor("automation_craft/facebook-photos-scraper").call(run_input={"pages": ["natgeo"], "onlyPhotosNewerThan": "30 days"})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    if item["type"] == "photo":
        print(item["publishedAt"], item["reactionCount"], item["imageUrl"])
```

### FAQ

#### How do I download all the photos of a Facebook page?

Give the page and choose **Every album**: every album of the page is read to its end and every public photo becomes a row with its full size image link. Turn on **Stored image copies** to keep each image as a file, in the run's storage or in a store of yours that stays (**Store for the images**), then download the files or export the rows to CSV.

#### Can I download the photo albums of someone else's Facebook page?

Yes, when the page shows them to visitors who are not logged in: give the page with **Every album**, or give an album's own link. Each album comes as a row with its title, description, item count and engagement, followed by its photos.

#### How do I find the date a Facebook photo was posted?

Every photo row carries `publishedAt`, the time Facebook gives for the photo (UTC), read from the photo's own details. Use **Posted on or after** and **Posted on or before** to get only the photos of a period.

#### Can I scrape Facebook page photos without logging in?

Yes. The Actor reads what Facebook shows a visitor who is not logged in, through Apify's proxy, with no account, cookies or password of yours.

#### Why does this Actor run with limited permissions?

It needs only its own run's storage: the dataset it writes, and the run's key-value store for its run record and, with the Stored image add-on, the image files (or the one named store you give it for them). Limited permissions keep it from reading or changing anything else in your account.

### More data tools by Automation Craft

- [Facebook Reels Scraper: Views, Likes, No Login](https://apify.com/automation_craft/facebook-reels-scraper)
- [Facebook Posts Scraper - Page Posts, No Login](https://apify.com/automation_craft/facebook-posts-scraper)
- [Facebook Video Search Scraper: Reels, No Login](https://apify.com/automation_craft/facebook-video-search-scraper)
- [Facebook Comments Scraper: Replies, No Login](https://apify.com/automation_craft/facebook-comments-scraper)
- [Facebook Post Scraper: Reactions and Shares by URL](https://apify.com/automation_craft/facebook-post-scraper)
- [Facebook Groups Scraper: Posts of Public Groups](https://apify.com/automation_craft/facebook-groups-scraper)
- [Facebook Page ID Finder: Names to Page IDs](https://apify.com/automation_craft/facebook-page-id-finder)
- [Instagram Posts Scraper: Profiles, Reels, No Login](https://apify.com/automation_craft/instagram-posts-scraper)

### Changelog

- 0.1 (2026-10-24): first version: the Photos tab, tagged photos and every album of a page, album, photo and share links, photo details, comments and stored image copies.

# Changelog

This Actor's version history is a separate document: https://apify.com/automation_craft/facebook-photos-scraper/changelog.md

# Actor input Schema

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

One per line: a public page or profile (facebook.com/natgeo, facebook.com/natgeo/photos/, facebook.com/profile.php?id=100044623170418, facebook.com/people/Name/100044623170418/, a username such as natgeo or @natgeo, or a numeric id), an album link (facebook.com/media/set/?set=a.528642321966536), a photo link (facebook.com/photo/?fbid=1699318501565573, photo.php?fbid=..., facebook.com/natgeo/photos/a.528642321966536/1699318501565573/) or a share link (facebook.com/share/...). Up to 500. Links of a post, reel, video, group or event are skipped free. Also read as startUrls, profileUrls, facebook_urls, username, pageNames, pageIds, pageId or profileId.

## `pagesListUrl` (type: `string`):

One https link to a public text or CSV file of up to 1 MB, or to a Google Sheet shared with "anyone with the link" (its first tab, or the tab in the link, is read as CSV). Every cell that names facebook.com is read, and in a file of one column every line (a page, album, photo or share link, a username or a numeric id; a value of another kind is skipped free). It joins the values above (at most 500 together). A link that carries a password or token is refused.

## `photoSources` (type: `array`):

photos: the page's Photos tab, newest first, Facebook's own list (the default). tagged: the photos other accounts tagged the page in. albums: every album of the page, each with its own row, and every photo of each album (the complete set of the page's public photos, album by album). Several can be chosen; a photo met twice is delivered once. Empty: photos. Also read as photoType (photos_by or photos_of).

## `maxPhotosPerPage` (type: `integer`):

How many photos to deliver for each page and each source chosen (photos, tagged, albums), 50 when empty. Photos left out by a filter do not count. Also read as resultsLimit, maxPhotos, photos_count or maxPhotosPerProfile.

## `maxItems` (type: `integer`):

An upper bound on the photos the whole run delivers, across every value. Empty: no bound beyond the photos per page and your charge limit. Also read as maxResults.

## `maxAlbumsPerPage` (type: `integer`):

With the albums source: how many albums of each page to read, in the order Facebook lists them (50 when empty). Also read as max_albums_per_profile.

## `maxPhotosPerAlbum` (type: `integer`):

With the albums source or an album link: how many photos of each album to deliver (1000 when empty). 0 delivers the album rows alone. Also read as photos_per_album.

## `onlyPhotosNewerThan` (type: `string`):

Only photos posted on or after this day (UTC): YYYY-MM-DD, an ISO time, today, yesterday, or a relative "7 days", "2 weeks", "3 months", "1 year" counted back from the run's start. Sent to Facebook as its own date window on the Photos and tagged tabs; in the albums mode judged on each photo's own time. Also read as onlyNewerThan, photos_newer_than, dateFrom or newerThan; sinceDays takes a number of days.

## `onlyPhotosOlderThan` (type: `string`):

Only photos posted on or before this day (UTC), the same forms as the start. Also read as onlyOlderThan, photos_older_than, dateTo or olderThan.

## `includeKeywords` (type: `array`):

Only photos whose caption, hashtags or Facebook alt text contain at least one of these words or phrases, as whole words, case and accents ignored. Photos left out are free. Also read as keywords.

## `excludeKeywords` (type: `array`):

Leave out photos whose caption, hashtags or alt text contain any of these words or phrases (the same matching). Photos left out are free.

## `minReactions` (type: `integer`):

Leave out photos with fewer reactions than this. Photos left out are free.

## `minWidth` (type: `integer`):

Leave out photos whose full size image is narrower than this many pixels. Photos left out are free.

## `includeDetails` (type: `boolean`):

On (the default): each photo's own details are read and delivered: posting time, caption with hashtags and mentions, exact reactions by type, comments, shares, post id and link, uploader, album. No extra charge. Off: the faster rows of the Photos and tagged tabs only (id, link, image, size, alt text); the albums mode and links always read the details.

## `includeComments` (type: `boolean`):

Deliver the comments of each delivered photo and album as rows of their own, up to the number below, in the order chosen below. Charged as the Comment event per comment row. Commenters' names are delivered; their ids and profile links only with personal data on. Also read as include_album_comments.

## `maxCommentsPerItem` (type: `integer`):

With comments on: how many comment rows (replies included) to deliver for each photo or album (20 when empty). Also read as comments_limit.

## `commentsOrder` (type: `string`):

With comments on: oldest first (the default), newest first, or Facebook's most relevant first. Also read as comment_filter (most_relevant, newest, all_comments).

## `includeReplies` (type: `boolean`):

With comments on: read the replies under each comment too (charged as Comment rows, inside the comments per photo or album).

## `maxRepliesPerComment` (type: `integer`):

With replies on: how many replies to read under each comment (10 when empty).

## `storeImages` (type: `boolean`):

Keep each delivered photo's full size image as a file in the run's key-value store (photo-<id>.jpg) and give its link in storedImageUrl, which keeps working after Facebook's own image link expires (imageUrlExpiresAt). Charged as the Stored image event on each image stored; an image that could not be stored is not charged. Also read as storePhotos.

## `imageStoreName` (type: `string`):

With stored image copies on: the name of a key-value store in your Apify account to keep the images in, for example facebook-photos (letters, digits and hyphens inside the name, 63 characters at most). It is created when missing and kept until you delete it, so its image links keep working after the run's own storage is removed; a photo stored again keeps one file (photo-<id>.jpg). Empty: the run's own key-value store, kept as long as your plan keeps a run's storage. Also read as keyValueStorePrefix or keyValueStoreName.

## `includePageDetails` (type: `boolean`):

Add each Page's About tab and its Meta Ad Library facts to its page row: category, address, phone, e-mail, websites, business hours, price range, the rating line, and whether the Page runs ads now (with its active ads count, Ad Library link, creation date, name changes and the countries of the people who manage it). No extra charge; read for Pages only (never for a person's profile), for a Page that delivered a photo in the run, after its photos; its pageDetailsStatus says ok, not_a_page, no_photos or not_read (Facebook did not answer, or the run's allowance for options had no room left).

## `includePersonalData` (type: `boolean`):

Off: a person's profile (a public figure's included) keeps its name, and its profile id, username, link and picture are empty; the uploader of a photo that is not the Page itself (tagged photos, photo and album links) keeps its name without its id or post link; commenters and mentioned people keep their names without ids or links; phone numbers and e-mail addresses read from captions and comments are not listed. On: those fields are filled. You are responsible for a lawful use of personal data (GDPR included).

## `outputFormat` (type: `string`):

full: every field of a photo. compact: 24 fields most buyers sort, chart and download by (ids, link, image, size, alt text, caption, time, counts, album, post, uploader, page, stored image link).

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

How many values to read at the same time (1 to 3).

## `requestDelayMs` (type: `integer`):

The pause between two calls of one page, in milliseconds (200 to 10000; 300 when empty).

## `maxRunSeconds` (type: `integer`):

End the run after this many seconds with what was read so far (60 to 86400). Empty: the run's own timeout.

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

Apify's datacenter proxy by default (every door of this Actor answers it logged out). Your own proxy links are possible, and no proxy uses the run container's own address. Apify's residential group is not offered: its transfer price is above what a photo is charged.

## Actor input object example

```json
{
  "pages": [
    "https://www.facebook.com/natgeo"
  ],
  "photoSources": [
    "photos"
  ],
  "maxPhotosPerPage": 10,
  "includeDetails": true,
  "maxCommentsPerItem": 20,
  "maxRepliesPerComment": 10,
  "includePersonalData": false,
  "outputFormat": "full",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `items` (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 = {
    "pages": [
        "https://www.facebook.com/natgeo"
    ],
    "photoSources": [
        "photos"
    ],
    "maxPhotosPerPage": 10,
    "includeDetails": true,
    "maxCommentsPerItem": 20,
    "maxRepliesPerComment": 10,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation_craft/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 = {
    "pages": ["https://www.facebook.com/natgeo"],
    "photoSources": ["photos"],
    "maxPhotosPerPage": 10,
    "includeDetails": True,
    "maxCommentsPerItem": 20,
    "maxRepliesPerComment": 10,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("automation_craft/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 '{
  "pages": [
    "https://www.facebook.com/natgeo"
  ],
  "photoSources": [
    "photos"
  ],
  "maxPhotosPerPage": 10,
  "includeDetails": true,
  "maxCommentsPerItem": 20,
  "maxRepliesPerComment": 10,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call automation_craft/facebook-photos-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation_craft/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/0QXJ4fKZFVXbAnLFI/builds/7oo4QXH08yxVBldJR/openapi.json
