Skip to content

Latest commit

 

History

History
550 lines (394 loc) · 18.6 KB

File metadata and controls

550 lines (394 loc) · 18.6 KB
icon lucide/hammer

Usage

This library provides multiple functions for accessing JustWatch:

  • search - search for entries based on title
  • popular - get a list of currently popular titles
  • details - get details for a title based on its ID
  • seasons - get information about all seasons of a show
  • episodes - get information about all episodes of a season
  • offers_for_countries - get offers for a title for multiple countries simultaneously
  • providers - get data about all available providers (like Netflix) in a country

All functions return response from JustWatch API parsed into a [NamedTuple] [typing.NamedTuple], check [Data structures](API Reference/data.md) page for more details.

All needed functions, data structures, raised exceptions are available through single module - simplejustwatchapi.

Examples of parsed responses are in the GitHub repository in examples/.


Each function can raise two exceptions:

You can check [Exceptions](API Reference/exceptions.md) page for more details.


Functions

Common arguments

Most functions have a number of common arguments (in addition to function-specific ones, like title to search for):

Name Description
country 2-letter country code for which offers will be returned, e.g., US, GB, DE.
language Code for language in responses. It consists of 2 lowercase letters with optional uppercase alphanumeric suffix (e.g., en, en-US, de, de-CH1901).
best_only Whether to return only "best" offers for each provider instead of, e.g., separate offers for SD, HD, and 4K.

Functions returning data for multiple titles ([search][simplejustwatchapi.justwatch.search], [popular][simplejustwatchapi.justwatch.popular]) also allow for specifying number of elements, basic pagination, and optional filtering:

Name Description
count How many entries should be returned.
offset Basic "pagination". Offset for the first returned result, i.e. how many first entries should be skipped. Everything is handled on API side, this library isn't doing any filtering.
providers Providers (like Netflix, Amazon Prime Video) for which offers should returned. Requires 3-letter "short name". Check Provider codes page for an example of how you can get that value.
min_release_year Minimum release year for a title.
max_release_year Maximum release year for a title.
object_types Types of objects to filter for, such as SHOW or MOVIE. Check Additional filtering section for more details.

Search for a title

[search][simplejustwatchapi.justwatch.search]{data-preview} function allows for searching entries based on a given title.

from simplejustwatchapi import search

results = search("The Matrix", "US", "en", 5, True, 0, ["nfx", "apv"])

for entry in results:
    print(entry.title, entry.offers)

!!! note "Whitespaces in title" Value of the given title isn't stripped, so passing a string with multiple spaces will look them up. For more than 1 space it will probably return an empty list.

All arguments are optional.

First argument is just a string to look up. If empty, or not provided, you'll get a selection of popular titles, similar to popular function.

For very large searches (high count value) I recommend using default best_only=True to avoid issues with operation complexity. Alternatively you can offset for basic pagination.

Example function call and its output is in examples/search_output.py.

Popular titles

[popular][simplejustwatchapi.justwatch.popular]{data-preview} function allows for getting a list of currently popular titles.

from simplejustwatchapi import popular

results = popular("US", "en", 5, True, 0, ["nfx", "apv"])

for entry in results:
    print(entry.title, entry.offers)

All arguments are optional.

The usage and output will be similar to search, function without any titles specified.

No arguments are required.

For very large searches (high count value) I recommend using default best_only=True to avoid issues with operation complexity. Alternatively you can offset for basic pagination.

Example function call and its output is in examples/popular_output.py.

Details for a title based on its ID

[details][simplejustwatchapi.justwatch.details]{data-preview} function allows for looking up details for a single entry via its node ID.

from simplejustwatchapi import details

result = details("tm19698", "US", "en", False)

print(result.title, result.short_description)

Node ID can be taken from output of the search function.

!!! note "Usefulness versus search" This function is only useful if you have node ID already stored. There's no reason to first use the search, then use node ID from one of entries for details, you won't get any additional information.

Only the first argument is required - the node ID of element to look up details for.

This function can be used for all types of media - shows, movies, episodes, seasons (the last two having their dedicated functions described below), for all types the result is a single [MediaEntry][simplejustwatchapi.tuples.MediaEntry]. Some fields are specific for one of the media types and will be None for others - for example:

  • total_episode_count is only present for seasons
  • season_number is present for seasons and episodes
  • episode_number is present only for episodes
  • age_certification is present only for movies and shows

For episodes specifically most of the fields will be empty (which is why episodes function returns different structure).

Example function call and its output is in examples/details_output.py.

Details for all seasons of a TV show

[seasons][simplejustwatchapi.justwatch.seasons]{data-preview} function allows for looking up details for all seasons of a TV show based on its node ID.

from simplejustwatchapi import seasons

results = seasons("tss20091", "US", "en", True)

for season in results:
    print(season.season_number, season.total_episode_count)

Only the first argument is required - the node ID of a TV show to look up season details for.

Example function call and its output is in examples/seasons_output.py.

Details for all episodes of a TV show

[episodes][simplejustwatchapi.justwatch.episodes]{data-preview} function allows for looking up details for all episodes of a single TV show season based on its node ID.

from simplejustwatchapi import episodes

results = episodes("tse334769", "US", "en", False)

for episode in results:
    print(episode.episode_id, episode.episode_number, episode.offers)

Only the first argument is required - the node ID of a season to look up episode details for.

Returned value is a list of [Episode][simplejustwatchapi.tuples.Episode], which contains only a small subset of fields from the [MediaEntry] [simplejustwatchapi.tuples.MediaEntry]. JustWatch API doesn't return "full" data for individual episodes.

Example function call and its output is in examples/episodes_output.py.

Get offers for multiple countries for a single title

[offers_for_countries][simplejustwatchapi.justwatch.offers_for_countries]{data-preview} function allows for looking up offers for a single entry, but for multiple countries at once. Only offers are returned.

from simplejustwatchapi import offers_for_countries

results = offers_for_countries("tm10", {"US", "UK", "CA"}, "en", True)

for country, offers in results.items():
    print(f"Offers for {country}:")
    for offer in offers:
        print(f"  - {offer.package.name}: {offer.monetization_type}")

First two arguments are required - ID, and a set of country codes.

Example function call and its output is in examples/offers_for_countries_output.py.

Get all available providers for a country

[providers][simplejustwatchapi.justwatch.providers]{data-preview} function allows for looking up all available service providers (such as "Netflix", "Amazon Prime Video", etc.) for a given country.

from simplejustwatchapi import providers

results = providers("US")

netflix_apple_only = [
    provider
    for provider in all_providers
    if provider.name in ("Netflix", "Apple TV")
]

Returned value is a list of [OfferPackage][simplejustwatchapi.tuples.OfferPackage]. Initially they were meant to be used for [Offer][simplejustwatchapi.tuples.Offer] in [MediaEntry][simplejustwatchapi.tuples.MediaEntry]/[Episode] [simplejustwatchapi.tuples.Episode], however the data structure matches output here, so it's reused.

You can use this function to get values for providers for search and popular functions, the short_name field in [OfferPackage][simplejustwatchapi.tuples.OfferPackage] is the exact 3-letter code needed there.

Example function call and its output is in examples/providers_output.py.


Error handling

HTTP errors

[JustWatchHttpError][simplejustwatchapi.exceptions.JustWatchHttpError]{data-preview} is raised when HTTP-related error occurs, e.g., JustWatch API responds with non-2xx status code.

Non-2xx response status codes can happen when trying to use incorrect type for parameters, e.g., trying to use a non-numeric string for count:

from simplejustwatchapi import search, JustWatchHttpError

try:
    results = search("The Matrix", count="five")
except JustWatchHttpError as e:
    print(str(e), e.response)

Aside from exception message, the error can also contains optional field response with full response text as string. This will only contain data if error is related to the response message, otherwise it's None. Usually it is a JSON (in string form) with API errors, if these specific errors are also causing non-2xx status codes.

!!! note "Numeric strings instead of int" Since requests are send as a JSON you can use strings for int arguments, as long as they are numeric strings, like 5, instead of five:

```python
from simplejustwatchapi import search

results = search("The Matrix", count="5")
# No exception is raised.
```

API errors

[JustWatchApiError][simplejustwatchapi.exceptions.JustWatchApiError]{data-preview} is raised when no HTTP-related errors occur, but the internal JSON response contain errors.

API errors can occur for invalid country code:

from simplejustwatchapi import search, JustWatchApiError

try:
    # Country code matches 2-letter pattern, but isn't a valid code for any country.
    results = search("The Matrix", country="xx")
except JustWatchApiError as e:
    # Print all error messages.
    error_messages = [error.get("message") for error in e.errors]
    print(",".join(error_messages))

It can occur for language codes not matching expected pattern:

from simplejustwatchapi import search, JustWatchApiError

try:
    # Language code "xx" also isn't valid for any languages, but since it matches the
    # pattern it would default to English.
    results = search("The Matrix", language="xxx")
except JustWatchApiError as e:
    # Print only error codes.
    # Codes are collected to a set, as the API will return an error for each place,
    # where language code is used, in all offers, descriptions, etc.
    error_codes = {error["extensions"]["code"] for error in e.errors}
    print(",".join(error_codes))

Using title, instead of ID in [details][simplejustwatchapi.justwatch.details] function:

from simplejustwatchapi import details, JustWatchError

try:
    # "details" expects an ID, not a title.
    results = details("The Matrix")
except JustWatchError as e:
    # JustWatchError will catch both API and HTTP exceptions.
    print(e.errors)

Too high operation complexity due to too large count:

from simplejustwatchapi import search, JustWatchApiError

try:
    results = search("The Matrix", count=500)
except JustWatchApiError as e:
    error_messages = [error.get("message") for error in e.errors]
    print(",".join(error_messages))

These are just examples of internal API errors, which cause [JustWatchApiError] [simplejustwatchapi.exceptions.JustWatchApiError] exception.


More complicated examples

Get popular titles for only specific providers

You can combine providers and popular functions:

from simplejustwatchapi import popular, providers

# Get all providers in the US.
all_providers = providers("US")

# Filter only required providers by name.
netflix_apple_only = [
    provider.short_name  # We only need the codes for filtering.
    for provider in all_providers
    if provider.name in ("Netflix", "Apple TV")  # Get providers we need.
]

# Use found codes for filtering.
filtered_popular = popular("US", providers=netflix_apple_only)

Get offers for each episode of a TV show based on title

You can combine search, seasons and episodes functions:

from simplejustwatchapi import episodes, search, seasons

title = "True Detective"

# Search for a title.
search_results = search(title)

# Look for a first match with the expected title.
first_match = next(
    result
    for result in search_results
    if result.title == title and result.object_type == "SHOW"
)

# Get all seasons.
all_seasons = seasons(first_match.entry_id)

# Create a dict with episode offers.
id_to_episodes_offers = {
    season.season_number: {
        episode.episode_number: episode.offers
        for episode in episodes(season.entry_id)
    }
    for season in all_seasons
}

Get offers for multiple countries for all seasons of a TV show

You can combine search, seasons and offers_for_countries functions:

from simplejustwatchapi import offers_for_countries, search, seasons

title = "Andor"

# Search for a title.
search_results = search(title)

# Look for a first match with the expected title.
first_match = next(
    result
    for result in search_results
    if result.title == title and result.object_type == "SHOW"
)

# Get all seasons.
all_seasons = seasons(first_match.entry_id)

# Get offers for each season for each country.
countries = {"US", "DE"}
season_offers = [
    offers_for_countries(season.entry_id, countries)
    for season in all_seasons
]

# Convert to a dict of country codes to list of offers.
season_offers_per_country = {
    country: [
        season[country]
        for season in season_offers
    ]
    for country in countries
}

Pagination through offset

When trying to get as much data as possible with search or popular functions and avoid issues with operation complexity you can use offset parameter to set up a basic pagination:

from simplejustwatchapi import popular

i = 0
page = 99
all_results = []
while results := popular(count=page, offset=i):
    i += page
    all_results.extend(results)
# len(all_results) == 1980

!!! note "Maximum number of responses" 1999 is the limit of number of entries you can get from the JustWatch API using this method. Check Maximum number of entries page for more details.

Additional filtering in search and popular

search and popular functions allow for additional filtering of returned entries.

Argument name Description
min_release_year Minimum release year.
max_release_year Maximum release year.
object_types Media types, like SHOW or MOVIE.

All filters are optional; when not configured (or set to None) the filtering is disabled.

object_types is a list of strings (or for one type just a single string), like SHOW, or MOVIE. You can check examples/ for field object_type, however the only "useful" ones seem to be SHOW and MOVIE. You can use types like SHOW_EPISODE, or SHOW_SEASON, however they seem to default to "TV shows" - same as for SHOW.

!!! warning "Type values are not enforced, but must be valid" Possible values for types are not enforced by functions in this API, but they still must be valid types in JustWatch API. Using unexpected type will result in HTTP error with code 422.

from simplejustwatchapi import popular, search

# Get only currently popular TV shows:
popular_shows = popular(object_types=["SHOW"])

# Search for movies between 1990 and 2010:
movies = search(
    "The Matrix",
    min_release_year=1990,
    max_release_year=2010,
    object_types="MOVIE"
)
# "object_types" with single type can be either a list, or just a string.