Providers
How Kunai chooses among third-party adapters, retries, recovers, and falls back when one fails, plus the live status table for every registered provider.
Kunai resolves playable streams through direct HTTP provider adapters. You pick a title; Kunai asks registered providers for stream inventory; playback goes to mpv.
This page explains user-visible provider behavior. It does not document scraper internals, crypto constants, or site-specific extraction logic.
Third-party providers
/recover, then /fallback (or Shift+F during playback), then /diagnostics; each command maps to a distinct recovery strategy.Active providers
Live registry synced from the CLI when docs are generated. Click a provider name to jump to its notes below.
| Provider | Domain | Media | Status | Description |
|---|---|---|---|---|
| Videasy videasy | videasy.to | movie, series | Active | Registered movies/series adapter; source and subtitle inventory vary by title |
| VidLink vidlink | vidlink.pro | movie, series | Active | Movies and series with multi-language subtitles |
| VidRock vidrock | vidrock.net | movie, series | Active | Backup source for movies and series with direct video files |
| Rivestream rivestream | rivestream.app | movie, series | Candidate | Candidate movies/series adapter; quality varies by title |
| Movy movy | movy.sx | movie, series | Candidate | Movies and series via a multi-lane source aggregator |
| AniDB anidb | anidb.app | anime | Active | anidb.app catalog and streams — ani-cli v5's source; second in the default anime order |
| AllManga allanime | mkissa.to | anime | Active | Anime episodes in sub and dub — the ani-cli parity source, third in the default order |
| HiAnime hianime | hianime.at | anime | Production | Anime episodes in sub and dub via HiAnime (ani-cli parity lane) |
| Miruro miruro | www.miruro.bz | anime | Active | Primary anime source — sub and dub from many backends behind one AniList-keyed pipe |
| AnimeGG animegg | www.animegg.org | anime | Active | Independent anime source — direct MP4s, sub and dub, no AniList dependency |
| KickAssAnime kickassanime | kaa.lt | anime | Active | Independent anime source — HLS with separate subtitle tracks, sub and dub |
| YouTube youtube | youtube.com | video | Production | YouTube via Invidious search and yt-dlp playback |
Mode defaults at a glance:
- Movies / series: VidLink first, then Rivestream, then Videasy (from
providerPriority). Videasy's canonical metadata host has stopped resolving at DNS, so it is a fallback rather than the lead; its stream resolve path still answers - Anime: HiAnime first, then Miruro, then KickAssAnime, then AnimeGG, then AniDB, then AllManga (from
animeProviderPriority). Every registered provider is tried automatically; the list sets the order, not who is included - YouTube: dedicated video mode via Invidious search + yt-dlp playback
Legacy id vidking maps to Videasy in config and cache. Cineby is research-only, not registered for production resolve.
Videasy
Adapter role: registered movies/series adapter, last in the automatic lane. Its metadata host api.videasy.to has stopped resolving at DNS (title enrichment degrades), while the wings stream endpoints it resolves through still answer, which is why it stays a fallback rather than the lead or removed.
Config id: videasy (legacy alias vidking still accepted).
Caveats: catalog and source availability can change; use /recover then /fallback (or ⇧F during playback) when a stream dies.
VidLink
Adapter role: registered default for movies and series; also carries the best subtitle inventory of the lane.
Config id: vidlink. The automatic order is VidLink, Rivestream, then Videasy.
Caveats: subtitle language coverage is not guaranteed for every title.
Rivestream
Adapter role: candidate movies/series adapter. Second in the automatic series lane after VidLink.
Config id: rivestream.
Caveats: treat failures as normal for a candidate; fallback is expected.
KickAssAnime
Adapter role: the anime backup, third in the default order. It has its own catalogue, site and video servers, so a HiAnime or Miruro outage does not reach it. Unlike the others it can pick up a show Kunai found anywhere, by matching the name and year against its own catalogue.
Config id: kickassanime.
{
"animeProvider": "hianime",
"animeProviderPriority": ["miruro", "kickassanime", "animegg", "anidb", "allanime"]
}Caveats: anime mode must be active. This is the one anime source with real subtitle tracks
rather than subtitles burned into the picture, so /tracks can switch languages during playback.
Dubs usually live inside the same video file as extra audio tracks; when a show has no English
audio Kunai plays the subbed version and says so in the playback trace. If it cannot tell which
show you mean, it steps aside rather than playing the wrong one.
AnimeGG
Adapter role: the fourth anime source, behind HiAnime, Miruro and KickAssAnime. AnimeGG has its own catalogue, its own site and its own video servers, so it keeps working when the earlier providers do not, which is the whole reason it is there. It picks up a show Kunai found anywhere by matching its name against AnimeGG's own catalogue. Sub and dub both come from AnimeGG's own episode tabs.
Config id: animegg.
{
"animeProvider": "hianime",
"animeProviderPriority": ["miruro", "kickassanime", "animegg", "anidb", "allanime"]
}Caveats: anime mode must be active. Subtitles are burned into the picture on subbed episodes, so there is no separate subtitle track to switch. Not every show has a dub, and Kunai says so in the playback trace when it falls back to the subbed version. Its catalogue is smaller than Miruro's, and when more than one of its shows could be the one you picked, it steps aside rather than guess.
Movy
Adapter role: registered movies/series adapter backed by the movy.sx source aggregator. Each upstream lane (denver, atlanta, and so on) is a separate source, so /source switches lanes directly.
Config id: movy.
Caveats: lanes are independent upstream scrapers; coverage varies per title and individual lanes may 500 while others still resolve. A seed exchange precedes each resolve; a stale seed is retried once automatically.
AniDB
Adapter role: fifth in the default anime order, behind HiAnime, Miruro, KickAssAnime and AnimeGG. Selected directly, Kunai searches AniDB, routes each season to its own AniDB title, and resolves streams from that title. It was the lane default until anidb.app started answering 503 at the origin; ani-cli moved off it the same way.
Config id: anidb for animeProvider / animeProviderPriority. To use it as your lead anyway:
{
"animeProvider": "anidb",
"animeProviderPriority": ["hianime", "miruro", "kickassanime", "animegg", "allanime"]
}Caveats: anime mode must be active (-a or anime mode in the shell). Some networks need curl
installed for AniDB requests to get past Cloudflare. If a season cannot be matched unambiguously,
Kunai reports that rather than playing a different season. AniDB does not advertise hardsub tracks.
AllManga
Adapter role: last in the default anime order, behind HiAnime, Miruro, KickAssAnime, AnimeGG and AniDB. Display name is AllManga; the runtime id is allanime. It carries the ani-cli parity path, which is why it stays registered even when its stream API is gated.
Config id: allanime. The display name is not the config id.
Caveats: anime mode must be active (-a or anime mode in the shell). Some networks hit a captcha/Cloudflare gate on stream sources while the episode catalog still loads, so the episode list can look healthy and still not play. Its decryption keys rotate often; a key change shows up as resolve failures until Kunai is updated.
HiAnime
Adapter role: the default anime provider, first in the order. HiAnime has its own catalogue and search, so anime search keeps working when AniList or AniDB are down. It resolves the ZokoAnime server for each episode, the same one ani-cli uses, and hands the HLS ladder and subtitle tracks to the player.
Config id: hianime.
{
"animeProvider": "hianime",
"animeProviderPriority": ["miruro", "kickassanime", "animegg", "anidb", "allanime"]
}Caveats: anime mode must be active. Sub and dub are separate episode fetches; a show without
English audio plays subbed and says so in the playback trace. Each season is its own entry in
HiAnime's catalogue, so a season jump is a new title rather than a deeper episode number. On
networks where Kunai's own HTTP client meets Cloudflare, it falls back to curl.
Miruro
Adapter role: second in the default anime order, behind HiAnime. Miruro fronts roughly a dozen streaming backends behind one AniList-keyed service, so when one of them goes down Kunai moves to the next server instead of failing the episode. Anime search goes through Miruro too, so it keeps working when AniList is down; if Miruro's search finds nothing, Kunai asks AniList.
Config id: miruro.
{
"animeProvider": "miruro",
"animeProviderPriority": ["hianime", "kickassanime", "animegg", "anidb", "allanime"]
}Caveats: anime mode must be active. Kunai tries its own HTTP client first, but Cloudflare
refuses it at Miruro's API, so in practice curl is what gets through; a provider relay answers
on Kunai's behalf if you run one. Some servers burn subtitles into the video
rather than shipping a separate track, and one opens on a short site bumper before the episode.
If miruro.bz itself is unreachable, every one of its backends is too, and Kunai falls back to
the providers behind it.
HiAnime
Adapter role: the automatic anime lane's lead, Kunai's shipped animeProvider. Sub and dub resolve through the ZokoAnime server with soft English subtitles; each season is a separate catalog title.
Config id: hianime. The shipped lane is animeProvider: "hianime" with animeProviderPriority: ["miruro", "kickassanime", "animegg", "anidb", "allanime"].
Caveats: anime mode must be active (-a or anime mode in the shell). Some networks need curl installed for HiAnime requests to get past Cloudflare. Only the ZokoAnime server is resolved; other servers the catalog lists are observed but unsupported.
YouTube
Adapter role: YouTube mode: Invidious search, yt-dlp stream handoff to mpv. This is not a TMDB movie/series adapter.
Config id: youtube. Switch with /youtube-mode or Tab to cycle catalog mode.
Caveats: requires network; yt-dlp must be available for resolve. Kunai does not bypass DRM or circumvent YouTube access controls. It only forwards optional cookies you already have to yt-dlp/mpv.
Search can return videos, Shorts, playlists, and channels. Results retain
their shape and the shell labels it before playback, so a Short is not mistaken
for a collection. Playlists and channels are catalog collections
(youtube-playlist:… / channel ids): pick a video inside them to play. Live
and upcoming entries carry their own status badge (● LIVE for an active
broadcast, Upcoming for a premiere that has not started, Was Live for an
archived stream). Backends that omit a shape or status signal are labelled
conservatively. Use type:short in YouTube search to narrow to Shorts; that query
runs YouTube's own Shorts search through yt-dlp rather than filtering ordinary
results, which never include Shorts. If it finds none, it says so instead of
falling back to regular videos.
Live URLs (youtube.com/live/…) resolve as videos. Kunai passes
--no-live-from-start to yt-dlp so a live handoff joins at the live edge, and it
will not offer to resume a broadcast from a saved position; a live stream has no
fixed position to return to. Opening a premiere that has not started tells you so
instead of handing mpv a stream that cannot play yet.
SponsorBlock is off unless you set youtubeMetadata.sponsorblockRemove in Settings › YouTube (for example sponsor,intro). That value is forwarded to yt-dlp / mpv. There is no shipped default category list.
Cookie safety (age-restricted / members)
Optional keys under youtubeMetadata in ~/.config/kunai/config.json (also editable from /settings → YouTube):
| Key | Safe usage |
|---|---|
cookiesFromBrowser | Browser name for yt-dlp --cookies-from-browser (for example chrome, firefox). Reads cookies from that browser profile on your machine. |
cookiesFile | Absolute path to a Netscape cookie file passed as yt-dlp --cookies. Relative paths are easy to mis-resolve; use an absolute path. |
poToken | Proof of Origin token in yt-dlp's CLIENT.CONTEXT+TOKEN form (for example visionos.gvs+...). A bare token is scoped to whichever client Kunai is asking for. Used for playback and downloads alike. |
Safety rules:
- Never paste cookie file contents into issues, chats, or support bundles.
- Prefer
cookiesFromBrowserwhen it works; keepcookiesFileprivate on disk. - Before sharing
/export-diagnosticsor/report-issueoutput, open the redacted bundle locally and confirm cookies/tokens/paths stay redacted. - There is no shipped default cookie file and no claim of DRM bypass.
How resolution works (user view)
You select a title and episode
Kunai builds a resolve request from your mode, language profiles, and any per-title provider preference.
Kunai tries the default provider first
Your provider or animeProvider config key sets the session default. Startup priority policy may influence first pick.
Falling back to another provider can change the available source inventory (quality ladder, sub/dub mix). Title and catalog identity never silently cross to another catalog: an advanced search with no compatible catalog is reported as unsupported rather than quietly answered by TMDB.
Provider-local cycling
Within one provider, Kunai may try multiple sources, servers, or variants before giving up. Diagnostics shows this as retry progress, not necessarily an error.
Global fallback
If the active provider is exhausted, skipped, or unhealthy for this request, Kunai moves to the next id in your priority list.
Stream handoff
The winning stream becomes mpv input with required headers and subtitle attachments. Inventory is cached for faster re-selection.
More detail on pickers: Media selection.
Fallback chain configuration
Configure order in /settings or ~/.config/kunai/config.json:
{
"provider": "vidlink",
"providerPriority": ["rivestream", "videasy"],
"animeProvider": "hianime",
"animeProviderPriority": ["miruro", "kickassanime", "animegg", "anidb", "allanime"]
}The anime client shows as AllManga in the UI; the config id remains allanime. Every
registered anime provider is tried automatically when the selected one fails. The priority list
sets the order, it does not decide who is included.
If you saved settings while AniDB was the default, Kunai moves that inherited default to the order above once, on the first launch after updating. It only does this when your anime settings are still exactly the old default; if you had changed them, they are left alone, and if you pick AniDB again afterwards, it stays picked.
Rules:
- Empty priority arrays use registry default order.
- Unknown ids in the list are ignored.
- Providers not listed remain available after configured entries.
- Per-title overrides in
titleProviderPreferenceswin over history provider on resume.
See Customization.
Retry vs recover vs fallback
Kunai uses three distinct user-facing actions. They are not interchangeable.
| Action | Keys / command | What happens |
|---|---|---|
| Recover | r, /recover | Refresh current playback intent on the active provider: new resolve, cache revalidation, or mpv reload |
| Retry (automatic) | none | Provider-local cycling through sources/variants before global fallback; shown in diagnostics timeline |
| Fallback provider | ⇧F, /fallback | Stop active provider; global engine picks next compatible provider |
| Recompute | /recompute | Bypass stream cache and provider health memory for current episode |
Recover before fallback
When a stream dies mid-playback, try recover first. Fallback switches providers and may change source quality or subtitles.
Recovery mode setting
recoveryMode in config changes default aggressiveness:
| Mode | Behavior |
|---|---|
guided (default) | Explain failures; suggest recover then fallback |
fallback-first | Prefer moving to next provider sooner after classified failures |
manual | Minimal automatic fallback; user drives /recover and /fallback |
Provider health and cache
Kunai remembers provider health locally to avoid hammering known-bad paths. Health updates come from resolve outcomes, not from your home network being offline.
- Cache hit: reuse recent stream inventory when still valid.
- Stale cache: revalidate before play when health checks fail.
- Cold resolve: full provider lookup when no usable cache exists.
/diagnostics shows cache provenance and health deltas without exposing signed URLs.
Network-unavailable failures stop cycling early. Kunai does not mark unrelated providers as unhealthy because your Wi-Fi dropped.
Domain overrides
Provider domains for the media (movie/TV and anime) providers are compiled in; changing a media-provider domain requires a code change and rebuild, not a config file. Exception: YouTube metadata endpoints are configurable via youtubeMetadata.instanceUrl and youtubeMetadata.pipedApiUrl in settings or config.json, no rebuild needed. To use a different network path for metadata calls, set providerRelay.baseUrl in /settings or config.json to your own relay; see Provider geo relay.
Provider geo relay
Some provider metadata APIs are geo-blocked from some countries while the final video CDN still works globally. Kunai supports an optional user-owned provider relay for those metadata calls.
What it does:
- Routes provider API/search/source JSON through your relay when
providerRelay.baseUrlis set. - Keeps playback direct: mpv receives the final stream URL and fetches it from your network.
- Uses provider manifest allowlists, so it is not an arbitrary URL proxy.
What it does not do:
- Kunai does not operate a public relay for you.
- Kunai does not host or proxy video. There is no video-relay configuration; stream URLs always stay direct.
- The relay does not bypass provider login or DRM.
Installed binaries: leave providerRelay.baseUrl empty (the default) for direct fetches. To use a relay you operate, set baseUrl in /settings or config.json to your origin; Kunai never ships a public relay URL. An internet relay requires a matching bearer token; only a relay bound to numeric loopback may run without one. fallbackToDirect: true degrades to direct fetches after relay network or authorization-policy failures where the provider is not geo-blocked. Env overrides: KUNAI_RELAY_BASE_URL, KUNAI_RELAY_TOKEN.
Deploying your own relay
A relay only helps when it reaches the provider from a network that is not blocked. A captcha gate (NEED_CAPTCHA) or a regional block is tied to your IP, so the relay has to run somewhere else: a free serverless host, or a machine in an ungated region. Both deploy from a source checkout, since the relay imports the @kunai/relay and @kunai/providers workspace packages.
On Vercel. Full steps and the reason handler bundling is required are in apps/relay-server/README.md:
cd apps/relay-server
vercel env add RELAY_TOKEN # a random secret; the relay refuses internet traffic without one
vercel build --prod --yes
vercel deploy --prebuilt --prodLocally, for development or a home server on an ungated network:
bun run dev:relay # listens on http://127.0.0.1:8787Pointing Kunai at your relay
Set the origin and token in any one of three places (/settings → Provider Relay, config.json, or the environment) and keep fallbackToDirect on so Kunai degrades to direct fetches when the relay is unreachable and the provider is not geo-blocked.
{
"providerRelay": {
"baseUrl": "https://your-relay.vercel.app",
"token": "your-secret-token",
"fallbackToDirect": true
}
}Environment overrides: KUNAI_RELAY_BASE_URL, KUNAI_RELAY_TOKEN. Leave the token blank only for a relay bound to numeric loopback; any internet origin needs one.
Source-checkout smoke and verification steps: Debugging workflow and apps/relay-server/README.md.
When providers fail (expected behavior)
Provider catalogs drift. Failure is operational, not exceptional.
- Diagnostics records failure class and stage.
- Kunai attempts provider-local retries when inventory exists.
- Global fallback runs when configured and appropriate.
- You stay in the shell with context intact; search, history, and offline library remain available.
If all providers fail, Kunai explains why in diagnostics and the shell footer. Collect evidence with /export-diagnostics; see Troubleshooting.
What Kunai does not do with providers
- No browser/Playwright scraping in the active beta runtime
- No Kunai-hosted proxy or stream relay; the optional provider geo relay is user-owned and metadata-only by default
- No guarantee of subtitle language, quality tier, or dub availability
- No silent provider switching without user action (except configured automatic fallback within policy)
See Supported and Unsupported.
Picking a provider manually
Before playback starts:
- Provider picker in the starting-episode flow when multiple providers are compatible.
/sourceor/tracksduring playback when inventory supports switching without full re-resolve.
After explicit pick, Kunai stores per-title preference for future resume.
Last updated on
Downloads and Offline
Queue Kunai downloads, play local files, manage the offline library, clean up finished jobs, and diagnose a download that stalled or failed to resume.
Provider status
Daily live check on every registered provider, covering upstream reachability, resolve health, lane counts, and known gate reasons.