TVmaze API alternative
TVmaze is TV only, free to use, rate limited per IP address, and its data is under an attribution license. Check their docs for the details. amodb is a paid API for TV, movies and people, with limits counted per key and TMDB v3 paths. Choose by scope and budget.
Choose by scope and budget
TVmaze is TV only. It is free to use as a public API with rate limits per IP address, and its data comes under an attribution license, so check their docs for the details. amodb is paid and covers TV, movies and people. If your app is a TV tracker and a free source meets your needs, TVmaze is a sensible start. If you also show films, cast pages or posters in several languages, one amodb key replaces several sources.
What each scope means for your app
| Your app shows | TVmaze | amodb |
|---|---|---|
| A TV show page | Yes | GET /3/tv/{series_id} |
| An episode list | Yes | GET /3/tv/{series_id}/season/{season_number} |
| A movie page | No movies | GET /3/movie/{movie_id} |
| An actor page | Check their docs | GET /3/person/{person_id} and combined credits |
| Shows airing today | Check their docs | GET /3/tv/airing_today |
| A translated overview | Check their docs | language parameter, 14 languages |
| Scores from several sites | Check their docs | /ratings extension |
The movie row decides most cases. If you have no film pages, the extra scope has no value to you.
Gaps to check before you move
The season and episode endpoints follow the TMDB shape, and a few parts of them come back empty. Test the screens that use them.
- Episode cast. On an episode,
castis an empty array.guest_starsandcreware filled, and the series/creditscall has the main cast. - Season extras. Season
images,videosandtranslationsare empty, so a season poster comes from the season record and not from an image list. - External ids. Season and episode
external_idsare all null. Map episodes to your own records byseason_numberandepisode_number. - Creators.
created_byon a series is empty for most shows. - No changes feed. amodb has no endpoint that lists the shows changed since a date.
Feature comparison
| Feature | TVmaze | amodb |
|---|---|---|
| Pricing model | Free to use public API | Prepaid, 1 to 24 months per purchase |
| Free tier | Yes, the whole public API | None, and no trial |
| Authentication | Check their docs | api_key or Bearer header |
| Response format | JSON, check their docs | JSON in TMDB v3 shape |
| Languages | Check their docs | 14 interface languages |
| Movies | No | Yes |
| TV | Yes, its only focus | Yes |
| People | Check their docs | Yes |
| Images | Check their docs | img.amodb.dev, ten size tokens |
| Ratings | Check their docs | Five sources where known |
| Rate limit | Per IP address, check their docs for numbers | 20, 40 or 120 per minute per key |
| Commercial use | Data under an attribution license, check their docs | Paid plans, see pricing |
| Compatibility | Its own API | TMDB v3 reads and OMDb |
Where amodb differs
- The limit follows the key. All your servers share one counter in a sliding 60 second window, and replies carry
X-RateLimit-Remaining. Nothing depends on which address a request leaves from. - Movies, TV and people in one place. One client, one error format and one set of headers cover the whole app.
- Languages. Titles and overviews come back in any of 14 languages, and
original_namekeeps the native title. - Established protocol. Libraries written for TMDB v3 reads work with a new base URL. See the TV show API page for the series endpoints.
Where TVmaze is a better fit
- No budget. It is free to use, so a student project or a weekend tracker needs no payment. amodb has no free tier and no trial.
- TV only, kept simple. If your data model has shows and episodes and nothing else, a TV focused API matches it.
- Its own conventions. Apps already built around the TVmaze model save work by staying.
If you stay, follow its attribution license. Check their docs for the wording.
Migrate to amodb
Start with a mapping job. Read the external ids that your stored TVmaze records list (check their docs for the field names) and resolve them through /3/find. The program below maps one IMDb id to a series and prints the next episode date.
package main
import (
"encoding/json"
"fmt"
"net/http"
"os"
"time"
)
type findResult struct {
TVResults []struct {
ID int `json:"id"`
Name string `json:"name"`
} `json:"tv_results"`
}
type episode struct {
AirDate string `json:"air_date"`
SeasonNumber int `json:"season_number"`
EpisodeNumber int `json:"episode_number"`
}
type series struct {
Name string `json:"name"`
Status string `json:"status"`
NextEpisode *episode `json:"next_episode_to_air"`
}
var client = &http.Client{Timeout: 10 * time.Second}
func get(path string, out any) error {
req, err := http.NewRequest(http.MethodGet, "https://api.amodb.dev/3"+path, nil)
if err != nil {
return err
}
req.Header.Set("Authorization", "Bearer "+os.Getenv("AMODB_KEY"))
res, err := client.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
if res.StatusCode != http.StatusOK {
return fmt.Errorf("amodb returned %s", res.Status)
}
return json.NewDecoder(res.Body).Decode(out)
}
func main() {
var found findResult
if err := get("/find/tt0903747?external_source=imdb_id", &found); err != nil {
fmt.Println(err)
return
}
if len(found.TVResults) == 0 {
fmt.Println("no match")
return
}
var s series
if err := get(fmt.Sprintf("/tv/%d", found.TVResults[0].ID), &s); err != nil {
fmt.Println(err)
return
}
fmt.Println(s.Name, s.Status)
if s.NextEpisode != nil {
fmt.Println("next episode:", s.NextEpisode.AirDate)
}
}The pointer type for NextEpisode handles the null that ended shows return. Run the mapping once, save the amodb id with each of your records, and call /3/tv/{id} from then on. A 429 is answered with Retry-After, and the find by external id page lists the other id sources.
Sizing a nightly sync
Suppose you refresh 300 shows each night. That is 300 requests, since one series call returns one show. At 20 requests per minute the job takes 15 minutes, at 40 it takes 7.5 minutes, and at 120 it takes 2.5 minutes. Add append_to_response=credits,ratings to each call so cast and scores arrive in the same request instead of costing two more per show. Read X-RateLimit-Remaining and pause when it reaches zero, then continue after the X-RateLimit-Reset seconds.
Pricing
amodb is prepaid and never renews on its own. Choose 1, 3, 6, 12 or 24 months and a plan of 20, 40 or 120 requests per minute. Longer periods are 10, 20, 30 or 40 percent cheaper, and each plan includes all data. Amounts are on pricing.
Questions and answers
Is the TVmaze API free?
TVmaze offers a free public API with rate limits per IP address, and its data is under an attribution license. Check their docs for current limits and the licence text. amodb is paid and has no free tier.
Does amodb cover movies as well as TV?
Yes. Movies, TV series, seasons, episodes and people are on the same key and base URL. TVmaze is TV only, so a movie page in your app needs a second source there.
How do I map TVmaze shows to amodb ids?
TVmaze show records list ids for other databases such as IMDb (check their docs for the exact fields). Call the find endpoint with the IMDb id and external_source=imdb_id, then store the id from tv_results.
Why does a per-IP limit matter?
A limit tied to an IP address is shared by everything behind it, such as a server pool or an office network. amodb counts requests per key in a sliding 60 second window, wherever the calls come from.
Can I show the next episode date for a show?
Yes. Series details return next_episode_to_air with air_date, season_number and episode_number, or null when nothing is scheduled. The edge caches details for 6 hours, so refresh a few times a day.