Letterboxd Films Scraper
Pricing
from $2.98 / 1,000 results
Letterboxd Films Scraper
Scrape public Letterboxd film and list pages to build structured film records. Capture titles, years, ratings, genres, credits, identifiers and optional reviews, with list metadata when applicable. Choose embedded popular reviews or paginate through recent reviews with a configurable per-film limit.
Pricing
from $2.98 / 1,000 results
Rating
0.0
(0)
Developer
Axiom Works
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
Returns: one row per film with title, year, rating, ratingCount, genres, directors, cast, and reviews.
Input: {"startUrls":[{"url":"https://letterboxd.com/official/list/letterboxds-top-500-films/"}],"maxItems":10}
Best for: film catalog research, rating tracking, and list analysis.
{"id":"43015","title":"Harakiri","year":1962,"rating":4.68,"ratingCount":268176,"genres":["History","Drama","Action"],"directors":["Masaki Kobayashi"]}
What does Letterboxd Films Scraper do?
Letterboxd Films Scraper reads public Letterboxd film pages and public film lists, then writes one structured dataset row for each unique film. It collects the film details visible on the site, including ratings, credits, posters, and optional public reviews. You can give it a list URL, individual film URLs, or film slugs. A list supplies the film order and list name as well as the film details. The Letterboxd scraper processes multiple inputs in one run and deduplicates films that occur in more than one source.
The Actor is useful when you need repeatable film data without manually opening hundreds of pages. For example, you can compare the titles and average ratings in a public list, collect director and cast information for a set of films, or track changes in rating counts across runs. The output is a dataset that can be exported, filtered, and joined with your own records by filmId, slug, or id. The sourceUrl field links each result to the film page read for that row.
This Actor uses public pages and does not require a Letterboxd login. It does not claim to be an official Letterboxd API or an affiliated Letterboxd service. Its output reflects what the public pages showed when the run took place. Ratings, reviews, list order, and other changing fields may differ on a later run.
What data can you get?
Each row represents a film, even when the film was discovered through a list. Reviews are nested inside that row. Optional fields are null or empty when the page does not provide them or the corresponding input option is disabled.
| Field | Meaning |
|---|---|
id, filmId, slug | Stable film identifiers and the URL slug. |
title, originalTitle, year | Display title, original title when present, and release year. |
url, sourceUrl | Canonical film URL and page used for extraction. |
rating, ratingCount, reviewCount | Average rating, rating volume, and review volume shown on the film page. |
genres, themes | Public genre and theme names on the film page. |
directors, cast, crew | Director names, cast entries with character and URL, and crew names by role. |
tagline, description, runtimeMinutes, releaseDate | Film description and release details available on the page. |
studios, countries, languages | Production details and language codes or names. |
posterUrl, backdropUrl, trailerUrl | Media URLs exposed by the film page. |
imdbId, tmdbId, tmdbType | External catalog identifiers shown on the page. |
listName, listUrl, listPosition | Source list details when the film came from a list. |
reviews, reviewsSort | Nested public reviews and the selected review order. |
scrapedAt | Time the row was extracted. |
A review entry can include its review ID, public author username and display name, star rating, like and comment counts, date when shown, spoiler marker, text, truncation flag, and review URL. Popular reviews are embedded in the film page. Recent reviews come from public paginated review pages. Some popular review text ends in an ellipsis on Letterboxd; truncated flags that text instead of pretending the full review was retrieved.
How to use
Open the Actor input and add one or more film or list URLs under startUrls. The prefilled example uses a public Letterboxd list, so you can run it as supplied to see the dataset shape. Change maxItems to the number of unique films you need. A value of 7 outputs at most 7 film rows, regardless of how many films the list contains. You can also enter film slugs under films, such as parasite-2019, when you already know the desired titles.
For a list, the Actor reads the page in list order and follows its next-page link if more films are needed. It stores the 1-based position in listPosition. For a film URL, it normalizes film subpaths to the main film page. The Actor accepts multiple sources in the same run and skips duplicate film URLs. The first source to introduce a film supplies its list context.
Use includeReviews to control whether the Actor attaches review entries. reviewsSort selects popular or recent. Popular reviews require no extra review-page requests and usually provide up to 12 entries. Recent reviews may take longer because the Actor reads review pages until maxReviewsPerFilm is reached or no more reviews are present. Set the review limit to zero to omit review entries while keeping the review option available for later runs. Set includeCrew to false if you do not need the crew map.
The supported discovery URL is /lists/popular/, which supplies public list links from its first page. It is distinct from Letterboxd's film popularity grid. Film search, genre browsing, and the film popularity grid are not supported input sources because those public paths may return a challenge page. The Actor warns and skips unsupported URLs. A missing film or list produces no dataset row and is recorded in RUN_SUMMARY in the default key-value store.
Input
| Input | Description | Default |
|---|---|---|
startUrls | Film, list, /lists/popular/, person (/director/quentin-tarantino/, /actor/tom-hanks/, /writer/greta-gerwig/), studio or member films (/dave/films/) URLs. Supply this or films. | No API default; the Console has a prefilled public list. |
films | Film slugs, film page URLs, IMDb IDs such as tt0114369, or tmdb:603. Supply this or startUrls. | Empty. |
maxItems | Maximum film rows, from 1 to 1000. | 50. |
includeReviews | Attach reviews to film rows. | true. |
reviewsSort | Choose popular or recent. | popular. |
maxReviewsPerFilm | Maximum attached reviews per film, from 0 to 500. | 12. |
includeCrew | Include crew names grouped by role. | true. |
maxListsFromPopular | Number of popular lists to expand when that URL is supplied. | 3. |
proxyConfiguration | Optional Apify Proxy configuration. | Proxy disabled. |
{"films": ["parasite-2019", "harakiri", "seven-samurai"],"maxItems": 3,"includeReviews": true,"reviewsSort": "recent","maxReviewsPerFilm": 24,"includeCrew": true}
Director, actor and member pages fill listName and listUrl with the page they came from, so every row records its source. IMDb and TMDB IDs are resolved to the Letterboxd film page before scraping.
The Actor requires at least one URL or film slug in API calls. The Console prefill is an example, while an API caller should supply its own target. maxItems counts films rather than nested reviews. The Actor requests pages at a modest rate and retries temporary server or blocking responses. If a requested film is unavailable, the other inputs can still produce results.
Output
The following shortened row is based on a local run of the prefilled public list. It keeps the real field names and representative values from that run. Ratings and counts are a snapshot and can change.
{"id": "43015","filmId": 43015,"slug": "harakiri","title": "Harakiri","originalTitle": "切腹","year": 1962,"url": "https://letterboxd.com/film/harakiri/","sourceUrl": "https://letterboxd.com/film/harakiri/","rating": 4.68,"ratingCount": 268176,"reviewCount": 68809,"genres": ["History", "Drama", "Action"],"directors": ["Masaki Kobayashi"],"runtimeMinutes": 135,"studios": ["Shochiku"],"countries": ["Japan"],"languages": ["ja"],"listName": "Letterboxd's Top 500 Films","listPosition": 1,"reviewsSort": "popular"}
The full row can also include cast and crew arrays, media URLs, text description, and nested reviews. To inspect what a run did when no rows appear, open the default key-value store and read RUN_SUMMARY. It records the total pushed film rows, per-source counts, and skipped sources. Dataset rows are reserved for actual films; failures are never inserted as placeholder rows.
How much does it cost?
The Actor is charged per film result pushed to the dataset. Review entries are attached to film results and are not separate dataset rows. The maxItems limit controls how many film records can be pushed. See the Actor's Pricing tab for the current pricing and billing details. The Actor does not assign a charge to a skipped input or a URL that yields no film row.
To estimate work before running a large list, start with a small maxItems, inspect the dataset, then raise the limit. Recent reviews require additional page requests, so those runs can take longer than runs using embedded popular reviews. The number of items available depends on the public source list and whether its linked film pages can be read at run time.
Use with AI agents (MCP)
An AI agent can discover this Actor through Apify MCP and run it with JSON input. The tool description exposes film URLs, list URLs, the result limit, review controls, and the output fields. Configure the Apify MCP server with the Store path for this Actor:
{"mcpServers": {"apify": {"url": "https://mcp.apify.com?tools=axiomworks/letterboxd-films-scraper"}}}
Example prompts include: “Get the first 10 films from Letterboxd's Top 500 list with ratings and directors”; “Compare ratings and rating counts for these seven film slugs”; and “Collect 24 recent public reviews for each of these film URLs.” Give the agent a target URL or slug and a numeric maxItems. If you need the complete review text, check the truncated flag because a public film page may show an excerpt.
For downstream workflows, id and filmId help an agent match rows across runs. sourceUrl lets it cite the page used for a film, and scrapedAt tells it when the extraction occurred. For a list analysis task, listName, listUrl, and listPosition preserve source context without making separate rows for list entries.
Integrations and API
Use the Apify API to run the Actor, then read items from its default dataset. Replace the token placeholder with your own Apify API token in your local environment. These examples show the same small list job in three common clients. Keep the token outside source control.
Python:
from apify_client import ApifyClientimport osclient = ApifyClient(os.environ["APIFY_TOKEN"])run = client.actor("axiomworks/letterboxd-films-scraper").call(run_input={"startUrls": [{"url": "https://letterboxd.com/official/list/letterboxds-top-500-films/"}],"maxItems": 10,})for item in client.dataset(run["defaultDatasetId"]).iterate_items():print(item["title"], item["rating"])
JavaScript:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('axiomworks/letterboxd-films-scraper').call({films: ['harakiri', 'parasite-2019'],maxItems: 2,});const { items } = await client.dataset(run.defaultDatasetId).listItems();items.forEach(item => process.stdout.write(`${item.title}: ${item.rating}\n`));
cURL:
curl -X POST \'https://api.apify.com/v2/acts/axiomworks~letterboxd-films-scraper/run-sync-get-dataset-items' \-H "Authorization: Bearer $APIFY_TOKEN" \-H 'Content-Type: application/json' \-d '{"films":["harakiri","parasite-2019"],"maxItems":2}'
The dataset is JSON. Export it through Apify's dataset tools when a spreadsheet or other format is needed. Keep the numeric rating alongside ratingCount: a high rating based on a small sample may need different treatment from a high rating based on many ratings. The Actor returns the source values and leaves that interpretation to your workflow.
FAQ
Why are there fewer rows than maxItems? The limit is a ceiling. A list may end early, a film URL may be unavailable, or a public page may return a challenge. Inspect RUN_SUMMARY for skipped URLs and per-source counts.
Are review records separate dataset items? No. Every dataset item is one film. Public review objects, when requested, are nested in its reviews array. The film result limit therefore stays predictable even when review limits change.
Can I search Letterboxd by a title phrase? No. Provide a film slug or public film URL. Public list pages can be used for discovery within a known list, while the live film search and popularity grid are outside the supported URL set.
Why is a review marked truncated? Letterboxd sometimes shows an excerpt on a public film page. The Actor preserves that displayed text and marks the excerpt. It does not invent missing text.
What happens with repeated films? The Actor deduplicates by canonical film URL within the run. The first occurrence supplies list context; it does not push another row for the same film on a later list page.
Do I need a proxy? The default uses no proxy. The optional proxyConfiguration input lets you supply Apify Proxy settings, and temporary blocking responses can trigger retries. Results still depend on what Letterboxd serves at run time.
Is it legal to scrape Letterboxd?
This Actor reads publicly accessible film and review pages without a login. Whether a particular use is permitted depends on your location, the applicable rules, and what you do with the data. Review the site's current terms and any relevant legal requirements before using results commercially or redistributing review text. Avoid collecting more personal data than your use requires. Public review author names and review links are included only as they appear on the source pages. This Actor is independently developed and is not affiliated with Letterboxd.
Feedback
If a field becomes empty after a site change, send the film URL, the field name, and the run identifier through the Actor's feedback channel. A list URL and expected position help diagnose list-order issues. For missing reviews, include the selected reviewsSort and maxReviewsPerFilm values. Sharing the input and the affected sourceUrl makes it possible to reproduce the extraction problem without guessing which page was read.