DEV Community

Cover image for Build a "Where to Watch" feature in 50 lines with the StreamWatchHub API
kavela
kavela

Posted on • Originally published at streamwatchhub.com

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

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"
Enter fullscreen mode Exit fullscreen mode

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/..." }
    ]
  }]
}
Enter fullscreen mode Exit fullscreen mode

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

  1. Visit the RapidAPI listing and select the free plan.
  2. 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();
}
Enter fullscreen mode Exit fullscreen mode

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>Loading…</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>
  );
}
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (0)