Skip to main content

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.

Help us keep the Simkl API at 100% uptime — optimise your app’s requests

The limits below are generous and most apps never hit them. The ones that do are almost always parallelizing calls to endpoints that should be sequential, or polling /sync/all-items without gating behind /sync/activities. The patterns on this page keep your app fast and keep the API healthy for every other developer building on Simkl.
These are the rules of the road for using the Simkl API. They’re short, they’re real, and they exist for good reasons. Read once, agree, and ship. By using the Simkl API, you also agree to the full Simkl Terms.
Don’t get your client_id suspended. The Simkl API caps every app at 10 GET/sec and 1 POST/sec per client_id and per user token — generous, and most apps never hit them. The ones that do are almost always either parallelizing calls to uncached endpoints, or polling GET /sync/all-items on a timer without first checking GET /sync/activities for changes. Apps that sustain overage get their client_id suspended without warning, no appeal — we see the traffic pattern and turn the key off.See Rate limits for the full caps, when parallel requests are allowed (only on Cloudflare-cached endpoints), and the sequential-by-default pattern. The two-phase sync model in Rule 7 → Sync incrementally shows the correct loop in code.
Wherever Simkl data appears in your app, link back to the Simkl page for that specific item — not just a generic homepage link. Better for users (they can dive into ratings, episodes, related titles, reviews), better for Simkl, and trivial to implement.
https://simkl.com/movies/:simkl_id/:slugexample
Both ids.simkl and ids.slug are returned on every standard media object, so the slug is free — you already have it in the response you just parsed.
Always include the slug when you have it. It’s technically optional — bare numeric URLs like simkl.com/movies/53536 still work — but Simkl has to run a database lookup and 301-redirect to the slugged URL, costing your user an extra round-trip and Simkl an extra search query. The slug is right there in ids.slug; pass it through and everyone wins.
The simkl ID is the only stable identifier — slugs are not unique. Multiple titles can share the same slug (e.g. three different Superman movies live at /movies/2059585/superman, /movies/260740/superman, /movies/951252/superman). Always build links with the numeric ID first; the slug is purely a human-readable URL hint. Never key your cache or do a lookup by slug alone.
build-simkl-url.js
function simklUrl(item) {
  const section = { movie: 'movies', anime: 'anime' }[item.type] || 'tv';
  return 'https://simkl.com/' + section + '/' +
    (item.ids.simkl || item.ids.simkl_id) + '/' +
    (item.ids.slug || '');
}

simklUrl(movieDetails);   // → https://simkl.com/movies/1306562/project-hail-mary
simklUrl(tvDetails);      // → https://simkl.com/tv/967226/the-boys
simklUrl(animeDetails);   // → https://simkl.com/anime/1885096/tongari-boushi-no-atelier

// No slug? URL ends with /:
simklUrl({ type: 'movie', ids: { simkl: 53536 } });
// → https://simkl.com/movies/53536/
Notes on the moving parts:
  • TV detail responses set item.type = "show" even though the URL section is /tv/. The map deliberately only lists movie and anime; anything else (including "show" and the empty type returned by /search/* and /{movies|tv|anime}/trending) falls through to /tv/ — Simkl will 301 to the correct section if needed, but you should set item.type yourself when you already know it (e.g. on /movies/trending results) to skip that hop.
  • The id key is either ids.simkl (detail endpoints, /sync/* responses, request bodies) or ids.simkl_id (/search/*, /trending, /calendar, /genres, /best, /premieres, episode-level detail). The same integer; the key name differs by endpoint family — simkl || simkl_id covers both. See Standard media objects → Supported ID keys.
Don’t have a Simkl ID yet? If all you have is an external ID — IMDB, TMDB, TVDB, MAL, AniDB, etc. — drop a /redirect URL straight into your <a href>. No request, no parsing, no JSON — the browser follows the 301 for you and the user lands on the canonical Simkl page.
<a href="https://api.simkl.com/redirect?to=simkl&imdb=tt0944947&client_id=YOUR_CLIENT_ID&app-name=my-app-name&app-version=1.0">
  View on Simkl
</a>
Click to try it → lands on https://simkl.com/tv/17465/game-of-thrones.
  • A simkl.com link buried in your privacy policy with no visible UI attribution.
  • An unbranded <a href="https://simkl.com">More info</a> that doesn’t say “Simkl”.
  • Fetching Simkl data into your own database and dropping the link entirely.
These are just illustrative samples — not visual requirements. Match the colours, shape, type, and density to your own design system. The only attribution rules are the substantive ones above: Simkl is named, the brand mark is visible, and the link goes to the per-item page with the slug.
Two brand-mark assets are available — the colored PNG for full-colour brand badges and the monochrome SVG (transparent “S” cutout) for icons that recolour with their parent via CSS filter:
AssetURL
Colored PNGhttps://us.simkl.in/img_favicon/v2/favicon-192x192.png
Monochrome SVGhttps://us.simkl.in/img_favicon/v2/safari-pinned-tab.svg
<a href="https://simkl.com/movies/53536/terminator-3-rise-of-the-machines"
   style="display: inline-flex; align-items: center; gap: 8px; padding: 6px 12px; border: 1px solid currentColor; border-radius: 999px; text-decoration: none; color: inherit;">
  <img src="https://us.simkl.in/img_favicon/v2/favicon-192x192.png" width="18" height="18" alt="Simkl" style="border-radius: 3px;">
  <span style="color: #FBBF24;"></span>
  <span style="font-weight: 700;">7.8</span>
</a>
Not sure how to implement this for your specific app? DM us on Discord or visit support.simkl.com — we’ll help you find the right placement.

2. Tracker apps must offer Simkl sync

If your app or service is a Movie / TV / Anime / Manga tracker that already syncs with another tracker, you may use the Simkl API only if you also offer Simkl login and sync alongside. In other words: the catalog and discovery endpoints are not a free metadata source for a competing tracker that doesn’t integrate Simkl. If you’re integrating Simkl as one of multiple supported services in a media app, you’re good. If you’re using Simkl’s catalog without offering Simkl sync, contact us first.

3. Use TVDB / TMDB for raw metadata

If you need a generic metadata host, please use TVDB and TMDB APIs from their original sources. Simkl is built for tracking and discovery, not as a CDN for the world’s metadata.

4. Keep your client_secret secret

client_secret is a credential — treat it like a password. Never commit it to a public repo, and never embed it in code that ships to a user’s device (mobile apps, single-page apps, browser extensions, desktop binaries). On a server, store it in an environment variable; in CI, store it as an encrypted secret — every CI provider supports this natively. A leaked secret lets anyone authenticate as your app, eats into your rate-limit quota, and forces you to rotate from your app settings and re-auth every user.client_id is not a secret — it’s a public identifier that appears in every API URL and is fine to include in client-side code. The thing to protect is client_secret.
For client-side apps that can’t keep a secret, pick the flow that matches your platform — both work without client_secret:
  • Mobile, single-page app, browser extension, desktop binary — use Public PKCE. Same browser-based UX as the standard OAuth flow, with a one-time code_verifier instead of a shipped secret.
  • TV, console, smartwatch, CLI tool, media-server plugin — use the PIN flow. Show a 5-character code, the user enters it on their phone.

5. Free for non-commercial use, and under $150 / month

The Simkl API is free for:
  • Non-commercial apps and personal projects.
  • Commercial apps and services that generate less than $150 / month in revenue.
If your app generates $150 / month or more, you must obtain a commercial license before continuing to use the API. Reach out via Discord to discuss terms.
Running the API at scale costs us real money in DNS, routing, health checks, CDN, server hosting, failover, and ops. Commercial fees cover those costs proportional to your usage.
If you display Trending data, you must use a section title that names Simkl — for example, Simkl Trending Today, Trending on Simkl This Week, Simkl Trending Movies. Full rules and examples on the Trending page.

7. Be a good API citizen

These are the habits well-built apps share. They keep your app fast, keep your users happy, and keep your traffic well clear of the rate-limit and overage patterns that trip the suspension warning at the top of this page.
Most metadata never changes. Cache by URL on the device — minutes for user data, hours for catalogs, forever for images.
The Trending and Calendar JSON files don’t count against your client_id quota and are cached at the edge. Always prefer them over per-user catalog calls.
Never call watchlist endpoints without first checking /sync/activities. And never run unconditional background polling timers without active user interaction.Use a two-phase pattern:
  1. Initial sync (one time per user) — pull the full library, no date_from on this pass.
    • Multi-type apps: call /sync/all-items/shows, /sync/all-items/movies, /sync/all-items/anime sequentially (not in parallel — back-to-back massive payloads spike your CPU and ours).
    • Single-type apps (anime-only, movie-only, TV-only): call only the one type you care about.
  2. Continuous sync (every poll after that) — call /sync/activities first; if every timestamp matches what you stored locally, skip. Otherwise:
    • Multi-type apps: /sync/all-items?date_from=YOUR_SAVED_TIMESTAMP — pulls deltas across all types and statuses in one response.
    • Single-type apps: /sync/all-items/{your_type}?date_from=YOUR_SAVED_TIMESTAMP — same delta semantics, scoped to one type so you don’t transfer data you’ll discard.
    Save the new activities.all timestamp for next time.
Triggers — sync on user-visible events, not timers:
  • Mobile / TV apps — app start, wake-from-background, pull-to-refresh. Throttle to once per 15–30 min.
  • Media servers (Plex, Kodi, Jellyfin) — library-scan-completed events, or when a playback session ends.
Full walkthrough with code: Sync guide.
POST /sync/history, POST /sync/history/remove, POST /sync/ratings, and POST /sync/add-to-list all accept arrays. Send 50 items in one call, not 50 calls.
Identify your app: myapp/1.0. It helps us tell legitimate clients apart from bad actors and keeps you out of any accidental blocks.
On 429, 500, 502, 503: wait, retry, double the wait, cap at 60s, give up after 5 attempts. See Errors.

More

Rate limits

The full set of limit signals and how to handle them.

Errors

Every status code Simkl returns and what to do about it.

Get help

Discord, email, GitHub — pick your favorite.