# Letterboxd Scraper (`aurenic/letterboxd-scraper`) Actor

Extract film metadata, ratings, cast, crew, and user diary entries from Letterboxd. Titles, directors, genres, ratings, reviews, and watch histories.

- **URL**: https://apify.com/aurenic/letterboxd-scraper.md
- **Developed by:** [Aurenic](https://apify.com/aurenic) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.50 / 1,000 results

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

## Letterboxd Scraper

Extract film metadata, user film lists, tags, and search results from Letterboxd.

### What does Letterboxd Scraper do?

Scrape structured data from Letterboxd in four modes:

- **Film details** — pass film URLs, get title, year, runtime, rating, cast, crew, genres, poster, and external links (TMDb, IMDb).
- **User films** — pass usernames, get their public film list: every film they've watched. 72 films per page, auto-paginated.
- **Tags** — pass tags, get every film carrying that tag. 72 films per page, auto-paginated.
- **Search** — pass keywords, get matching films via Letterboxd's mobile API. Returns slug, title, and URL. Up to 10,000 results per term.

Film pages and user/tag lists are server-rendered. Search uses Letterboxd's anonymous mobile API endpoint — no login, no browser.

### Output fields

#### Film mode

| Field | Description |
|---|---|
| slug | Letterboxd film slug |
| title | Film title |
| year | Release year |
| runtime | Runtime in minutes |
| rating | Average user rating (0–5) |
| ratingCount | Number of ratings |
| directors | Array of director names |
| cast | Array of cast names |
| genres | Array of genres |
| tagline | Marketing tagline |
| description | Synopsis |
| poster | Poster image URL |
| tmdbLink | TMDb URL |
| imdbLink | IMDb URL |
| letterboxdUrl | Direct URL to film page |

#### User films / Tags / Search modes

| Field | Description |
|---|---|
| type | `user`, `tag`, or `search` |
| source | Username, tag, or search term |
| slug | Letterboxd film slug |
| title | Film title (with year where available) |
| letterboxdUrl | Direct URL to film page |

### Who is it for?

- **Film researchers** building datasets of films, directors, and ratings
- **Cinephile communities** tracking what members have watched
- **Data scientists** building recommendation models on Letterboxd ratings
- **Journalists** monitoring film discourse and rating trends
- **Developers** integrating film metadata into apps

### Pricing

**$0.0012 per result** ($1.20 per 1,000 items). No subscription.

| Results | Cost |
|---|---|
| 100 | $0.12 |
| 1,000 | $1.20 |
| 10,000 | $12.00 |

### How to use it

1. Paste **Film URLs** for detailed metadata, or
2. Enter **Usernames** for public film lists, or
3. Add **Tags** for genre/theme collections, or
4. Add **Search Terms** to find films by keyword.
5. Set **Max Items per Source** (default 500) and **Max Pages per Source** (default 3).
6. Click **Start**.

### Output example

```json
{
  "type": "film",
  "slug": "parasite-2019",
  "title": "Parasite",
  "year": 2019,
  "runtime": 132,
  "rating": 4.34,
  "ratingCount": 892341,
  "directors": ["Bong Joon-ho"],
  "cast": ["Song Kang-ho", "Lee Sun-kyun", "Cho Yeo-jeong"],
  "genres": ["Thriller", "Drama", "Comedy"],
  "tagline": "Act like you own the place.",
  "description": "All unemployed, Ki-taek's family takes peculiar interest in the wealthy and glamorous Parks...",
  "poster": "https://a.ltrbxd.com/resized/film-poster/...",
  "tmdbLink": "https://www.themoviedb.org/movie/496243",
  "imdbLink": "https://www.imdb.com/title/tt6751668",
  "letterboxdUrl": "https://letterboxd.com/film/parasite-2019/",
  "scrapedAt": "2026-09-20T10:00:00.000Z"
}
```

### Technical details

- Built with **Cheerio + got-scraping** (TLS impersonation) for film pages, user lists, and tags.
- **Search** uses Letterboxd's anonymous mobile API (`api.letterboxd.com/api/v0/search`) — pure JSON, cursor-paginated.
- Chrome-realistic headers, retry with exponential backoff on 403/429/5xx.
- **Residential proxy is recommended** for user film list pagination — Cloudflare rate-limits datacenter IPs after the first page.
- No API key or login required.

### Known limits

- **Letterboxd has no official public API.** This Actor extracts from public HTML and the mobile API endpoint.
- **User film lists are capped by maxPagesPerSource.** Each page holds 72 films; Letterboxd may rate-limit rapid pagination.
- **Search returns slug + title only**, not full metadata. Chain it with film mode by passing result URLs as filmUrls.
- **Private profiles and private lists are not accessible.**

### FAQ

**Do I need a proxy?** Film pages and search work without one. User film lists benefit from residential proxy to avoid Cloudflare rate-limits on pagination.

**Can I scrape private profiles?** No. Only public profiles and public data.

**Does this include reviews or diaries?** No. This Actor extracts film lists (watched films), not the diary or review text.

**How do I export data?** After a run, go to Storage → Export as JSON, CSV, Excel.

### Support

Open an issue on the Actor's page for bugs or feature requests.

# Actor input Schema

## `filmUrls` (type: `array`):

Direct Letterboxd film page URLs (e.g. https://letterboxd.com/film/parasite-2019/). Returns full metadata per film.

## `usernames` (type: `array`):

Letterboxd usernames. Scrapes their public film list at /{username}/films/. 72 films per page.

## `tags` (type: `array`):

Letterboxd tags (e.g. 'horror', 'noir'). Scrapes /tag/{tag}/. 72 films per page.

## `searchTerms` (type: `array`):

Keywords to search on Letterboxd. Scrapes /search/films/{term}/ via browser. Results load dynamically via 'Show more'.

## `maxItemsPerSource` (type: `integer`):

Cap on results per film URL, username, tag, or search term.

## `maxPagesPerSource` (type: `integer`):

Maximum pages to paginate for user/tag sources. Each page holds up to 72 films. Ignored for search (uses Show more).

## Actor input object example

```json
{
  "maxItemsPerSource": 500,
  "maxPagesPerSource": 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("aurenic/letterboxd-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 = {}

# Run the Actor and wait for it to finish
run = client.actor("aurenic/letterboxd-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 '{}' |
apify call aurenic/letterboxd-scraper --silent --output-dataset

```

## MCP server setup

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