> ## Documentation Index
> Fetch the complete documentation index at: https://api.simkl.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Redirect & deep-linking

> Two jobs: link from anywhere into the right Simkl page (no API call), or resolve any external ID to a Simkl ID at the lowest possible cost.

`GET /redirect` is a passive helper that **`301`-redirects** to a Simkl URL given any combination of identifiers. It's designed for two distinct situations — pick the one that matches your job.

## Two use cases

<CardGroup cols={2}>
  <Card title="1. Link to Simkl without an API call" icon="link" href="#use-case-1-%E2%80%94-link-to-simkl-when-you-don%E2%80%99t-have-a-simkl-id">
    You have an external ID or a title and you just want to send the user to the matching Simkl page (or trailer / share / mark-watched action). No `client_id`, no JSON parsing.
  </Card>

  <Card title="2. Cheapest external ID → Simkl ID" icon="bolt" href="#use-case-2-%E2%80%94-resolve-an-external-id-to-a-simkl-id">
    You have an IMDB / TMDB / TVDB / MAL ID and need the **Simkl ID** so you can call `/movies/:id`, `/tv/:id`, or `/anime/:id`. `/redirect` is the lowest-overhead way to get there — read one header, no JSON parsing.
  </Card>
</CardGroup>

<Note>
  Always returns `301 Moved Permanently` with a `Location` header and `Cache-Control: no-store`. The `type=show` value matches both `tv` and `anime`. Like every Simkl endpoint, requests must include the [required URL parameters](/conventions/headers#required-url-parameters) (`client_id`, `app-name`, `app-version`) and a `User-Agent` header. No `Authorization` token is needed except for `to=watched`, which signs the user in if they aren't already.
</Note>

<Warning>
  **Do not follow the 301.** This applies to **HTTP clients, scrapers, server-side fetchers, automated tools, AI agents, and LLM-driven workflows alike** — the information you need is in the **`Location` response header**, never in the destination body. The destination is one of:

  * A human-facing simkl.com page (HTML),
  * A YouTube trailer page,
  * A `twitter.com/intent/tweet` URL,
  * A `/oauth/authorize` URL (for `to=watched` flows when the user isn't signed in).

  None of those contain API data. Fetching them wastes bandwidth, can break (CORS / auth / rate limits on the destination host), and gives you nothing useful. **The Simkl URL you want — and the `simkl_id` you can parse out of its path — is in the redirect target string, available without ever following the redirect.**

  Configure your HTTP client to stop at the 301 and read the header:

  | Tool / language   | How to stop at the 301                                                          |
  | ----------------- | ------------------------------------------------------------------------------- |
  | `curl`            | `curl -I <url>` (HEAD request) or `curl --max-redirs 0 -s -D - <url>`           |
  | Python `requests` | `requests.get(url, allow_redirects=False)` then `r.headers['location']`         |
  | Python `httpx`    | `httpx.get(url, follow_redirects=False)`                                        |
  | Node `fetch`      | `fetch(url, { redirect: 'manual' })` then `r.headers.get('location')`           |
  | Node `axios`      | `axios.get(url, { maxRedirects: 0, validateStatus: s => s === 301 })`           |
  | Go `net/http`     | Set `client.CheckRedirect = func(...) error { return http.ErrUseLastResponse }` |

  This is **the canonical way to use `/redirect`** — not a perf optimisation. Following the redirect defeats the endpoint's purpose.

  **What to do after reading the `Location` header — pick one:**

  * **You only need the Simkl ID.** Parse it out of the URL path and **stop here**. Don't call anything else. Example: `Location: https://simkl.com/tv/17465/game-of-thrones` → `simkl_id = 17465`. You're done.
  * **You also need the full record** (title, overview, poster, fanart, ratings, trailers, etc.). Use the parsed Simkl ID to call the matching detail endpoint, which is **Cloudflare-cached by Simkl ID** — popular titles come straight from edge cache and are near-free:
    * Movies → [`GET /movies/{simkl_id}`](/api-reference/simkl/get-movie)
    * TV shows → [`GET /tv/{simkl_id}`](/api-reference/simkl/get-tv-show)
    * Anime → [`GET /anime/{simkl_id}`](/api-reference/simkl/get-anime)
    * Episode lists → [`GET /tv/episodes/{simkl_id}`](/api-reference/simkl/get-tv-episodes) or [`GET /anime/episodes/{simkl_id}`](/api-reference/simkl/get-anime-episodes)

  Two HTTP requests max (one to `/redirect` for the ID, one to the cached detail endpoint for the data). Never follow the 301 from `/redirect` itself.
</Warning>

## Use case 1 — Link to Simkl when you don't have a Simkl ID

You're rendering a clickable link in a newsletter, a browser-extension menu, a "Share" button, or any external surface, and you'd rather not call the JSON API yourself. Hand `/redirect` whatever identifier you have on hand and it sends the user to the right place.

### Action modes (`to=`)

| Mode                | Redirects to                                                                                                                                                                      |
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `simkl` *(default)* | The Simkl page for the resolved item.                                                                                                                                             |
| `trailer`           | The trailer URL (typically YouTube).                                                                                                                                              |
| `twitter`           | A `twitter.com/intent/tweet` URL with the title and a Simkl link prefilled.                                                                                                       |
| `watched`           | Marks the item watched on the user's account. If the user isn't signed in, Simkl first redirects through `/oauth/authorize`, then performs the action and lands them on the page. |

### Recipes

<CodeGroup>
  ```bash IMDB → Simkl page theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -I "https://api.simkl.com/redirect?to=simkl&imdb=tt0944947&client_id=YOUR_CLIENT_ID&app-name=my-app-name&app-version=1.0" \
    -H "User-Agent: my-app-name/1.0"
  # 301 Location: https://simkl.com/tv/17465/game-of-thrones
  ```

  ```bash TMDB → Simkl page (movie) theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -I "https://api.simkl.com/redirect?to=simkl&type=movie&tmdb=27205&client_id=YOUR_CLIENT_ID&app-name=my-app-name&app-version=1.0" \
    -H "User-Agent: my-app-name/1.0"
  # 301 Location: https://simkl.com/movies/472214/inception
  ```

  \`\`\`bash TMDB → Simkl page (TV — `type` is required)
  curl -I "[https://api.simkl.com/redirect?to=simkl\&type=tv\&tmdb=1399\&client\_id=YOUR\_CLIENT\_ID\&app-name=my-app-name\&app-version=1.0](https://api.simkl.com/redirect?to=simkl\&type=tv\&tmdb=1399\&client_id=YOUR_CLIENT_ID\&app-name=my-app-name\&app-version=1.0)" \
  -H "User-Agent: my-app-name/1.0"

  # 301 Location: [https://simkl.com/tv/17465/game-of-thrones](https://simkl.com/tv/17465/game-of-thrones)

  ````

  ```bash TMDB → specific episode
  curl -I "https://api.simkl.com/redirect?to=simkl&type=tv&tmdb=1399&season=1&episode=3&client_id=YOUR_CLIENT_ID&app-name=my-app-name&app-version=1.0" \
    -H "User-Agent: my-app-name/1.0"
  # 301 Location: https://simkl.com/tv/17465/.../season-1/episode-3
  ````

  ```bash MAL → Simkl anime page theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -I "https://api.simkl.com/redirect?to=simkl&mal=11757&client_id=YOUR_CLIENT_ID&app-name=my-app-name&app-version=1.0" \
    -H "User-Agent: my-app-name/1.0"
  # 301 Location: https://simkl.com/anime/37226/sword-art-online
  ```

  ```bash Title + year → Simkl page theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -I "https://api.simkl.com/redirect?to=simkl&type=movie&title=Inception&year=2010&client_id=YOUR_CLIENT_ID&app-name=my-app-name&app-version=1.0" \
    -H "User-Agent: my-app-name/1.0"
  # 301 Location: https://simkl.com/movies/472214/inception
  ```

  ```bash Trailer theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -I "https://api.simkl.com/redirect?to=trailer&imdb=tt0944947&client_id=YOUR_CLIENT_ID&app-name=my-app-name&app-version=1.0" \
    -H "User-Agent: my-app-name/1.0"
  # 301 Location: https://www.youtube.com/watch?v=...
  ```

  ```bash Tweet a movie theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -I "https://api.simkl.com/redirect?to=twitter&type=movie&title=Inception&year=2010&client_id=YOUR_CLIENT_ID&app-name=my-app-name&app-version=1.0" \
    -H "User-Agent: my-app-name/1.0"
  # 301 Location: https://twitter.com/intent/tweet?text=...
  ```

  ```bash Mark as watched (signs the user in if needed) theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -I "https://api.simkl.com/redirect?to=watched&imdb=tt0944947&season=1&episode=3&client_id=YOUR_CLIENT_ID&app-name=my-app-name&app-version=1.0" \
    -H "User-Agent: my-app-name/1.0"
  # 301 Location: https://simkl.com/oauth/authorize?...   (returns to the action after login)
  ```
</CodeGroup>

### Building the Simkl URL yourself

If you already have the Simkl ID and slug (returned in `ids.simkl_id` and `ids.slug` on every standard media object), you don't need `/redirect` at all — assemble the URL directly:

| Resource      | URL pattern                                                                |        |           |
| ------------- | -------------------------------------------------------------------------- | ------ | --------- |
| Movie         | `https://simkl.com/movies/{simkl_id}/{slug}`                               |        |           |
| TV show       | `https://simkl.com/tv/{simkl_id}/{slug}`                                   |        |           |
| Anime         | `https://simkl.com/anime/{simkl_id}/{slug}`                                |        |           |
| TV season     | `https://simkl.com/tv/{simkl_id}/{slug}/season-{N}`                        |        |           |
| TV episode    | `https://simkl.com/tv/{simkl_id}/{slug}/season-{N}/episode-{M}`            |        |           |
| Anime episode | `https://simkl.com/anime/{simkl_id}/{slug}/episode-{M}`                    |        |           |
| User profile  | `https://simkl.com/{username}`                                             |        |           |
| User stats    | `https://simkl.com/{username}/stats/`                                      |        |           |
| User library  | \`[https://simkl.com/\{username}/\{tv](https://simkl.com/\{username}/\{tv) | movies | anime}/\` |

The `slug` is **technically optional, but always include it when you have it.** If you skip it, Simkl runs an extra title lookup and `301`-redirects to the slugged URL anyway — wasted server time on Simkl's side and an extra round-trip on yours. The `slug` is returned in `ids.slug` on every standard media object — store it alongside the Simkl ID and reuse.

***

## Use case 2 — Resolve an external ID to a Simkl ID

You have an external ID (IMDB, TMDB, TVDB, MAL, AniDB, AniList, Kitsu, etc.) and you need the **Simkl ID** so you can fetch the full record from `/movies/{id}`, `/tv/{id}`, or `/anime/{id}`. **This is the recommended path** — `/redirect` returns a tiny redirect with the Simkl ID baked into the URL, and the detail endpoints are aggressively cached on Cloudflare by Simkl ID.

### How `/redirect` resolves an ID

The response is a `301` with a `Location` header pointing at the canonical Simkl URL, e.g. `https://simkl.com/tv/17465/game-of-thrones`. Parse out `17465` and pass it to `/tv/17465` to get the full record from Cloudflare cache.

* **Tiny payload** — just HTTP headers, no JSON to parse.
* **Cached path** — the follow-up detail call (`/movies/{id}`, `/tv/{id}`, `/anime/{id}`) hits Cloudflare's edge cache, so it stays cheap for repeat lookups of the same title.
* **Same required params** as every Simkl endpoint — see [Headers and required parameters](/conventions/headers#required-url-parameters).

### How to extract the Simkl ID from the redirect

The `Location` header looks like one of:

```
https://simkl.com/movies/{simkl_id}/{slug}
https://simkl.com/tv/{simkl_id}/{slug}
https://simkl.com/anime/{simkl_id}/{slug}
```

The numeric segment immediately after `/movies/`, `/tv/`, or `/anime/` is the Simkl ID. Then call the summary endpoint of your choice with that ID.

### Recipes

<CodeGroup>
  ```bash IMDB → Simkl ID → /tv/:id theme={"theme":{"light":"github-light","dark":"vesper"}}
  PARAMS="client_id=YOUR_CLIENT_ID&app-name=my-app-name&app-version=1.0"
  UA="my-app-name/1.0"

  SIMKL_URL=$(curl -sI "https://api.simkl.com/redirect?to=simkl&imdb=tt0944947&$PARAMS" \
    -H "User-Agent: $UA" \
    | awk -v IGNORECASE=1 '/^location:/ {print $2}' | tr -d '\r\n')
  SIMKL_ID=$(echo "$SIMKL_URL" | awk -F/ '{print $5}')

  curl "https://api.simkl.com/tv/$SIMKL_ID?$PARAMS" \
    -H "User-Agent: $UA"
  ```

  ```js IMDB → Simkl ID → /movies/:id theme={"theme":{"light":"github-light","dark":"vesper"}}
  const PARAMS  = `client_id=${CLIENT_ID}&app-name=my-app-name&app-version=1.0`;
  const HEADERS = { 'User-Agent': 'my-app-name/1.0' };

  const loc = await fetch(
    `https://api.simkl.com/redirect?to=simkl&imdb=tt1375666&${PARAMS}`,
    { redirect: 'manual', headers: HEADERS }
  ).then(r => r.headers.get('location'));

  // loc === "https://simkl.com/movies/472214/inception"
  const simklId = loc.match(/\/(?:movies|tv|anime)\/(\d+)\//)[1];

  const movie = await fetch(
    `https://api.simkl.com/movies/${simklId}?${PARAMS}`,
    { headers: HEADERS }
  ).then(r => r.json());
  ```

  ```python MAL → Simkl ID → /anime/:id theme={"theme":{"light":"github-light","dark":"vesper"}}
  import re, requests

  PARAMS = {
      'client_id':   CLIENT_ID,
      'app-name':    'my-app-name',
      'app-version': '1.0',
  }
  HEADERS = {'User-Agent': 'my-app-name/1.0'}

  # 1. Resolve MAL ID to a Simkl URL — read the Location header, no JSON parse
  loc = requests.get(
      'https://api.simkl.com/redirect',
      params={**PARAMS, 'to': 'simkl', 'mal': 11757},
      headers=HEADERS,
      allow_redirects=False,
  ).headers['location']

  # 2. Extract the Simkl ID from the URL path
  simkl_id = int(re.search(r'/(?:movies|tv|anime)/(\d+)/', loc).group(1))

  # 3. Pull the full anime record (summary endpoints auto-include extended data)
  anime = requests.get(
      f'https://api.simkl.com/anime/{simkl_id}',
      params=PARAMS,
      headers=HEADERS,
  ).json()
  ```
</CodeGroup>

<Tip>
  **Cache the resolved Simkl ID.** External IDs map to Simkl IDs once and rarely change. Store the mapping locally so the next request goes straight to `/movies/{id}` / `/tv/{id}` / `/anime/{id}` without a round-trip through `/redirect`.
</Tip>

***

## What you can pass

`/redirect` accepts a wide set of identifiers — pass any combination, the more the better:

<CardGroup cols={2}>
  <Card title="External IDs" icon="hashtag">
    Any of the [supported ID keys](/conventions/standard-media-objects#supported-id-keys) — `simkl`, `imdb`, `tmdb` (pair with `type=movie` or `type=tv` — TMDB has no anime type), `tvdb`, `mal`, `anidb`, `crunchyroll`, etc. Most stand alone.
  </Card>

  <Card title="Title + year" icon="text-size">
    `title=...&year=...&type=...`. Title-based fallback for when you have nothing else.
  </Card>

  <Card title="Episode targeting" icon="list-ol">
    `season` (defaults to `1`) and `episode`. Setting either one excludes movies from the search.
  </Card>

  <Card title="Tweet text" icon="quote-left">
    `ep_title` is used when `to=twitter` to include the episode title in the tweet body.
  </Card>
</CardGroup>

## Endpoint reference

<CardGroup cols={1}>
  <Card title="GET /redirect" icon="arrow-right" href="/api-reference/simkl/redirect">
    Full parameter list, response codes, and an interactive playground.
  </Card>
</CardGroup>

## Related

<CardGroup cols={3}>
  <Card title="Standard media objects" icon="film" href="/conventions/standard-media-objects">
    Where the `ids.simkl_id` and `ids.slug` fields come from.
  </Card>

  <Card title="Detail endpoints" icon="film" href="/api-reference/movies">
    Once you have the Simkl ID, fetch the full record from `/movies/{id}`, `/tv/{id}`, or `/anime/{id}` (Cloudflare-cached by ID).
  </Card>

  <Card title="OAuth flow" icon="lock" href="/api-reference/oauth">
    `to=watched` first redirects through `/oauth/authorize` for unauthenticated users.
  </Card>
</CardGroup>
