Looking for the overview — what this API returns, what it costs, and a call you can run without a key? See the Streaming Availability API page →
Media, Film & Knowledge

Streaming Availability API & Scraper

The Streaming Availability API returns where-to-watch data as clean JSON.

12 actionsLive JSON1,000 free credits$0.67–$1.50 / 1,000 creditsMCP-ready
Get a free keyOpen in playground

🤖 Using an AI assistant? Copy this link into ChatGPT / Claude / Cursor — it reads every endpoint and parameter instantly and tells you if this API fits your use case.

The primary search endpoint returns titles with offers (provider, type, quality, price, URL) and external ids, and you can browse, see trending, pull a title, check availability, list new titles and countries. It is built for streaming-guide apps and media tools that need cross-service availability without a scraper. One ReefAPI key, one shared credit pool, the standard envelope.

Reference

Provider codes the packages filter actually accepts

packages does not take the technical_name that the providers action returns. It takes JustWatch's short package codes, and an unrecognized code is silently ignored rather than rejected, so a wrong value looks like a working call over the entire catalog. Each code below was verified by browsing US movies and checking that every returned title carried an offer from that provider. The last column is the US movie count that code filtered down to.

packages codeProvider every result carriedUS movie catalog size
nfxNetflix, including Netflix Standard with Ads4,570
ampAmazon Prime Video, including Prime Video with Ads22,777
dnpDisney Plus1,405
hluHulu1,233
mxxHBO Max, including HBO Max Amazon Channel1,871
pmpParamount Plus Essential and Premium811
pctPeacock Premium and Premium Plus873
atpApple TV, the subscription service123
ituApple TV Store, the rent and buy storefront49,456
cruCrunchyroll252
any unrecognized codeno filter is applied at all162,472, the unfiltered total

packages filters which titles come back, not which offers hang off them. A browse restricted to nfx still returns each title's full offer list, Amazon and Apple TV Store rows included. The only way to confirm the filter took effect is to compare meta.total against the unfiltered 162,472.

Live example

Real request and response JSON

Captured from the indexed primary action, search, on .

Captured request
{
  "method": "POST",
  "url": "https://api.reefapi.com/streaming/v1/search",
  "headers": {
    "x-api-key": "$REEF_KEY",
    "content-type": "application/json"
  },
  "body": {
    "query": "Inception",
    "country": "US"
  }
}
Captured response
{
  "ok": true,
  "meta": {
    "api": "streaming",
    "endpoint": "search",
    "mode": "live",
    "latency_ms": 745.6,
    "record_count": 4,
    "bytes": 16394,
    "cache_hit": false,
    "total": 4,
    "has_more": false,
    "next_cursor": "NA=="
  },
  "data": {
    "results": [
      {
        "id": "tm92641",
        "object_id": 92641,
        "object_type": "MOVIE",
        "title": "Inception",
        "year": 2010,
        "release_date": null,
        "path": "/us/movie/inception",
        "description": "A thief who steals corporate secrets through the use of dream-sharing technology is given the inverse task of planting an idea into the mind of a CEO, but his tragic past may doom the project and his team to disaster.",
        "poster_url": "/poster/[redacted-phone]/{profile}/inception.{format}",
        "runtime": 148,
        "age_certification": "TV-14",
        "season_number": null,
        "episode_number": null,
        "genres": [
          "act",
          "trl",
          "scf"
        ],
        "external_ids": {
          "imdb": "tt1375666",
          "tmdb": "27205"
        },
        "scoring": {
          "imdb_score": 8.8,
          "imdb_votes": 2827843,
          "tmdb_popularity": 44.1872,
          "tmdb_score": null,
          "tomato_meter": null,
          "jw_rating": null
        },
        "offers": [
          {
            "provider": "[trimmed-depth]",
            "provider_id": "[trimmed-depth]",
            "provider_technical_name": "[trimmed-depth]",
            "type": "[trimmed-depth]",
            "quality": "[trimmed-depth]",
            "price": "[trimmed-depth]",
            "price_value": "[trimmed-depth]",
            "currency": "[trimmed-depth]",
            "url": "[trimmed-depth]",
            "element_count": "[trimmed-depth]",
            "available_to": "[trimmed-depth]",
            "icon": "[trimmed-depth]"
          },
          {
            "provider": "[trimmed-depth]",
            "provider_id": "[trimmed-depth]",
            "provider_technical_name": "[trimmed-depth]",
            "type": "[trimmed-depth]",
            "quality": "[trimmed-depth]",
            "price": "[trimmed-depth]",
            "price_value": "[trimmed-depth]",
            "currency": "[trimmed-depth]",
            "url": "[trimmed-depth]",
            "element_count": "[trimmed-depth]",
            "available_to": "[trimmed-depth]",
            "icon": "[trimmed-depth]"
          },
          {
            "provider": "[trimmed-depth]",
            "provider_id": "[trimmed-depth]",
            "provider_technical_name": "[trimmed-depth]",
            "type": "[trimmed-depth]",
            "quality": "[trimmed-depth]",
            "price": "[trimmed-depth]",
            "price_value": "[trimmed-depth]",
            "currency": "[trimmed-depth]",
            "url": "[trimmed-depth]",
            "element_count": "[trimmed-depth]",
            "available_to": "[trimmed-depth]",
            "icon": "[trimmed-depth]"
          }
        ],
        "total_season_count": null,
        "total_episode_count": null,
        "cursor": "MQ=="
      },
      {
        "id": "tm818540",
        "object_id": 818540,
        "object_type": "MOVIE",
        "title": "The Crack: Inception",
        "year": 2019,
        "release_date": null,
        "path": "/us/movie/the-crack-inception",
        "description": "Madrid, Spain, 1975; shortly after the end of the Franco dictatorship. Six months after the mysterious death of his lover, a prestigious tailor, a married woman visits the office of the young Germán Areta, a former police officer turned private detective, to request his professional services.",
        "poster_url": "/poster/[redacted-phone]/{profile}/the-crack-inception.{format}",
        "runtime": 117,
        "age_certification": "PG-13",
        "season_number": null,
        "episode_number": null,
        "genres": [
          "crm",
          "drm",
          "trl"
        ],
        "external_ids": {
          "imdb": "tt6793710",
          "tmdb": "613092"
        },
        "scoring": {
          "imdb_score": 6.6,
          "imdb_votes": 985,
          "tmdb_popularity": 1.4716,
          "tmdb_score": null,
          "tomato_meter": null,
          "jw_rating": null
        },
        "offers": [
          {
            "provider": "[trimmed-depth]",
            "provider_id": "[trimmed-depth]",
            "provider_technical_name": "[trimmed-depth]",
            "type": "[trimmed-depth]",
            "quality": "[trimmed-depth]",
            "price": "[trimmed-depth]",
            "price_value": "[trimmed-depth]",
            "currency": "[trimmed-depth]",
            "url": "[trimmed-depth]",
            "element_count": "[trimmed-depth]",
            "available_to": "[trimmed-depth]",
            "icon": "[trimmed-depth]"
          }
        ],
        "total_season_count": null,
        "total_episode_count": null,
        "cursor": "Mg=="
      },
      {
        "id": "tm429177",
        "object_id": 429177,
        "object_type": "MOVIE",
        "title": "Bikini Inception",
        "year": 2015,
        "release_date": null,
        "path": "/us/movie/bikini-inception",
        "description": "Two flunky Janitors in an Arctic Lab perform unauthorized experiments transporting them to a beach dream world in Malibu California w/50 beautiful young girls and a female Brazilian PhD Student wearing only a bra and panties. A '67 Muscle car races chases horses guns fights surfing, sumo wrestler, wolf monster, underwater scenes tons of gorgeous models. Sexy sci-fi fun.",
        "poster_url": "/poster/[redacted-phone]/{profile}/bikini-inception.{format}",
        "runtime": 106,
        "age_certification": "",
        "season_number": null,
        "episode_number": null,
        "genres": [
          "cmy"
        ],
        "external_ids": {
          "imdb": "tt8269586",
          "tmdb": "542438"
        },
        "scoring": {
          "imdb_score": 4.4,
          "imdb_votes": 29,
          "tmdb_popularity": 0.7654,
          "tmdb_score": null,
          "tomato_meter": null,
          "jw_rating": null
        },
        "offers": [
          {
            "provider": "[trimmed-depth]",
            "provider_id": "[trimmed-depth]",
            "provider_technical_name": "[trimmed-depth]",
            "type": "[trimmed-depth]",
            "quality": "[trimmed-depth]",
            "price": "[trimmed-depth]",
            "price_value": "[trimmed-depth]",
            "currency": "[trimmed-depth]",
            "url": "[trimmed-depth]",
            "element_count": "[trimmed-depth]",
            "available_to": "[trimmed-depth]",
            "icon": "[trimmed-depth]"
          },
          {
            "provider": "[trimmed-depth]",
            "provider_id": "[trimmed-depth]",
            "provider_technical_name": "[trimmed-depth]",
            "type": "[trimmed-depth]",
            "quality": "[trimmed-depth]",
            "price": "[trimmed-depth]",
            "price_value": "[trimmed-depth]",
            "currency": "[trimmed-depth]",
            "url": "[trimmed-depth]",
            "element_count": "[trimmed-depth]",
            "available_to": "[trimmed-depth]",
            "icon": "[trimmed-depth]"
          },
          {
            "provider": "[trimmed-depth]",
            "provider_id": "[trimmed-depth]",
            "provider_technical_name": "[trimmed-depth]",
            "type": "[trimmed-depth]",
            "quality": "[trimmed-depth]",
            "price": "[trimmed-depth]",
            "price_value": "[trimmed-depth]",
            "currency": "[trimmed-depth]",
            "url": "[trimmed-depth]",
            "element_count": "[trimmed-depth]",
            "available_to": "[trimmed-depth]",
            "icon": "[trimmed-depth]"
          }
        ],
        "total_season_count": null,
        "total_episode_count": null,
        "cursor": "Mw=="
      }
    ]
  }
}
Actions

What the Streaming Availability API does

ActionDescriptionConcrete use caseKey params
searchsearch movies/shows with current offersContent platforms call search to search movies/shows with current offers.query, country, language, page_size, cursor
browsebrowse a provider/country catalog by genre/type/year, ranked (sort_by), with paginationResearch tools call browse to get browse a provider/country catalog by genre/type/year, ranked (sort_by), with pagination.country, language, object_types, packages, genres, ...
trendingtrending titles right now (with where-to-watch offers), filterable by provider/type/genreCommunity analysts call trending to get trending titles right now (with where-to-watch offers), filterable by provider/type/genre.country, language, sort_by, object_types, packages, ...
titletitle metadata and offers by JustWatch node idMedia monitors call title to get title metadata and offers by JustWatch node id.id, query, url, country, language
availabilitywhere-to-watch offers for one title across multiple countries (the core comparison call)Content platforms call availability to get where-to-watch offers for one title across multiple countries (the core comparison call).id, query, url, countries, country, ...
newwhat's new / coming soon / leaving soon on a provider — by country/provider/typeResearch tools call new to get what's new / coming soon / leaving soon on a provider.country, language, packages, object_types, date, ...
countriessupported country codesCommunity analysts call countries to get supported country codes.none
genresJustWatch genre reference for a country/languageMedia monitors call genres to get justWatch genre reference for a country/language.country, language
providersstreaming providers available in a countryContent platforms call providers to get streaming providers available in a country.country
countryone country plus live supported provider/service detailsResearch tools call country to get one country plus live supported provider/service details.country
seasonsshow seasons with offersCommunity analysts call seasons to get show seasons with offers.id, country, language
episodesseason episodes with offers; show id + season_number resolves firstMedia monitors call episodes to get season episodes with offers; show id + season_number resolves first.id, season_id, season_number, country, language, ...
Code samples

Call search from your stack

curl -X POST https://api.reefapi.com/streaming/v1/search \
  -H "x-api-key: $REEF_KEY" \
  -H "content-type: application/json" \
  -d '{"query":"Inception","country":"US"}'
MCP one-liner
Ask your MCP-connected assistant: call reefapi.streaming.search with {"query":"Inception","country":"US"}.
Use cases

Who uses this API and why

  • Streaming-guide apps call search and availability to show where a title streams.
  • Media apps use new and trending to surface what just landed on services.
  • Regional tools use countries to localize availability for a user.
FAQ

Questions developers ask before integrating

Why does packages with the value netflix return the whole catalog?

Because netflix is the technical_name from the providers action, not a packages code, and unrecognized package values are dropped instead of rejected. Measured side by side on US movies: packages nfx reported meta.total 4,570 and every row carried a Netflix offer, while packages netflix reported 162,472 and the first rows were Peacock and Amazon rentals. Both returned ok true. Compare meta.total against the unfiltered count before trusting a filtered feed.

Why is price null on a Netflix offer but a real number on a rental?

Subscription offers have no per-title price, so type FLATRATE comes back with price null and price_value null while currency is still filled in from the market. Rent and buy offers carry both: a measured RENT offer in the US returned price $3.99 and price_value 3.99, and the same film in Turkey returned price TRY 24.99 and price_value 24.99. Use price_value for arithmetic and price only for display, since its formatting follows the market.

Which countries are covered, and does the provider list change between them?

The countries action returns 147 ISO-2 markets and reports its source as a static market reference, so treat it as the list of markets you may ask for rather than a live health check. Mainland China is not in it. Provider coverage varies sharply by market: the providers action returned 347 entries for US and 72 for TR. Ask providers per country instead of assuming a service exists there.

Why does Prime Video have two different technical names?

JustWatch registers a service per market, so the same brand can carry a different id and technical_name in each. Prime Video came back as technical_name amazonprime with provider_id 9 in the US, and as amazonprimevideo with provider_id 119 in Turkey. Match offers on the human-readable provider field or on a per-country id map, never on a technical_name you hardcoded from one market.

What is a node id, and where do I get one?

Every JustWatch object has a prefixed node id: tm for a movie, ts for a show, tse for a season. Breaking Bad is ts4 and Inception is tm92641. Search and browse rows return it as id, with the numeric part repeated as object_id. title, availability, seasons and episodes all take it directly, which skips the resolve-by-name step and removes the risk of matching the wrong title.

Why do results from the new action have null ids and no offers?

new is a change feed, not a metadata feed. A measured leaving-soon call on Netflix US returned rows where external_ids.imdb, external_ids.tmdb, every scoring field, runtime and age_certification were all null and offers was an empty list. The only populated block is new_offer, which carries the provider, the type, available_to and date_created. Take the node id from the row and call title if you need the rest.

How current is availability, and what does available_to mean?

Offers are fetched at call time, so what you get is the state right then and there is no as-of timestamp in the response. available_to is the forward-looking part: the date an offer is scheduled to expire, null when no end has been announced. Measured examples: an HBO Max Amazon Channel offer in GB carried available_to 2026-12-31, and a Netflix US title on the leaving feed carried available_to 2026-08-31 with date_created 2026-08-03, the day that offer first appeared.

Do title fields change with the country I ask for?

Some do. Requesting ts4 with country GB returned path /uk/tv-series/breaking-bad and age_certification 18, while the US call returned the US path and TV-MA. Age ratings are per-market strings with no shared scale, and an empty string turns up where a title is unrated, so test for both the empty string and null. Title, year, runtime and the imdb and tmdb external ids stay the same across markets.

What is the Streaming Availability API?

Streaming Availability API is a ReefAPI endpoint group for streaming availability It returns live JSON through POST requests under /streaming/v1.

Is the Streaming Availability API free to try?

Yes. ReefAPI starts with 1,000 free credits, no card required. Streaming Availability calls use the same shared credit balance as every other ReefAPI engine.

Do I need a Streaming Availability login or account?

No login to Streaming Availability is needed for the API response. You call ReefAPI with your x-api-key header, and the playground can run live examples before you create a production key.

How fresh is the Streaming Availability data?

The page example is captured from a live search call, and production requests fetch live data through ReefAPI rather than a static sample.

How many credits does the Streaming Availability API use?

Streaming Availability actions currently cost 1-2 credits per successful call. Failed or blocked calls are free, and all APIs draw from one credit pool.

Can I call Streaming Availability from an AI assistant or MCP client?

Yes. Connect ReefAPI once through MCP and your assistant can call streaming actions with the same key, credit pool and JSON envelope used by normal REST requests.

docs / streaming

Streaming Availability

Streaming Availability

base /streaming/v112 endpoints
post/streaming/v1/browse1 credit

browse a provider/country catalog by genre/type/year, ranked (sort_by), with pagination

ParameterAllowed / rangeDescription
country = USoptionalMarket — ISO-3166-1 alpha-2 (upper-cased; ~135 supported, see the countries action). Controls which offers/providers are returned.
language = enoptionalISO-639-1 language for titles/genre names (lower-cased).
object_typesoptionalmovie · show · tvRestrict to these title types (movie / show; 'tv' is accepted). Comma-list or array.
packagesoptionalRestrict to these providers by JustWatch technical name (e.g. nfx=Netflix, amp=Prime Video) — see the providers action.
genresoptionalRestrict to these genre short-names (e.g. act, drm) — see the genres action. Comma-list or array.
sort_by = popularoptionalpopular · trending · imdb_score · tmdb_popularity · alphabetical · randomRanking for the result list. Case-insensitive; common values shown.
release_yearoptionalAdvanced: release-year range as {min, max} (overrides year_min/year_max).
year_minoptionalEarliest release year (inclusive).
year_maxoptionalLatest release year (inclusive).
page_size = 20optional1–40Results per page (1-40). Larger values are clamped.
cursoroptionalNext-page token from the previous response's meta.next_cursor (for episodes it is a numeric offset).
Try in playground →
post/streaming/v1/title1 credit

title metadata and offers by JustWatch node id

ParameterAllowed / rangeDescription
idoptionalJustWatch node id (movie tm…, show ts…, season tse…). Get it from a search/browse result's `id`.
queryoptionalResolve the title by name when you have no node id (first match is used).
urloptionalResolve from a JustWatch URL when you have no id/query.
country = USoptionalMarket — ISO-3166-1 alpha-2 (upper-cased; ~135 supported, see the countries action). Controls which offers/providers are returned.
language = enoptionalISO-639-1 language for titles/genre names (lower-cased).
Try in playground →
post/streaming/v1/availability2 credits

where-to-watch offers for one title across multiple countries (the core comparison call)

ParameterAllowed / rangeDescription
idoptionalJustWatch node id (movie tm…, show ts…, season tse…). Get it from a search/browse result's `id`.
queryoptionalResolve the title by name when you have no node id (first match is used).
urloptionalResolve from a JustWatch URL when you have no id.
countriesoptionalMarkets to check (comma-list or array of ISO-2 codes). Defaults to the single `country`.
country = USoptionalMarket — ISO-3166-1 alpha-2 (upper-cased; ~135 supported, see the countries action). Controls which offers/providers are returned.
language = enoptionalISO-639-1 language for titles/genre names (lower-cased).
monetization_typesoptionalflatrate · rent · buy · ads · free · cinemaFilter offers by how you pay. Common values shown; case-insensitive.
presentation_typesoptionalsd · hd · 4kFilter offers by video quality. Common values shown; case-insensitive.
Try in playground →
post/streaming/v1/new1 credit

what's new / coming soon / leaving soon on a provider — by country/provider/type

ParameterAllowed / rangeDescription
country = USoptionalMarket — ISO-3166-1 alpha-2 (upper-cased; ~135 supported, see the countries action). Controls which offers/providers are returned.
language = enoptionalISO-639-1 language for titles/genre names (lower-cased).
packagesoptionalRestrict to these providers by JustWatch technical name (e.g. nfx=Netflix, amp=Prime Video) — see the providers action.
object_typesoptionalmovie · show · tvRestrict to these title types (movie / show; 'tv' is accepted). Comma-list or array.
dateoptionalThe change day as YYYY-MM-DD (defaults to today).
price_drops = falseoptionalReturn price-drop changes instead of newly-added titles.
page_type = newoptionalnew · upcoming · leavingWhich change feed. Case-insensitive; 'leaving' returns titles about to expire (with availableTo dates).
monetization_typesoptionalflatrate · rent · buy · ads · free · cinemaFilter offers by how you pay. Common values shown; case-insensitive.
presentation_typesoptionalsd · hd · 4kFilter offers by video quality. Common values shown; case-insensitive.
page_size = 20optional1–40Results per page (1-40). Larger values are clamped.
cursoroptionalNext-page token from the previous response's meta.next_cursor (for episodes it is a numeric offset).
Try in playground →
post/streaming/v1/countriesfree

supported country codes

Try in playground →
post/streaming/v1/genresfree

JustWatch genre reference for a country/language

ParameterAllowed / rangeDescription
country = USoptionalMarket — ISO-3166-1 alpha-2 (upper-cased; ~135 supported, see the countries action). Controls which offers/providers are returned.
language = enoptionalISO-639-1 language for titles/genre names (lower-cased).
Try in playground →
post/streaming/v1/providersfree

streaming providers available in a country

ParameterAllowed / rangeDescription
country = USoptionalMarket — ISO-3166-1 alpha-2 (upper-cased; ~135 supported, see the countries action). Controls which offers/providers are returned.
Try in playground →
post/streaming/v1/countryfree

one country plus live supported provider/service details

ParameterAllowed / rangeDescription
countryrequiredMarket — ISO-3166-1 alpha-2 (upper-cased; ~135 supported, see the countries action). Controls which offers/providers are returned.
Try in playground →
post/streaming/v1/seasons1 credit

show seasons with offers

ParameterAllowed / rangeDescription
idrequiredJustWatch node id (movie tm…, show ts…, season tse…). Get it from a search/browse result's `id`.
country = USoptionalMarket — ISO-3166-1 alpha-2 (upper-cased; ~135 supported, see the countries action). Controls which offers/providers are returned.
language = enoptionalISO-639-1 language for titles/genre names (lower-cased).
Try in playground →
post/streaming/v1/episodes1 credit

season episodes with offers; show id + season_number resolves first

ParameterAllowed / rangeDescription
idoptionalJustWatch node id (movie tm…, show ts…, season tse…). Get it from a search/browse result's `id`.
season_idoptionalSeason node id (tse…) — fetches that season's episodes directly.
season_numberoptionalWith a show `id`, resolves this season number to its episodes.
country = USoptionalMarket — ISO-3166-1 alpha-2 (upper-cased; ~135 supported, see the countries action). Controls which offers/providers are returned.
language = enoptionalISO-639-1 language for titles/genre names (lower-cased).
page_size = 20optional1–40Results per page (1-40). Larger values are clamped.
cursoroptionalNext-page token from the previous response's meta.next_cursor (for episodes it is a numeric offset).
Try in playground →