Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Imports Letterboxd scores into

Letterboxd -> import script

This script imports your Letterboxd ratings into


Too lazy to make this into an npm package so here's how you could use it. You'll need nodejs and npm.

  1. Save the script
  2. Run npm i through2 JSONStream got cookie x-ray in the script's directory
  3. Login to and go to your home page. Open your browser's developer tools to the network tab. Refresh the page and look for the request to the /me endpoint. Copy the Authorization token from the headers.
  4. Edit the script at the top with your own letterboxd username and token.
  5. Run node letterboxd2taste.js
  6. cool ur done now
'use strict'
// Letterboxd username
const LETTERBOXD_USERNAME = 'rahatarmanahmed'
// Authorization token
// Too lazy to impl auth considering my account is facebook oauth'd
const TOKEN = ''
// Maps letterboxd 10 point rating scale to 4 point scale.
// Adjust if desired
const mapRating = function(rating) {
// 1 2 3 4 5 6 7 8, 9, 10
return [null, 1, 1, 1, 2, 2, 3, 3, 3, 4, 4][rating]
// =================================================================
const through2 = require('through2')
const JSONStream = require('JSONStream')
const got = require('got')
const cookie = require('cookie')
const Xray = require('x-ray')
const x = Xray()
const serializeCookie = function(obj) {
return Object.keys(obj).map((key) => cookie.serialize(key, obj[key])).join('; ')
// Scrape my letterboxd watchlist
const url = `${LETTERBOXD_USERNAME}/films/`
x(url, '.film-list', x('.poster-container', [{
rating: '@data-owner-rating',
title: '.film-poster img@alt'
// Stream the scraped titles one by one
.pipe(through2.obj(function({title, rating}, enc, cb){
if(rating == 0) {
console.log(`Skipping ${title}`)
return cb(null)
console.log(`Rating ${title} as ${rating} -> ${mapRating(rating)}...`)
got('' + encodeURIComponent(title), { headers: {
Authorization: 'Bearer ' + TOKEN
}, json: true })
.then(res => {
if(!res.body.length) return
const cook = cookie.parse(res.headers['set-cookie'].join('; '))
return'', {
headers: {
Authorization: 'Bearer ' + TOKEN,
Cookie: serializeCookie(cook),
body: {
id: res.body[0].slug,
rating: mapRating(rating)
.then(_ => cb(null, 'Success!\n'))
.catch(err => { console.error(err); cb(err) })
// Pipe results to stdout!
.on('error', err => console.error(err))

This comment has been minimized.

Copy link

@johanhermansson johanhermansson commented Aug 7, 2019

Updated script to new Letterboxd/Taste structure:


This comment has been minimized.

Copy link

@pedromga pedromga commented Sep 29, 2019

just what i was looking for. does this still work? if so, what happens if the movie is missing from taste database? thanks in advance.


This comment has been minimized.

Copy link
Owner Author

@rahatarmanahmed rahatarmanahmed commented Sep 29, 2019

i dunno i just wrote this in an hour 3 years ago, it's not exactly production quality.


This comment has been minimized.

Copy link

@johanhermansson johanhermansson commented Sep 30, 2019

@pedromga Check out my Gist above, I used it myself in August :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.