trakt-to-letterboxd
Sync Trakt movie watches to Letterboxd via the ttl CLI.
- Pull new watches from Trakt into
export.csv(accumulates) - Upload
export.csvto Letterboxd, then clear it on success - Manual Cloudflare Turnstile in Chrome when Letterboxd requires it
Install
Requires pipx and Google Chrome.
pipx install trakt-to-letterboxd
From GitHub (latest main, or before a PyPI release exists):
pipx install git+https://github.com/louiscrc/trakt-to-letterboxd.git
This installs the ttl command globally. Check with ttl --help.
Setup
ttl init
# Prompts for Letterboxd username/password and Trakt client ID/secret
Non-interactive (writes a template to edit by hand):
ttl init --non-interactive
Get Trakt API credentials at https://trakt.tv/oauth/applications/new (redirect URI: urn:ietf:wg:oauth:2.0:oob).
On first Trakt sync you'll authenticate via device code.
config.yml stores your Letterboxd password in plaintext. Keep the data directory private and never commit that file.
Usage
ttl --version
ttl init # interactive config setup
ttl init --non-interactive # write template config only
ttl trakt # pull new watches from Trakt into export.csv
ttl letterboxd # upload export.csv to Letterboxd, then clear it
ttl sync # trakt then letterboxd (stops if trakt fails)
ttl letterboxd --no-diary # skip diary entries on Letterboxd import
ttl letterboxd --manual-sign-in # fill credentials but do not auto-click Sign In
ttl trakt --dry-run # Trakt: fetch only, no CSV writes
ttl letterboxd --dry-run # Letterboxd: stop before Import Films (Ctrl-C to exit)
ttl trakt -v # verbose progress logs
ttl trakt --config /path.yml # custom config path
Letterboxd upload flow
ttl letterboxd opens Chrome and:
- Navigates to letterboxd.com — complete Turnstile if Cloudflare shows it
- If not logged in, opens sign-in, pre-fills credentials, and tries to click Sign In automatically. Use
--manual-sign-into click yourself when the automatic click fails (Cloudflare sometimes treats it as a bot). - Uploads
export.csv, clicks Import Films, waits for Saved N films.
Data directory
ttl stores all user data in a fixed app folder (created automatically). It does not use your current working directory.
| Platform | Directory |
|---|---|
| macOS | ~/Library/Application Support/trakt-to-letterboxd/ |
| Linux | ~/.local/share/trakt-to-letterboxd/ (or $XDG_DATA_HOME/trakt-to-letterboxd/) |
| Windows | %LOCALAPPDATA%\trakt-to-letterboxd\ |
Layout:
| Path | Description |
|---|---|
config.yml |
Credentials and Trakt OAuth state |
csv/export.csv |
Pending queue for Letterboxd (grows with ttl trakt, cleared after successful ttl letterboxd) |
csv/merged.csv |
Full Trakt merged history (ratings + watch history) |
csv/ratings.csv |
Trakt ratings |
csv/watched.csv |
Trakt watch history |
chrome_profile/ |
Persistent Chrome session (Letterboxd login) |
CSV format: Title,Year,Rating10,Rewatch,imdbID,WatchedDate
ttl init prints the resolved paths. Override only the config file with --config /path/to/config.yml if needed; CSVs and the Chrome profile always stay under the data directory above.
Automation limits
Fully unattended / headless mode is not reliable: starting Chrome headless systematically re-triggers Cloudflare. In normal (headed) mode you usually only need to complete Turnstile (and occasionally Sign In) once in a while; a warm chrome_profile keeps most runs automated.
Development
Install from source:
git clone https://github.com/louiscrc/trakt-to-letterboxd.git
cd trakt-to-letterboxd
pipx install -e .
Optional environment overrides for Chrome (advanced):
| Variable | Purpose |
|---|---|
CHROME_BIN |
Path to the Chrome/Chromium binary |
CHROMEDRIVER_PATH |
Path to a local chromedriver (skips webdriver-manager) |
License
MIT © Louis Cresci. See LICENSE.
Release files for trakt-to-letterboxd 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| trakt_to_letterboxd-0.1.0.tar.gz | 21.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| trakt_to_letterboxd-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 43.7 kB
Release files / trakt_to_letterboxd-0.1.0.tar.gz
| Download URL | trakt_to_letterboxd-0.1.0.tar.gz |
|---|---|
| Size | 21.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a5b91fca8cc3a7277c356b3c5283f7112c73f59bc3ed23396966c4c967107102
|
|
BLAKE2b-256 checksum How to use checksums |
aadd31827b7f8b93409370c9b0a1c9f252c04ff0844942dd6a3b3b29ca84405a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 19, 2026.
Transparency logRelease files / trakt_to_letterboxd-0.1.0-py3-none-any.whl
| Download URL | trakt_to_letterboxd-0.1.0-py3-none-any.whl |
|---|---|
| Size | 22.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1927d937a457ff46d8a8fb005b093564c0e2e8cd3429b0dfc3557c55b72857fd
|
|
BLAKE2b-256 checksum How to use checksums |
2d58bc4e59525e96363f5b0f4aaa93145f505758e6cf5f1823eb413738f0de0e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 19, 2026.
Transparency log