Checks which films from your Letterboxd watchlist are streamable, and whether for free or not, via the TMDB API. Results are grouped into two sections — Free (free or free-with-ads) and Paid (subscription or rental) — based on what TMDB reports for each film.
The watchlist is fetched automatically from your public Letterboxd page — no manual export needed. An exported ZIP or CSV is still supported as a fallback.
$ cd ~/Documents/Code/all/watchlist_availability
$ ./run.sh
Fetching Letterboxd watchlist: 100%|██████████| 12/12 [00:03<00:00, 3.6 film/s]
Watchlist fetched from Letterboxd: @yourname (12 films)
Checking streaming availability on TMDB: 100%|██████████| 12/12 [00:08<00:00, 1.45 film/s]
## Paid
| Title | Year | Netflix | Canal+ |
|---------------:|-------:|:---------:|:--------:|
| Heat | 1995 | ✓ | ✓ |
| Gone Girl | 2014 | ✓ | |
| Ocean's Eleven | 2001 | | ✓ |
---
Netflix: 2
Canal+: 2
Results saved: /Users/you/Downloads/watchlist_2026-06-06.md- Python 3.11+ (uses
tomllibfrom the stdlib) - A free TMDB account for an API key
- A Letterboxd username whose watchlist is public (or, failing that, an exported file)
git clone https://github.com/your-username/watchlist-availability.git
cd watchlist-availability
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt- Copy the
.env.examplefile:cp .env.example .env
- Edit
.env:TMDB_API_KEY=your_key_here LETTERBOXD_USERNAME=your_username COUNTRY=FR- Get a free TMDB key at themoviedb.org/settings/api.
COUNTRYis the ISO 3166-1 alpha-2 code (e.g.FR,US,GB) — it must match a section inplatforms.toml.
Automatic (recommended). Set LETTERBOXD_USERNAME in .env. The script reads your
public watchlist directly (letterboxd.com/<username>/watchlist/), page by page, with a
progress bar. No manual download. Your watchlist must be public.
Fallback — ZIP or CSV. If scraping fails (private watchlist, outage) or
LETTERBOXD_USERNAME is empty, the script falls back to an exported file:
-
Sign in to letterboxd.com and go to:
https://letterboxd.com/data/export -
Drop the downloaded ZIP (or the extracted
watchlist.csv) into~/Downloads. -
Press Enter in the terminal — the script extracts
watchlist.csvfrom the ZIP automatically and deletes the ZIP. No manual unzipping needed.
The script also auto-detects watchlist*.csv files (both watchlist.csv and
watchlist-2024-06-01.csv are accepted).
What happens on failure? If scraping fails and nothing is found in Downloads, the
script does not crash: it prints a one-step guide (copy-paste link), then waits for
you to press Enter. Press Ctrl+C to cancel.
On every run, a dated Markdown file is written to Downloads
(e.g. watchlist_2026-06-06.md) so you can keep the result and avoid re-running it too often.
The canonical entry point is run.sh. Make sure you are in the project folder
first, then run it:
cd ~/path_to_project_folder
./run.shrun.sh activates the project's virtualenv and launches the script — no need to activate
.venv manually.
There are just two sections, detected automatically, per film, from TMDB's real monetization for that film on each provider (data sourced from JustWatch):
| Section | A ✓ appears when TMDB lists the film on the provider as… |
|---|---|
| Free | free or ads (watchable at no cost, possibly with ads) |
| Paid | flatrate (subscription) or rent (rental) |
The same provider can land in either section depending on the film, and a film can appear in
both at once — e.g. M6+ offering a film free-with-ads and by subscription puts it under
Free and Paid. The buy category (permanent purchase) is always excluded.
Note: TMDB does not expose expiry dates (the data comes from JustWatch's private API).
platforms.toml only chooses which platforms to check (true/false) — it does not
decide their section (that comes from TMDB, per film). The country is matched by the COUNTRY
setting in .env; each provider is a flat true/false toggle, grouped by comments for
readability only:
[FR]
# Typically free / ad-supported
Arte = true
Molotov = false
# Typically paid — subscription or rental
Netflix = true
"Canal+" = true
"TF1+" = true
"M6+" = false
"Canal VOD" = false
"Google Play" = false
[US]
Netflix = true
"Prime Video" = true
"Disney+" = true
Hulu = falseProvider names must match TMDB's own naming (verified against
GET /watch/providers/movie?watch_region=<COUNTRY>). To add a service not listed, extend
_ALL_PROVIDERS in watchlist_availability.py, then add it to the country section in
platforms.toml.
.venv/bin/python3.14 -m pytest tests/ -vThe tests are fully mocked — no real API key required.
watchlist-availability/
├── watchlist_availability.py # Main script (scraping + TMDB + rendering)
├── platforms.toml # Streaming services selection (per country)
├── run.sh # Entry point (venv + script)
├── tests/
│ └── test_watchlist.py # pytest suite (fully mocked)
├── .env.example # Configuration template
├── .gitignore
├── requirements.txt
└── README.md
Developed with the help of Claude (Anthropic).
MIT