@lorenzopant/tmdb
v1.21.2
Published
A completely type-safe The Movie Database (TMDB) API wrapper for typescript applications.
Downloads
2,734
Maintainers
Readme
🍿 @lorenzopant/tmdb
A TypeScript-first lightweight client for The Movie Database (TMDB) API.
This package is open-source and will be updated regularly with new features. Feel free to open pull requests on the project repository.
- 📦 Full TypeScript support
- 🔥 Simple and tiny wrapper
- 🚀 Designed for server-side and frontend use (NextJS, React, Vue, etc.)
Full documentation is available at @lorenzopant/tmdb
Installation
npm install @lorenzopant/tmdb
// or
pnpm add @lorenzopant/tmdb
// or
yarn add @lorenzopant/tmdbQuick Start
import { TMDB, TMDBError } from "@lorenzopant/tmdb";
const tmdb = new TMDB(process.env.TMDB_ACCESS_TOKEN!);
const movie = await tmdb.movies.details({ movie_id: 550 });
console.log(movie.title); // "Fight Club"Namespaces
Every namespace maps directly to a TMDB API section. All methods are fully typed.
| Namespace | Description |
| ------------------------ | ----------------------------------------------------------------- |
| tmdb.movies | Movie details, credits, images, videos, recommendations, and more |
| tmdb.movie_lists | Now Playing, Popular, Top Rated, Upcoming |
| tmdb.tv_series | TV series details, credits, seasons, episode groups |
| tmdb.tv_lists | Airing Today, On The Air, Popular, Top Rated TV |
| tmdb.tv_seasons | Season details, credits, images |
| tmdb.tv_episodes | Episode details, credits, images |
| tmdb.tv_episode_groups | Episode group details |
| tmdb.search | Search movies, TV shows, people, collections, keywords |
| tmdb.discover | Discover movies and TV shows by filter |
| tmdb.trending | Trending movies, TV, and people |
| tmdb.people | Person details, credits, images, translations |
| tmdb.people_lists | Popular people |
| tmdb.collections | Collection details and images |
| tmdb.companies | Company details, alternative names, images |
| tmdb.credits | Credit details |
| tmdb.genres | Movie and TV genre lists |
| tmdb.keywords | Keyword details and associated movies |
| tmdb.certifications | Movie and TV certifications per region |
| tmdb.changes | Recent content changes |
| tmdb.configuration | TMDB configuration, countries, languages, timezones |
| tmdb.find | Find resources by external ID (IMDb, TVDB, etc.) |
| tmdb.networks | TV network details |
| tmdb.watch_providers | Watch providers by region |
| tmdb.lists | User-created list management |
| tmdb.account | Account details and user lists |
| tmdb.authentication | Token-based authentication flows |
| tmdb.guest_sessions | Guest session rated movies/TV/episodes |
| tmdb.reviews | Review details |
| tmdb.images | Image URL builder (see below) |
| tmdb.v4 | TMDB API v4 (auth, account, lists — requires JWT) |
Constructor Options
const tmdb = new TMDB(accessToken, {
language: "en-US", // ISO 639-1: default language for all requests
region: "US", // ISO 3166-1: default region for all requests
timezone: "America/New_York", // default timezone for TV airing queries
logger: true, // enable built-in request/response logging
deduplication: true, // deduplicate concurrent identical requests (default: true)
rate_limit: true, // auto-queue requests to stay within TMDB rate limits
cache: true, // enable in-memory TTL-based response caching
images: {
secure_images_url: true,
default_image_sizes: { posters: "w500", backdrops: "w780" },
},
});logger
// Built-in console logger
const tmdb = new TMDB(token, { logger: true });
// Custom logger function
const tmdb = new TMDB(token, {
logger: (entry) => {
if (entry.type === "response") {
console.log(`[TMDB] ${entry.endpoint} → ${entry.status} (${entry.durationMs}ms)`);
}
},
});rate_limit
Automatically queues requests to stay within TMDB's API limits (~40 req/s). Useful for bulk scripts.
// Default limits
const tmdb = new TMDB(token, { rate_limit: true });
// Custom budget
const tmdb = new TMDB(token, { rate_limit: { max_requests: 30, per_ms: 1_000 } });cache
In-memory TTL-based caching for GET requests. Entries expire lazily on access.
// 5-minute TTL, no size limit (defaults)
const tmdb = new TMDB(token, { cache: true });
// Custom TTL and bounded size
const tmdb = new TMDB(token, {
cache: {
ttl: 60_000, // 60 seconds
max_size: 500, // evict oldest entry when limit is reached
excluded_endpoints: ["/trending", /\/discover\//],
},
});
// Runtime cache controls
tmdb.cache?.invalidate("/movie/now_playing"); // remove one entry
tmdb.cache?.clear(); // remove all entries
console.log(tmdb.cache?.size); // number of cached entriesinterceptors
Hook into every request or response globally.
const tmdb = new TMDB(token, {
interceptors: {
request: (ctx) => {
// Inject a param into every request
return { ...ctx, params: { ...ctx.params, include_adult: false } };
},
response: {
onSuccess: (data) => {
myAnalytics.track("tmdb_response", data);
},
onError: (error) => {
Sentry.captureException(error);
},
},
},
});Examples
Movie details
const movie = await tmdb.movies.details({ movie_id: 550 });
console.log(movie.title); // "Fight Club"
console.log(movie.release_date); // "1999-10-15"append_to_response — typed overloads
Fetch related data in a single request. The return type is automatically extended with the appended fields.
const movie = await tmdb.movies.details({
movie_id: 550,
append_to_response: ["credits", "videos"],
});
// TypeScript knows these are present:
console.log(movie.credits.cast[0].name);
console.log(movie.videos.results[0].key);Search
const results = await tmdb.search.movies({ query: "Inception", language: "en-US" });
console.log(results.results[0].title); // "Inception"TV series
const show = await tmdb.tv_series.details({ series_id: 1396 });
console.log(show.name); // "Breaking Bad"
const season = await tmdb.tv_seasons.details({ series_id: 1396, season_number: 1 });
console.log(season.episodes.length);Discover
const action = await tmdb.discover.movies({
with_genres: "28",
sort_by: "vote_average.desc",
"vote_count.gte": 1000,
});Trending
const trending = await tmdb.trending.movies({ time_window: "week" });Image URLs
const movie = await tmdb.movies.details({ movie_id: 550 });
// Build a full URL from a path
const posterUrl = tmdb.images.poster(movie.poster_path!, "w500");
const backdropUrl = tmdb.images.backdrop(movie.backdrop_path!, "w1280");
// Or enable auto-enrichment so all image paths in every response are resolved automatically
const tmdb = new TMDB(token, {
images: { autocomplete_images: true, secure_images_url: true },
});Error handling
import { TMDB, TMDBError } from "@lorenzopant/tmdb";
try {
const movie = await tmdb.movies.details({ movie_id: 0 });
} catch (error) {
if (error instanceof TMDBError) {
console.error(error.message); // human-readable message
console.error(error.http_status_code); // e.g. 404
console.error(error.tmdb_status_code); // TMDB-specific status code
}
}TMDB API v4 (requires JWT access token)
const tmdb = new TMDB(jwtAccessToken);
const lists = await tmdb.v4.lists.list({ account_id: "me" });Requirements
- Node.js 20+
- Works in frontend frameworks (React, Vue, Next.js) — never expose your access token to the browser in production
License
MIT
