Letterboxd API

What film people think, as opposed to what everyone thinks

The Letterboxd API returns film details, ratings and user data as clean JSON.

no credit card1,000 free credits · instant API key · live in 10 seconds
Missing a Letterboxd endpoint, or need a source we don't have yet?Contact us real people · same-day reply.
L
/letterboxd/v1

11 active endpoints. Every call is 1 credit.

  • POST/letterboxd/v1/film
  • POST/letterboxd/v1/user
  • POST/letterboxd/v1/user_films
  • POST/letterboxd/v1/user_diary
  • POST/letterboxd/v1/list
  • POST/letterboxd/v1/film_reviews
  • POST/letterboxd/v1/browse
  • +4 more

What Letterboxd endpoints does ReefAPI ship?

11 live read endpoints. Read-only data API: no writes, no account actions, no dashboard access on the target site.

11 endpoints

film

1 cr

Full Letterboxd film detail by film slug or URL.

required
optional
film, film_slug, url

user

1 cr

Public Letterboxd member profile and stats by username.

required
user
optional

user_films

1 cr

Paginated list of films a Letterboxd member has watched and rated, with their personal star r…

required
user
optional
page, per_page

user_diary

1 cr

Paginated diary entries for a Letterboxd member.

required
user
optional
page, per_page

list

1 cr

A public Letterboxd curated film list.

required
user, list
optional
page, per_page

film_reviews

1 cr

Paginated public reviews for a Letterboxd film.

required
optional
film, film_slug, url, page, per_page

browse

1 cr

Browse Letterboxd films with optional genre / decade / year filters, ordered by popularity, r…

required
optional
sort, genre, decade, year, page, per_page

film_similar

1 cr

Films Letterboxd shows as similar/related to a given film.

required
optional
film, film_slug, url

lists_popular

1 cr

Browse Letterboxd's most popular member-curated film lists for a time window (week/month/year…

required
optional
period, page, per_page

user_lists

1 cr

The public film lists a Letterboxd member has created (paginated).

required
user
optional
page, per_page

search

1 cr

Search Letterboxd for films, members, or curated lists by keyword.

required
query
optional
type, page, per_page

Every parameter, every allowed value →

Letterboxd API

3 of 11 endpoints, ready to run

View docs ↗

One film: title, tagline, description, poster, runtime, director, cast and crew, keyed on the Letterboxd slug.

1 credit1 required · 0 optional
POST/letterboxd/v1/film
ok880 ms · 1 records · sample
{
  "ok": true,
  "meta": {
    "api": "letterboxd",
    "endpoint": "film",
    "mode": "live",
    "latency_ms": 880.1,
    "record_count": 1,
    "cache_hit": false
  },
  "data": {
    "film": {
      "slug": "parasite-2019",
      "title": "Parasite",
      "name": "Parasite",
      "year": null,
      "tagline": "Act like you own the place.",
      "description": "All unemployed, Ki-taek's family takes peculiar interest in the wealthy and glamorous Parks for their livelihood until they get entangled in an unexpected incident.",
      "poster_url": "https://a.ltrbxd.com/resized/film-poster/4/2/6/4/0/6/426406-parasite-0-600-0-900-crop.jpg?v=8f5653f710",
      "runtime_minutes": 133,
      "directors": [
        "Bong Joon Ho"
      ],
      "director": "Bong Joon Ho",
      "cast": [
        {
          "name": "Song Kang-ho",
          "role": "Kim Ki-taek"
        },
        {
          "name": "Lee Sun-kyun",
          "role": "Park Dong-ik"
        },
        {
          "name": "Cho Yeo-jeong",
          "role": "Yeon-kyo"
        }
      ],
      "crew": {
        "producer": [
          "Jang Young-hwan",
          "Kwak Sin-ae",
          "Moon Yang-kwon"
        ],
        "writer": [
          "Kim Dae-hwan",
          "Han Jin-won",
          "Bong Joon Ho"
        ],
        "story": [
          "Bong Joon Ho"
        ],
        "editor": [
          "Yang Jin-mo"
        ],
        "cinematography": [
          "Hong Kyung-pyo"
        ],
        "assistant_director": [
          "Kim Seong-sik",
          "Yoon Young-woo"
        ],
        "executive_producer": [
          "Heo Min-heoi",
          "Miky Lee",
          "Lim Myeong-gyun"
        ],
        "production_design": [
          "Lee Ha-jun"
        ],
        "art_direction": [
          "Mo So-ra"
        ],
        "set_decoration": [
          "Noh Seung-goog",
          "Song Suk-ki",
          "Cho Won-woo"
        ],
        "visual_effects": [
          "Hong Jeong-ho",
          "Jeong Min-hyuk",
          "Ha Jae-gu"
        ],
        "stunts": [
          "Yoo Mi-jin",
          "Kwon Ji-hoon",
          "Kang Gyeong-su"
        ],
        "composer": [
          "Jung Jae-il"
        ],
        "sound": [
          "Choi Tae-young",
          "Eun Hee-soo",
          "Park Sung-gyun"
        ],
        "costume_design": [
          "Choi Se-yeon"
        ],
        "makeup": [
          "Kim Ho-sik",
          "Kwak Tae-yong",
          "Hwang Hyo-kyun"
        ]
      },
      "writers": [
        "Kim Dae-hwan",
        "Han Jin-won",
        "Bong Joon Ho"
      ],
      "cinematography": [
        "Hong Kyung-pyo"
      ],
      "editors": [
        "Yang Jin-mo"
      ],
      "composers": [
        "Jung Jae-il"
      ],
      "producers": [
        "Jang Young-hwan",
        "Kwak Sin-ae",
        "Moon Yang-kwon"
      ],
      "genres": [
        "Thriller",
        "Comedy",
        "Drama"
      ],
      "tags": [
        "Thriller",
        "Comedy",
        "Drama"
      ],
      "themes": [
        "Intense violence and sexual transgression",
        "Humanity and the world around us",
        "Moving relationship stories"
      ],
      "alternative_titles": [
        "ชนชั้นปรสิต",
        "パラサイト 半地下の家族:2019",
        "Parazit"
      ],
      "similar_films": [
        {
          "slug": "no-other-choice-2025",
          "name": "No Other Choice (2025)",
          "name_source": "page",
          "year": 2025,
          "url": "https://letterboxd.com/film/no-other-choice-2025/",
          "user_rating": null
        },
        {
          "slug": "the-housemaid",
          "name": "The Housemaid (1960)",
          "name_source": "page",
          "year": null,
          "url": "https://letterboxd.com/film/the-housemaid/",
          "user_rating": null
        },
        {
          "slug": "saltburn",
          "name": "Saltburn (2023)",
          "name_source": "page",
          "year": null,
          "url": "https://letterboxd.com/film/saltburn/",
          "user_rating": null
        }
      ],
      "countries": [
        "South Korea"
      ],
      "languages": [
        "English",
        "German",
        "Korean"
      ],
      "production_companies": [
        "Barunson E&A"
      ],
      "imdb_id": "tt6751668",
      "tmdb_id": "496243",
      "imdb_url": "https://www.imdb.com/title/tt6751668/",
      "tmdb_url": "https://www.themoviedb.org/movie/496243/",
      "url": "https://letterboxd.com/film/parasite-2019/",
      "avg_rating": 4.52,
      "rating_count": 5783521,
      "review_count": 775414,
      "watch_count": 7483455,
      "like_count": 3864766,
      "list_count": 885627,
      "watches": 7483455,
      "lists": 885627,
      "likes": 3864766,
      "fans": null
    }
  }
}
Real response, fetched from the live endpoint with the parameters on the left — trimmed to the first few rows, with seller names left out. Press Try it for the untrimmed response.

How the Letterboxd API works

Letterboxd is a normal ReefAPI surface — the same four rules that hold for every other engine on the key.

01
Authenticate
x-api-key header

No OAuth app, no request signing, no per-site account. One key covers all 184 engines.

02
Call
POST /letterboxd/v1/…

Every route is a POST with a JSON body. Parameters are validated against the published schema before anything is charged.

03
Pay
1 credit per call

Credits, not seats. Failed and blocked calls are never charged, and cache hits cost nothing.

04
Read
{ ok, data, meta, error }

One envelope everywhere. meta carries latency_ms, record_count and the endpoint that answered.

Finding what an audience with taste is rating highly

Mainstream rating sites regress towards a broad average. A site whose members log every film they watch produces a different, narrower signal.

01browse
POST/letterboxd/v1/browse
{"sort": "popular", "genre": "horror", "decade": "1990s"}

The discovery grid, filtered on the axes people actually browse by. Each row carries the slug you need next.

02film
POST/letterboxd/v1/film
{"film": "parasite-2019"}

Then the film record — director, cast, crew, runtime and the tagline, keyed on that slug.

Cross-referenced against a mainstream rating, the gap between the two audiences is the actual finding — and both are available in this catalogue.

request
curl -X POST https://api.reefapi.com/letterboxd/v1/film \
  -H "x-api-key: $REEF_KEY" \
  -H "content-type: application/json" \
  -d '{"film":"parasite-2019"}'
response envelope
{
  "ok": true,
  "data": { … },
  "meta": {
    "api": "letterboxd",
    "endpoint": "film",
    "mode": "live",
    "latency_ms": …,
    "record_count": …
  },
  "error": null
}

Slugs, the star scale and the page sizes Letterboxd fixes for you

Letterboxd has no numeric film id in its public pages, so everything here is addressed by slug. The numbers below are from live calls on Parasite, on a member diary, and on a one-minute 1920 documentary, which is what shows you where the nulls are.

Field or parameterMeasured valueWhat to know
film slugparasite-2019, the-housemaidthe id for every film action. Usually title-year, but a title with no collision has no year suffix. A full film URL is also accepted and parsed down to the slug.
avg_rating4.52the community mean on Letterboxd's 5-star scale, two decimals. Not out of 10.
user_rating, diary rating3.5, 4.0, 4.5half-star granularity from 0.5 to 5.0. null when the member logged the film without rating it: 6 of 72 rows in one member's film list, 16 of 50 in the diary.
watch_count, rating_count7,471,960 and 5,774,276two separate counters. More people log a film than rate it, so watch_count is always the larger of the pair.
like_count, list_count3,859,986 and 884,440likes are the heart, list_count is how many member lists include the film.
imdb_id, tmdb_idtt6751668 and 496243both are strings. tmdb_id is bare digits with no prefix, imdb_id keeps the tt.
year on the film actionnullthe film record does not carry a release year. Read it off the slug suffix, or off imdb_id / tmdb_id in another catalog.
per_pagefilms 72, diary 100, reviews 12, browse 72a hint only. Letterboxd fixes the page size per view and the value it actually used is echoed in meta.per_page. Walk pages with meta.has_more.

Community counters are published only once a film has enough activity. A measured film action on kino-the-girl-of-colour, a one-minute 1920 documentary, returned a title, runtime_minutes 1, genres, a poster, imdb_id tt3307880 and tmdb_id 360370, with avg_rating, rating_count, watch_count, like_count and list_count all null.

How rows are identified, and where a title comes from

Measured across four different grids. The second row describes a defect this batch found and fixed, and the honesty it left behind.

The slug is the identifier, and it is stable

Films are keyed on the slug in their URL — parasite-2019 — and it does not move. It is also human-readable, which makes it a workable identifier to store and to log, unlike an opaque numeric id.

Grid rows say where their title came from

Every row carries name_source. When the page publishes the title, it says page. When it does not, a title and year are derived from the slug and it says slug — because a slug flattens punctuation, so a derived title is close but not canonical. Three of the four grids report page; the search grid derives. We added this after finding that a markup change had silently emptied the title on every grid, search included: a film search returning slugs and no titles is technically a success and practically useless.

Reviews are text, not scores

The review endpoint returns what members wrote. Aggregate ratings tell you whether people liked something; the written reviews tell you what they liked or hated about it, which is the input for anything more interesting than a ranking.

The browse axes are the ones people use

Popularity, genre, decade and year — the same filters the site itself is organised around, so a discovery feature built on this matches how the audience already thinks about films.

Grid pages come in the site's own page size

A grid returns a full page of rows as the site paginates it. Asking for fewer does not make the upstream request smaller, so treat the page size as fixed and slice locally if you want a shorter list.

What people build with Letterboxd

The jobs this data is most often used for.

11

endpoints

1

credit per call

01

Film apps call film to enrich a title with rating, cast and cross-links to IMDb and TMDb.

02

Recommendation engines use film_similar and lists_popular to surface related films.

03

Media research uses user_films and film_reviews to study taste and sentiment.

What Letterboxd data costs

The cheapest call here is 1 credit, so $15/mo (Pro) buys 10,000 of them — $1.50 per 1,000 credits. Credits roll over and never expire, and failed or blocked calls are not charged.

Full pricing →
$0.67–$1.50 / 1,000 credits
  • 1,000 free credits on signup, no card
  • One key, all 184 APIs, one credit pool
  • Failed and blocked calls are never charged
  • Credits roll over and never expire

Call it in two lines

Sign up, get 1,000 credits and one key that works on every engine. Then this is the whole protocol.

curl
curl -X POST https://api.reefapi.com/letterboxd/v1/film \
  -H "x-api-key: $REEF_KEY" \
  -H "content-type: application/json" \
  -d '{"film":"parasite-2019"}'
python
import requests

r = requests.post(
    "https://api.reefapi.com/letterboxd/v1/film",
    headers={"x-api-key": REEF_KEY},
    json={
  "film": "parasite-2019"
},
)
print(r.json()["data"])
FAQ

Have a question? We got answers.

The questions people actually ask before wiring up Letterboxd.

Get a free key →
Why is year null even though the slug ends in a year?

The film action does not return a release year. Measured on parasite-2019, the-sheep-detectives and kino-the-girl-of-colour, year came back null every time while runtime_minutes, genres and the external ids were populated. The year in a slug is a disambiguator Letterboxd adds when two films share a title, not a data field, and plenty of slugs have no year at all. If you need a reliable year, take imdb_id or tmdb_id from the same record and resolve it elsewhere.

Why does an obscure film come back with no rating at all?

Letterboxd only publishes a rating histogram once a film has accumulated enough ratings, and below that threshold the page carries no numbers to read. A live call on kino-the-girl-of-colour returned a complete identity block, with title, runtime, genre, poster, tt3307880 and tmdb 360370, and null for avg_rating, rating_count, watch_count, like_count and list_count together. All five going null at once is the signal that the film is below the threshold, not that the call failed.

How does the half-star rating come back in the JSON?

As a float, not as stars or a string. Letterboxd's scale runs from half a star to five in half-star steps, and the API mirrors that exactly: a measured diary page returned 4.0, 3.5, 4.5, 2.5 and 2.0, and never a value like 3.7. Multiply by two if you need integer buckets. A member who logged a film without rating it produces null, which is different from a zero and should not be averaged in.

Why is watch_count higher than rating_count on every film?

They count different actions. watch_count is how many members marked the film as watched, rating_count is how many attached a star rating, and marking watched does not require rating. On Parasite the gap was 7,471,960 watches against 5,774,276 ratings, with 3,859,986 likes and 884,440 list appearances on top. If you are ranking by popularity, watch_count is the broader signal and rating_count is the one avg_rating is actually computed over.

What does this give me that the imdb or movies-tv engines do not?

The community layer. IMDb gives you a 10-point rating and a vote count, TMDB gives you a 10-point rating and popularity, and neither of them knows how many people put a film in a list or logged it in a diary. This engine returns the Letterboxd 5-star average, the watch, like and list counters, per-member diary entries with watch dates, member film lists with each member's own rating, and curated lists ranked by period. It also returns Letterboxd's editorial themes, which are phrases such as Intense violence and sexual transgression rather than genre labels.

Can I control how many rows a page returns?

No. per_page is accepted but treated as a hint, because Letterboxd fixes the page size per view server side. Measured: user_films returned 72 rows, user_diary returned 50 rows on a page reported as per_page 100, film_reviews returned 12, and browse returned 72. The value actually used comes back in meta.per_page and meta.has_more tells you whether to ask for the next page. Budget your calls off those two, not off a number you sent.

Why do user_films rows have a null name?

That view is a poster grid, so the only identity on the page is the film slug and its link. A measured page for one member returned rows of slug, url, user_rating and name null. Treat slug as the join key, which is what every other action in this engine takes anyway, and call film only for the slugs you actually need to display. user_diary is the richer sibling: its rows carry both slug and a name that includes the year, such as Spider-Man: No Way Home (2021).

What is the difference between genres, tags and themes?

genres is the conventional list, Thriller, Comedy, Drama on Parasite. tags came back identical to genres on the films measured, so do not treat it as a second signal. themes is the one that is genuinely different: it is Letterboxd's own editorial clustering and returns phrases such as Humanity and the world around us or Moving relationship stories, eight of them on Parasite. There is no numeric id on any of the three, so they join on the string.

What is the Letterboxd API?

Letterboxd API is a ReefAPI endpoint group for letterboxd It returns live JSON through POST requests under /letterboxd/v1.

Is the Letterboxd API free to try?

Yes. ReefAPI starts with 1,000 free credits, no card required. Letterboxd calls use the same shared credit balance as every other ReefAPI engine.

Do I need a Letterboxd login or account?

No login to Letterboxd is needed for the API response. You call ReefAPI with your x-api-key header, and the playground can run live examples before you create a production key.

How fresh is the Letterboxd data?

The page example is captured from a live film call, and production requests fetch live data through ReefAPI rather than a static sample.

How many credits does the Letterboxd API use?

Letterboxd actions currently cost 1 credit per successful call. Failed or blocked calls are free, and all APIs draw from one credit pool.

Can I call Letterboxd from an AI assistant or MCP client?

Yes. Connect ReefAPI once through MCP and your assistant can call letterboxd actions with the same key, credit pool and JSON envelope used by normal REST requests.

25 Media, Film & Knowledge APIs on the same key

One key, one credit pool, one response envelope. If you are pulling Letterboxd, you are one call away from the rest of the category — no second contract, no second integration.

Need something this API does not do?

Name the endpoint, the field, or a source we do not carry yet. We ship new APIs every week and you would be first to get the key. Real people read every message and reply the same day.

0/4000

No account needed · we reply from [email protected]

Try it on your own data before you pay anything

The call above is the real endpoint, not a recording. A free key gives you 1,000 credits, the other 183 APIs, and the same envelope everywhere.

Endpoints, parameters and credit costs on this page are read from the live catalog and cannot drift from what the API accepts. Field notes were captured on 2026-08-30.