OMDb compatible endpoint

GET https://api.amodb.dev/omdb/ answers OMDb style requests with the same parameter and field names. Look up a title by IMDb id with i or by title with t, or search with s. Poster links point to img.amodb.dev. Only r=json, movies and series are served. Change the base URL and the key, and a typical client keeps working.

Look up a title by IMDb id or title

GET https://api.amodb.dev/omdb/ returns one title as flat JSON with OMDb field names. Pass i for an IMDb id such as tt0137523, or t for a title. Auth is the apikey query parameter. The reply has Response set to True on success and False on failure.

The sample loads Fight Club by IMDb id and stops with the OMDb error text when Response is False.

curl -sf "https://api.amodb.dev/omdb/?i=tt0137523&plot=short&apikey=$AMODB_KEY"
const params = new URLSearchParams({ i: 'tt0137523', plot: 'short', apikey: process.env.AMODB_KEY });
const res = await fetch(`https://api.amodb.dev/omdb/?${params}`);
if (!res.ok) throw new Error(`amodb returned ${res.status}`);
const data = await res.json();
if (data.Response === 'False') throw new Error(data.Error);
console.log(data.Title, data.Year, data.imdbRating);
import os
import requests

r = requests.get(
    "https://api.amodb.dev/omdb/",
    params={"i": "tt0137523", "plot": "short", "apikey": os.environ["AMODB_KEY"]},
    timeout=10,
)
r.raise_for_status()
data = r.json()
if data["Response"] == "False":
    raise SystemExit(data["Error"])
print(data["Title"], data["Year"], data["imdbRating"])
<?php
$query = http_build_query(['i' => 'tt0137523', 'plot' => 'short', 'apikey' => getenv('AMODB_KEY')]);
$ch = curl_init('https://api.amodb.dev/omdb/?' . $query);
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 10]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status !== 200) {
    throw new RuntimeException("amodb returned $status");
}
$data = json_decode($body, true);
if ($data['Response'] === 'False') {
    throw new RuntimeException($data['Error']);
}
echo $data['Title'], ' ', $data['Year'], ' ', $data['imdbRating'], PHP_EOL;
package main

import (
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
	"os"
	"time"
)

type Title struct {
	Title      string `json:"Title"`
	Year       string `json:"Year"`
	ImdbRating string `json:"imdbRating"`
	Response   string `json:"Response"`
	Error      string `json:"Error"`
}

func main() {
	q := url.Values{"i": {"tt0137523"}, "plot": {"short"}, "apikey": {os.Getenv("AMODB_KEY")}}
	client := &http.Client{Timeout: 10 * time.Second}
	res, err := client.Get("https://api.amodb.dev/omdb/?" + q.Encode())
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	if res.StatusCode != http.StatusOK {
		panic(res.Status)
	}
	var t Title
	if err := json.NewDecoder(res.Body).Decode(&t); err != nil {
		panic(err)
	}
	if t.Response == "False" {
		panic(t.Error)
	}
	fmt.Println(t.Title, t.Year, t.ImdbRating)
}

Parameters

ParameterInRequiredDescription
apikeyqueryyesYour amodb key.
iqueryone of i, t, sIMDb id of the title: tt plus 7 to 9 digits, for example tt0137523.
tqueryone of i, t, sTitle to look up, returns the best match.
squeryone of i, t, sSearch text of at least 3 letters, returns a list.
typequerynomovie or series. episode finds nothing.
yquerynoRelease year.
plotquerynoshort or full. Default short.
pagequerynoPage of search results, 1 to 100. Used with s.
rquerynojson only. Any other value returns HTTP 400.

The Season, Episode, callback and v parameters from the original OMDb API are not supported and are ignored.

Response fields

FieldNotes
Title, Year, Rated, Released, RuntimeText. Released reads like 15 Oct 1999.
Genre, Director, Writer, ActorsComma separated names.
Plot, Language, Country, AwardsText.
PosterAddress on https://img.amodb.dev/t/p/w300/.
RatingsArray of objects with Source and Value.
Metascore, imdbRating, imdbVotes, imdbIDText, including the vote count with commas.
Typemovie or series.
DVD, BoxOffice, Production, WebsiteMovies only. BoxOffice carries a value when known. DVD, Production and Website always read N/A.
totalSeasonsSeries only, as text. Series replies have no DVD, BoxOffice, Production or Website.
ResponseTrue or False, always a string.

Fields follow OMDb, so an existing OMDb parser needs no change beyond the base URL.

Example response

JSON
{
  "Title": "Fight Club",
  "Year": "1999",
  "Rated": "R",
  "Released": "15 Oct 1999",
  "Runtime": "139 min",
  "Genre": "Crime, Drama, Thriller",
  "Director": "David Fincher",
  "Writer": "Chuck Palahniuk, Jim Uhls",
  "Actors": "Brad Pitt, Edward Norton, Meat Loaf",
  "Plot": "A nameless first-person narrator attends support groups in an attempt to subdue his emotional state and relieve his insomniac state.",
  "Language": "English",
  "Country": "United States, Germany",
  "Awards": "Nominated for 1 Oscar. 12 wins & 38 nominations total",
  "Poster": "https://img.amodb.dev/t/p/w300/qkrH7rjYKU4KOwwIl6wF6H3ISvm.jpg",
  "Ratings": [
    { "Source": "Internet Movie Database", "Value": "8.8/10" },
    { "Source": "Rotten Tomatoes", "Value": "81%" },
    { "Source": "Metacritic", "Value": "67/100" }
  ],
  "Metascore": "67",
  "imdbRating": "8.8",
  "imdbVotes": "2,669,989",
  "imdbID": "tt0137523",
  "Type": "movie",
  "DVD": "N/A",
  "BoxOffice": "$38,003,039",
  "Production": "N/A",
  "Website": "N/A",
  "Response": "True"
}

For a series such as The Wire (i=tt0306414), the reply ends with "Type": "series", "totalSeasons": "5" and "Response": "True".

Search with s

Send s to get a list instead of one title. Each page holds 10 items, and totalResults gives the full count as a string. Request page=2 for items 11 to 20, and keep going until you have read totalResults items. A page past the last one answers Movie not found!.

curl
curl -sf "https://api.amodb.dev/omdb/?s=Matrix&type=movie&page=1&apikey=$AMODB_KEY"
FieldNotes
SearchArray of up to 10 items with Title, Year, imdbID, Type, Poster.
totalResultsCount of all matches, as a string.
ResponseTrue or False.
JSON
{
  "Search": [
    {
      "Title": "The Matrix",
      "Year": "1999",
      "imdbID": "tt0133093",
      "Type": "movie",
      "Poster": "https://img.amodb.dev/t/p/w300/kEDbym5htJgDQNenjUtSJxAHysB.jpg"
    },
    {
      "Title": "The Matrix Reloaded",
      "Year": "2003",
      "imdbID": "tt0234215",
      "Type": "movie",
      "Poster": "https://img.amodb.dev/t/p/w300/d0xVNNxIYxId2qHkqpgE39soOvD.jpg"
    }
  ],
  "totalResults": "20",
  "Response": "True"
}

The list is cut to 2 of 10 items.

Read the Ratings array

Ratings holds one object per source, each with Source and Value, and the Value is text such as 8.8/10. The sources are Internet Movie Database, Rotten Tomatoes and Metacritic, and only the ones known for the title are listed. The flat fields imdbRating, imdbVotes and Metascore repeat some of the same data. Split Value on the slash if you need a number. For typed numbers and a Kinopoisk and TMDB score, use the ratings endpoint instead.

Errors

Lookup failures return {"Response":"False","Error":"..."}. Most of them come with HTTP 200, so read Error and branch on the text, not on the HTTP status alone.

Error textHTTPWhen
Movie not found!200No title matches t, the i value is valid but unknown, or a search page is past the last one.
Incorrect IMDb ID.200The i value is not shaped like an IMDb id.
Too many results.200The search text is shorter than 3 letters or matches too many titles. Make the text longer or add type or y.
Something went wrong.200None of i, t and s was sent.
Only r=json is supported.400r is set to anything but json.
No API key provided. or Invalid API key!401The apikey is missing or wrong.
Request limit reached!429Over your requests per minute. Wait for the Retry-After seconds.

An ended plan answers HTTP 402. See errors and rate limits.

Migrate an OMDb client

The migration is two edits: the base URL and the key. Nothing else in the request changes.

JavaScript
// Before: the base URL and key of your current OMDb setup.
// After:
const OMDB_BASE = 'https://api.amodb.dev/omdb/';
const OMDB_KEY = process.env.AMODB_KEY;

Remove r=xml if you send it. A client that reads episodes, Season or callback needs another source for those parts. The rate limit is per key, so OMDb style calls and TMDB style calls share one budget of 20, 40 or 120 requests per minute.

Practical notes

  • Treat every value as text. Convert Year, imdbRating and totalResults yourself, and treat N/A as missing.
  • Use plot=full only when you show the long plot. short keeps responses smaller.
  • Lookups by i or t are cached longer than searches with s, so a repeated lookup returns the stored answer.
  • To get a TMDB id from an IMDb id, call find by external id.
  • Posters are at w300. For other sizes, build the address from the TMDB style poster_path and the images size list.
  • Keep the key on a server. An apikey in a page URL is visible to every visitor.