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

Scrape Letterboxd without a login. Pull a member's diary by username (films watched, ratings, likes, rewatch flags, watched dates, review text, and lists) or full film detail by URL (directors, cast, genres, countries, studios, average rating, runtime, synopsis).

- **URL**: https://apify.com/goat255/letterboxd-scraper.md
- **Developed by:** [Goutam Soni](https://apify.com/goat255) (community)
- **Categories:** Social media, Videos, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

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

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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

## Letterboxd Scraper

Extract public Letterboxd data without a login or API key. Scrape any member's film diary by username (films watched, star ratings, likes, rewatch flags, watched dates, and review text) or pull full detail for any film by its URL (directors, cast, genres, countries, studios, average rating, runtime, and synopsis). Results come back as clean, structured JSON rows ready for export to CSV, Excel, Google Sheets, or your database.

### What it does

- **Member diary by username.** Returns every logged film with the member's star rating, whether they liked it, whether it was a rewatch, the watched date, the review text when present, and the canonical film URL plus the TMDB id for easy joining.
- **Film detail by URL.** Returns the film title, release year, directors, full cast, genres, countries, studios, the Letterboxd average rating, the rating count, runtime, poster, and synopsis.
- **Published lists (optional).** Include a member's curated lists with the list name, intro note, and every film in the list (title and URL).
- **No login, no password, no API key.** Feed it usernames or film links and it returns structured rows.
- **Bulk and parallel.** Process many usernames and film URLs in one run, with adjustable concurrency.
- **Clean, stable schema.** Every row has a consistent set of keys, missing values are `null`, and a `scrapedAt` timestamp is attached to each record.

### Use cases

- **Film data enrichment.** Build a movie database with ratings, cast, genres, runtime, and TMDB ids for thousands of titles.
- **Audience and taste research.** Analyze what a cohort of members watch, how they rate films, and which genres they favor.
- **Critic and reviewer monitoring.** Track new diary entries and reviews from public film-critic accounts for trend reporting.
- **Recommendation and ranking models.** Collect member ratings and watch histories as training signal for taste-based recommenders.
- **Content and market research.** Aggregate average ratings and rating counts to gauge how titles are received over time.

### Input

| Field | Type | Description |
|---|---|---|
| `usernames` | array | Letterboxd usernames to pull the public diary from. Accepts a bare handle, an `@handle`, or a full profile link. |
| `filmUrls` | array | Letterboxd film links to fetch full detail for (one record per film). |
| `maxItemsPerSource` | integer | Cap on diary entries returned per username. Up to the 100 most recent entries are available per member. Default 100. |
| `includeLists` | boolean | When on, a member's published lists are returned alongside diary entries. Default off. |
| `concurrency` | integer | How many sources to process in parallel. Default 5. |
| `proxyConfig` | object | Optional proxy configuration. The public pages do not require a proxy. |

#### Example input

```json
{
  "usernames": ["example_user", "@another_user", "https://letterboxd.com/third_user"],
  "filmUrls": ["https://letterboxd.com/film/example-film"],
  "maxItemsPerSource": 100,
  "includeLists": true,
  "concurrency": 5
}
````

### Output

Each result is one row in the dataset. Diary entries, list entries, and film details are distinguished by the `type` field (`"diary"`, `"list"`, or `"film"`).

#### Diary row

```json
{
  "type": "diary",
  "filmTitle": "Example Film",
  "filmYear": 2024,
  "filmUrl": "https://letterboxd.com/film/example-film/",
  "entryUrl": "https://letterboxd.com/example_user/film/example-film/",
  "tmdbId": "12345",
  "rating": 4.5,
  "liked": true,
  "review": "A short note on the film.",
  "hasReview": true,
  "rewatch": false,
  "watchedDate": "2024-06-01",
  "loggedAt": "Sat, 01 Jun 2024 12:00:00 +0000",
  "scrapedAt": "2024-06-02T10:00:00.000Z"
}
```

#### Film row

```json
{
  "type": "film",
  "name": "Example Film",
  "year": 1999,
  "url": "https://letterboxd.com/film/example-film/",
  "tmdbId": "550",
  "ratingAverage": 4.27,
  "ratingCount": 5536463,
  "runtimeMins": 139,
  "directors": ["Jane Doe"],
  "cast": ["Actor One", "Actor Two"],
  "genres": ["Drama", "Thriller"],
  "countries": ["USA"],
  "studios": ["Acme Pictures"],
  "synopsis": "A one paragraph synopsis of the film.",
  "poster": "https://example.com/poster.jpg",
  "scrapedAt": "2024-06-02T10:00:00.000Z"
}
```

#### Key fields

- `filmUrl` is the canonical film page, so a diary row joins cleanly to a film-detail row. `entryUrl` is the member's diary permalink for that watch.
- `tmdbId` lets you cross-reference any external movie database.
- `rating` is the member's own 0.5 to 5.0 star rating; `ratingAverage` and `ratingCount` are the community-wide values on a film row.
- `rating` and `review` are `null` when the member logged a film without rating or reviewing it.

A list row (when `includeLists` is on) carries `name`, `listUrl`, `filmCount`, `note`, `films` (title and URL for each), and `loggedAt`.

### FAQ

**Do I need a Letterboxd account or login?**
No. This scraper reads only public pages. No account, password, cookie, or API key is required.

**How much does it cost?**
You pay only for the Apify platform usage and per-result charges shown on the actor page. There is no separate Letterboxd subscription needed.

**How many diary entries can I get per member?**
Up to the 100 most recent activity entries per member, which is the full public diary window. Set `maxItemsPerSource` lower to return fewer.

**Can I scrape many members and films at once?**
Yes. Add as many usernames and film URLs as you like in a single run. The `concurrency` setting controls how many are processed in parallel.

**How fast is it?**
Each member diary is one fetch and each film is one fetch, so most runs finish in seconds to a couple of minutes depending on how many sources you pass and the concurrency you set.

**What if a username or film does not exist?**
The actor emits a row marked `ok: false` with an `error` reason for that source and continues with the rest, so one bad input never fails the whole run.

**What output formats are supported?**
Results are stored in an Apify dataset and can be exported to JSON, CSV, Excel, HTML, RSS, or XML, or pulled through the API.

# Actor input Schema

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

Letterboxd usernames to pull the public diary from (films watched, ratings, likes, rewatch flags, watched dates, review text). With or without the @ prefix, or a full profile link. Example: example\_user, @example\_user, https://letterboxd.com/example\_user.

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

Letterboxd film links to fetch full detail for (title, year, directors, cast, genres, countries, studios, average rating, runtime, synopsis). Example: https://letterboxd.com/film/example-film.

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

Cap on diary entries returned per username. Up to the most recent 100 activity entries are available per member. Film URLs always return one record each.

## `includeLists` (type: `boolean`):

When on, a member's published lists are included alongside diary entries (list name, intro note, and the films in it).

## `concurrency` (type: `integer`):

How many sources to process in parallel.

## `proxyConfig` (type: `object`):

Optional proxy. The public read pages do not require a proxy, but you may route through one if you wish.

## Actor input object example

```json
{
  "usernames": [
    "davidehrlich"
  ],
  "filmUrls": [],
  "maxItemsPerSource": 100,
  "includeLists": false,
  "concurrency": 5,
  "proxyConfig": {
    "useApifyProxy": false
  }
}
```

# 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 = {
    "usernames": [
        "davidehrlich"
    ],
    "filmUrls": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("goat255/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 = {
    "usernames": ["davidehrlich"],
    "filmUrls": [],
}

# Run the Actor and wait for it to finish
run = client.actor("goat255/letterboxd-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "usernames": [
    "davidehrlich"
  ],
  "filmUrls": []
}' |
apify call goat255/letterboxd-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=goat255/letterboxd-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Letterboxd Scraper",
        "description": "Scrape Letterboxd without a login. Pull a member's diary by username (films watched, ratings, likes, rewatch flags, watched dates, review text, and lists) or full film detail by URL (directors, cast, genres, countries, studios, average rating, runtime, synopsis).",
        "version": "0.1",
        "x-build-id": "TsDNBiEO2Qrl1vsCB"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/goat255~letterboxd-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-goat255-letterboxd-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/goat255~letterboxd-scraper/runs": {
            "post": {
                "operationId": "runs-sync-goat255-letterboxd-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/goat255~letterboxd-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-goat255-letterboxd-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "usernames": {
                        "title": "Usernames (diary mode)",
                        "type": "array",
                        "description": "Letterboxd usernames to pull the public diary from (films watched, ratings, likes, rewatch flags, watched dates, review text). With or without the @ prefix, or a full profile link. Example: example_user, @example_user, https://letterboxd.com/example_user.",
                        "default": [
                            "davidehrlich"
                        ],
                        "items": {
                            "type": "string"
                        }
                    },
                    "filmUrls": {
                        "title": "Film URLs (detail mode)",
                        "type": "array",
                        "description": "Letterboxd film links to fetch full detail for (title, year, directors, cast, genres, countries, studios, average rating, runtime, synopsis). Example: https://letterboxd.com/film/example-film.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "maxItemsPerSource": {
                        "title": "Max items per username",
                        "minimum": 1,
                        "maximum": 100,
                        "type": "integer",
                        "description": "Cap on diary entries returned per username. Up to the most recent 100 activity entries are available per member. Film URLs always return one record each.",
                        "default": 100
                    },
                    "includeLists": {
                        "title": "Include published lists",
                        "type": "boolean",
                        "description": "When on, a member's published lists are included alongside diary entries (list name, intro note, and the films in it).",
                        "default": false
                    },
                    "concurrency": {
                        "title": "Concurrency",
                        "minimum": 1,
                        "maximum": 20,
                        "type": "integer",
                        "description": "How many sources to process in parallel.",
                        "default": 5
                    },
                    "proxyConfig": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "Optional proxy. The public read pages do not require a proxy, but you may route through one if you wish.",
                        "default": {
                            "useApifyProxy": false
                        }
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
