A Swift Package for The Movie Database (TMDb) https://www.themoviedb.org
- Comprehensive API Coverage: Full support for TMDb API v3 with 25 specialized services
- Append to Response: Fetch details with credits, images, videos,
and more in a single request using
append_to_response - Movie & TV Data: Details, credits, images, videos, reviews, recommendations, similar content
- Discovery & Search: Advanced filtering, multi-type search, trending content
- User Features: Account management, favorites, watchlists, ratings (requires authentication)
- Metadata: Genres, certifications, companies, collections, watch providers
- Image Generation: Built-in URL generation for all image types with size optimization
- Swift 6 Ready: Full strict concurrency support with Sendable types
- Cross-Platform: iOS 16+, macOS 13+, watchOS 9+, tvOS 16+, visionOS 1+, Linux, Windows
- Automatic Retry: Opt-in retry with exponential backoff for rate limits (HTTP 429) and server errors (HTTP 5xx)
- Response Caching: Opt-in in-memory HTTP response cache with configurable TTL and entry limits
- Modern Swift: Async/await throughout, strongly-typed models, protocol-based architecture
| Service | Description |
|---|---|
| movies | Movie details, credits, keywords, images, videos, reviews, recommendations, similar, releases, watch providers, append-to-response |
| tvSeries | TV show details, credits, images, videos, reviews, recommendations, similar, watch providers, screened theatrically, episode groups, append-to-response |
| tvSeasons | Season-specific details, aggregate credits, credits, images, videos, translations, watch providers, append-to-response |
| tvEpisodes | Episode-specific details, credits, images, videos, translations, append-to-response |
| people | Person details, combined/movie/TV credits, images, external links, translations, append-to-response |
| search | Multi-search across movies, TV shows, people, collections, companies, keywords |
| discover | Advanced filtering for movies and TV shows with 30+ filter options |
| trending | Trending movies, TV shows, people, and all media (daily/weekly) |
| find | Find movies, TV shows, and people by external IDs (IMDb, TVDB, etc.) |
| account | User favorites, watchlist, rated items (requires authentication) |
| authentication | Session management, guest sessions, request tokens |
| genres | Genre lists for movies and TV shows |
| keywords | Keyword details and movies by keyword |
| networks | TV network details, alternative names, logos |
| watchProviders | Streaming availability by region |
| certifications | Content ratings (G, PG, R, etc.) |
| collections | Movie collection details, images, translations |
| companies | Production company details, alternative names, logos |
| lists | Custom list management (requires authentication) |
| configurations | API configuration, countries, jobs, languages, primary translations, timezones |
| changes | Track changes to movies, TV series, people, seasons, and episodes |
| credits | Credit details including person and media information |
| reviews | Review details with author and media information |
| tvEpisodeGroups | TV episode group details and episode organization |
| guestSessions | Guest session rated movies, TV series, and episodes |
See the full API documentation for detailed usage.
- Swift 6.0+
- OS
- macOS 13+
- iOS 16+
- watchOS 9+
- tvOS 16+
- visionOS 1+
- Windows
- Linux
Add the TMDb package as a dependency to your Package.swift file, and add it
as a dependency to your target.
// swift-tools-version:6.0
import PackageDescription
let package = Package(
name: "MyProject",
dependencies: [
.package(url: "https://github.com/adamayoung/TMDb.git", from: "14.0.0")
],
targets: [
.target(name: "MyProject", dependencies: ["TMDb"])
]
)Add the TMDb package to your Project's Package dependencies.
Create an API key from The Movie Database web site https://www.themoviedb.org/documentation/api.
import TMDb
// Initialize client
let tmdbClient = TMDbClient(apiKey: "<your-tmdb-api-key>")
// Discover movies with filters
let popularMovies = try await tmdbClient.discover.movies(
sortedBy: .popularity(descending: true)
).results
// Get movie details
let fightClub = try await tmdbClient.movies.details(forMovie: 550)
print("Title: \(fightClub.title)")
print("Release Date: \(fightClub.releaseDate)")
print("Rating: \(fightClub.voteAverage)/10")
// Search across movies, TV shows, and people
let searchResults = try await tmdbClient.search.multi(query: "Breaking Bad")
// Get trending movies today
let trendingMovies = try await tmdbClient.trending.movies(inTimeWindow: .day)
// Get streaming providers for a movie
let watchProviders = try await tmdbClient.movies.watchProviders(forMovie: 550)
if let usProvider = watchProviders.first(where: { $0.countryCode == "US" }) {
print("Available on: \(usProvider.watchProviders.flatRate?.map(\.providerName) ?? [])")
}
// Generate poster image URL
let config = try await tmdbClient.configurations.apiConfiguration()
if let posterPath = fightClub.posterPath {
let posterURL = config.images.posterURL(for: posterPath, idealWidth: 500)
}By default, the TMDb client automatically uses your system's language and
country settings from Locale.current:
import TMDb
// Uses system locale automatically (recommended)
let tmdbClient = TMDbClient(apiKey: "<your-api-key>")You can also configure the client with custom language and country settings:
// Custom configuration
let configuration = TMDbConfiguration(
defaultLanguage: "es-ES", // ISO 639-1 language code
defaultCountry: "ES" // ISO 3166-1 country code
)
let tmdbClient = TMDbClient(apiKey: "<your-api-key>", configuration: configuration)
// Disable locale defaults (API determines language)
let tmdbClient = TMDbClient(apiKey: "<your-api-key>", configuration: .default)Per-request overrides are always available:
// Override language for a specific request
let movieInFrench = try await tmdbClient.movies.details(forMovie: 550, language: "fr")Enable automatic retry with exponential backoff for transient errors:
// Use default retry (3 retries, exponential backoff)
let configuration = TMDbConfiguration(retry: .default)
let tmdbClient = TMDbClient(apiKey: "<your-api-key>", configuration: configuration)
// Custom retry configuration
let retryConfig = RetryConfiguration(
maxRetries: 5,
initialDelay: .seconds(2),
retryableErrors: .rateLimit // Only retry rate limit errors
)
let tmdbClient = TMDbClient(
apiKey: "<your-api-key>",
configuration: TMDbConfiguration(retry: retryConfig)
)Enable in-memory response caching to reduce redundant network requests:
// Use default caching (1-hour TTL, 100 entries)
let configuration = TMDbConfiguration(cache: .default)
let tmdbClient = TMDbClient(apiKey: "<your-api-key>", configuration: configuration)
// Custom cache configuration
let cacheConfig = CacheConfiguration(
defaultTTL: .seconds(1800), // 30-minute TTL
maximumEntryCount: 200
)
let tmdbClient = TMDbClient(
apiKey: "<your-api-key>",
configuration: TMDbConfiguration(cache: cacheConfig)
)
// Combine retry and caching
let tmdbClient = TMDbClient(
apiKey: "<your-api-key>",
configuration: TMDbConfiguration(retry: .default, cache: .default)
)let movie = try await tmdbClient.movies.details(forMovie: movieId)
let credits = try await tmdbClient.movies.credits(forMovie: movieId)
let images = try await tmdbClient.movies.images(forMovie: movieId)let movies = try await tmdbClient.discover.movies(
sortedBy: .popularity(descending: true),
withGenres: [28, 12], // Action & Adventure
releaseDateGTE: Date().addingTimeInterval(-365*24*60*60) // Last year
)let providers = try await tmdbClient.movies.watchProviders(forMovie: movieId)
if let usProvider = providers.first(where: { $0.countryCode == "US" }) {
print("Available on: \(usProvider.watchProviders.flatRate?.map(\.providerName) ?? [])")
}Iterate through all pages of paginated results using AsyncSequence without manual pagination:
// Iterate through all popular movies across all pages
for try await movie in tmdbClient.movies.allPopular() {
print(movie.title)
// Automatically fetches next page when needed
}
// Early break stops fetching additional pages
var count = 0
for try await movie in tmdbClient.movies.allTopRated() {
count += 1
if count >= 50 { break }
}
// Iterate through entire pages with metadata
for try await page in tmdbClient.movies.allPopularPages() {
print("Page \(page.page ?? 0) of \(page.totalPages ?? 0)")
for movie in page.results {
print(" - \(movie.title)")
}
}Available for all paginated endpoints across 7 services: MovieService
(8 endpoints), SearchService (7 endpoints), TrendingService (4 endpoints),
TVSeriesService (8 endpoints), PersonService (2 endpoints),
DiscoverService (2 endpoints), and ListService (1 endpoint). Total: 32
paginated endpoints with 64 auto-pagination methods.
// Add to favorites
try await tmdbClient.account.addToFavourites(movie: movieId, accountId: accountId)
// Rate a movie
try await tmdbClient.movies.addRating(8.5, toMovie: movieId)
// Get watchlist
let watchlist = try await tmdbClient.account.movieWatchlist(accountId: accountId)Documentation and examples of usage can be found at https://adamayoung.github.io/TMDb/documentation/tmdb/
- TMDb API Documentation
- Swift Package Index
- Full API Reference
- Getting Started Guide
- Image URL Generation Guide
Xcode 16.0+ Swift 6.0+ Homebrew
Install homebrew and the following formulae
brew install swiftlint swiftformat markdownlint xcsiftSee CLAUDE.md for comprehensive development guidelines including:
- Testing requirements (unit and integration tests)
- Code style enforcement with swift-format
- DocC documentation requirements
- Complete CI check commands
Quick reference:
make format # Auto-format code
make lint # Check code style
make test # Run unit tests
make ci # Full CI validationImportant: Both unit tests AND integration tests must pass. Integration tests require these environment variables:
TMDB_API_KEY- Your TMDb API keyTMDB_USERNAME- Your TMDb usernameTMDB_PASSWORD- Your TMDB password
Running unit tests on Linux requires Docker to be running.
- The Movie Database (TMDb) for providing the comprehensive movie and TV data API
- JustWatch for watch provider data
- All contributors who have helped improve this library
Disclaimer: This product uses the TMDb API but is not endorsed or certified by TMDb.
This library is licensed under the Apache License 2.0. See LICENSE for details.