cd /news/developer-tools/build-a-where-to-watch-feature-in-50… Β· home β€Ί topics β€Ί developer-tools β€Ί article
[ARTICLE Β· art-12030] src=dev.to β†— pub= topic=developer-tools verified=true sentiment=↑ positive

Build a "Where to Watch" feature in 50 lines with the StreamWatchHub API

The article introduces StreamWatchHub, a new API that consolidates streaming service and live football broadcaster data across 10 countries into a single REST endpoint with a consistent schema, available on RapidAPI with a free tier of 1,000 calls per month. It demonstrates how to build a production-ready "where to watch" feature using roughly 50 lines of Node.js code and a small React component, requiring only one API call per title to retrieve offers with monetization types. The API covers movies, series, and sports matches, and the team is evaluating additional features like a recommendation endpoint while seeking feedback on how to expose a confidence score.

read4 min views22 publishedMay 23, 2026

Most teams shipping a "where can I watch X?" feature run into the same set of problems:

  • JustWatch does not offer a public API.
  • TMDB watch-providers covers the major markets only, without rent prices or deep links.
  • Live sports availability requires a separate broadcaster feed.
  • Platform names, regional catalogs, and deep-link formats all need to be reconciled.

StreamWatchHub consolidates this into a single REST endpoint and one consistent schema, covering every streaming service plus live football broadcasters across 10 countries. The API is now live on RapidAPI with a free tier (1,000 calls/month), so it can be evaluated without a payment method.

This post walks through wiring a production-ready "where to watch" feature in roughly 50 lines of Node.js plus a small React component.

What the API returns #

A single call per title, with the monetization type flagged on every offer:

curl "https://streamwatchhub.p.rapidapi.com/v1/search?q=the+bear&country=US" \
  -H "X-RapidAPI-Key: $KEY" \
  -H "X-RapidAPI-Host: streamwatchhub.p.rapidapi.com"

Response (trimmed):

{
  "results": [{
    "tmdb_id": 136315,
    "title": "The Bear",
    "type": "series",
    "year": 2022,
    "offers": [
      { "platform": "hulu",     "type": "flatrate", "url": "https://hulu.com/series/..." },
      { "platform": "disney",   "type": "flatrate", "url": "https://disneyplus.com/..." },
      { "platform": "apple",    "type": "rent",     "price": "$2.99", "url": "https://tv.apple.com/..." }
    ]
  }]
}

No per-platform SDKs, no scraping fallbacks. The same response shape applies to movies, series, and football matches β€” sports responses substitute kickoff_at

and broadcasters[]

for offers[]

.

1. Sign up and obtain an API key #

  • Visit the RapidAPI listingand select the free plan. - Copy the issued RapidAPI key and export it: export RAPIDAPI_KEY=...

2. A minimal Node client #

// swh.js
const HOST = "streamwatchhub.p.rapidapi.com";
const BASE = `https://${HOST}/v1`;

export async function whereToWatch(query, country = "US") {
  const url = new URL(`${BASE}/search`);
  url.searchParams.set("q", query);
  url.searchParams.set("country", country);

  const res = await fetch(url, {
    headers: {
      "X-RapidAPI-Key":  process.env.RAPIDAPI_KEY,
      "X-RapidAPI-Host": HOST,
    },
  });
  if (!res.ok) throw new Error(`SWH ${res.status}`);
  return res.json();
}

No client library is required. The full surface is seven GET endpoints (/search

, /title/{id}/offers

, /series/{id}/season/{n}/offers

, /match/{id}/broadcasters

, /fixtures

, /platforms

, /changes

).

3. A drop-in React component #

import { useEffect, useState } from "react";
import { whereToWatch } from "./swh";

export function WhereToWatch({ title, country = "US" }) {
  const [data, setData] = useState(null);
  const [err,  setErr]  = useState(null);

  useEffect(() => {
    whereToWatch(title, country).then(setData).catch(setErr);
  }, [title, country]);

  if (err)        return <p>Couldn't load options.</p>;
  if (!data)      return <p>…</p>;
  const hit = data.results?.[0];
  if (!hit)       return <p>No streaming match in {country}.</p>;

  return (
    <div>
      <h3>{hit.title} <small>({hit.year})</small></h3>
      <ul>
        {hit.offers.map((o, i) => (
          <li key={i}>
            <a href={o.url} target="_blank" rel="noopener">
              <strong>{o.platform}</strong> β€” {o.type}
              {o.price && <> Β· {o.price}</>}
            </a>
          </li>
        ))}
      </ul>
    </div>
  );
}

Usage: <WhereToWatch title="The Bear" country="US" />

.

Current coverage #

14,000+ titles(movies and TV series), refreshed daily - 70+ providersβ€” Netflix, Disney+, HBO Max, Apple TV, OSN+, Shahid, Movistar Plus+, Kinopoisk, Now TV, Sky Go, Paramount+, and others - 10 countries at launch β€” US, GB, DE, ES, IT, FR, TR, BR, IN, SA (more being added) - Live footballβ€” 23 leagues including the Big Five plus UCL / UEL / UECL and the Saudi Pro League, with per-country broadcaster resolution (the same fixture airs on different channels in each market, and the API resolves the correct one) - Confidence scores on broadcaster matches so low-confidence entries can be filtered out client-side - Deep links that open the correct detail page on each platform

Roadmap #

  • A dedicated Sports RapidAPI listing is launching in the coming weeks; football fixtures are already accessible inside the current Movies & Series listing. - Additional countries are scheduled: Mexico, Argentina, Australia, Japan, and Korea.
  • A natural-language /recommend

endpoint is under evaluation ("where can I watch the Champions League final in Romania tonight?") β€” the team is still assessing whether it adds enough value beyond the structured endpoints.

Try it #

Feedback is welcome before the v1 schema is frozen. One open question for readers: how should confidence_score

be exposed β€” as a raw number, a low / medium / high

enum, or hidden entirely below a threshold? Comments are appreciated.

Thanks for reading.

── more in #developer-tools 4 stories Β· sorted by recency
── more on @streamwatchhub 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain β€” perfect for shipping the agent you just read about.

$git push zahid main
β†’ Live at https://your-agent.zahid.host βœ“
Get free account β†’ Pricing
from €0/mo Β· no card required
LIVE [news/build-a-where-to-wat…] indexed:0 read:4min 2026-05-23 Β· β€”