Skip to content

Welcome to letterboxdpy

A modern, fast, and feature-rich Python library for scraping and interacting with Letterboxd data.


Features

  • Core Letterboxd Entities: First-class models for User, Movie, Search, List, Watchlist, and Members.
  • WAF & Cloudflare Resilient: Built on curl_cffi using real browser TLS impersonation (chrome120) and RFC-compliant URL normalization.
  • Deep User Insights: Extract complete watchlists, chronological diary entries, user wrapped summaries, ratings, reviews, followers, and genre distribution.
  • Advanced Film Discovery: Discover films by genre, curated themes, release years, decades, or streaming services.
  • Trace-Locked Sessions: Authenticated account settings and profile updates via automated CSRF handling.
  • Deterministic & Typed: Strict type hints, comprehensive offline test suite, and clean snake_case JSON schemas.

Quick Start

Installation

pip install letterboxdpy
pip install git+https://github.com/nmcassa/letterboxdpy.git
git clone https://github.com/nmcassa/letterboxdpy.git
cd letterboxdpy
pip install -e ".[dev,docs,examples]"

Basic Usage

Fetching a User

from letterboxdpy.user import User

# Initialize a user instance
user = User("bugracoskun")

print(f"Display Name: {user.display_name}")
print(f"Badge: {user.badge}")
print(f"Watchlist Count: {user.watchlist_length}")
print(f"Watched Films: {user.stats.get('films')}")
Display Name: bugra
Badge: patron
Watchlist Count: 150
Watched Films: 500

Fetching a Movie

from letterboxdpy.movie import Movie

# Initialize by slug, TMDB ID, or IMDb ID
movie = Movie("v-for-vendetta")

print(f"Title: {movie.title} ({movie.year})")
print(f"Rating: {movie.rating} / 5.0")
print(f"Runtime: {movie.runtime} mins")
Title: V for Vendetta (2005)
Rating: 3.84 / 5.0
Runtime: 132 mins

Searching Letterboxd

from letterboxdpy.search import Search, SearchFilter

# Search for films
search = Search("Inception", search_filter=SearchFilter.FILMS)
results = search.get_results(3)

for item in results.get("results", []):
    print(f"{item.get('name')} ({item.get('year')}) -> {item.get('url')}")
Inception (2010) -> https://letterboxd.com/film/inception/

Architecture Overview

flowchart TD
    App[Your Application / Script] --> User[User Class]
    App --> Movie[Movie Class]
    App --> Search[Search Class]
    App --> List[List / Watchlist]
    App --> Films[Films Discovery]
    App --> Auth[UserSession / Settings]

    User --> Scraper[Scraper Gateway]
    Movie --> Scraper
    Search --> Scraper
    List --> Scraper
    Films --> Scraper
    Auth --> Scraper

    Scraper --> URLNorm[normalize_letterboxd_url]
    URLNorm --> Curl[curl_cffi Chrome TLS Session]
    Curl --> Letterboxd[(Letterboxd Web / CDN)]

Explore the Documentation

Module Guide Description API Reference
Getting Started Installation, Cloudflare resilience, core classes -
User Guide Profile stats, watched films, diary, wrapped, social User API
Movie Guide Details, cast, crew, reviews, similar movies Movie API
Search Guide Full-text search across 12 categories, slug lookup Search API
List Guide User lists, movie collections, tags, descriptions List API
Watchlist Guide Saved watchlists, genre/decade/provider filtering Watchlist API
Films & Discovery Browse upcoming, genres, themes, streaming services Films API
Members Guide Popular profiles, leaderboards, community members Members API
Authentication Sessions, profile updates, notification management Auth API
Examples & Tools Ready-to-run CLI utilities, export tools, visualizations -
Development Environment setup, pytest, Ruff linting, CI/CD -