// AniVault API — Documentation

Stream Anything.
From Anywhere.

A unified REST API to fetch anime stream URLs and embed links across multiple sources, addressed by MAL or AniList ID. Railway-ready, zero config.

Online 4 Streaming Sources MAL Scraper TMDB · Kitsu · AniList Sub · Dub · Raw
Supported Sources
Each source has its own scraper. CSS selectors and resolvers are kept in sync with upstream sites.
🎭
AnimeHeaven
animeheaven.me
Not on Vercel
Keyanimeheaven
ID formatAnimeHeaven show ID
StreamsDirect MP4
AudioSub only
🦊
Anikoto
anikoto.net
Megacloud & HLS
Keyanikoto
ID formatTitle-search slug
ServersMegacloud, Megaplay, Kiwi Mapper
AudioSub, Dub
▶️
MegaPlay Direct
megaplay.buzz
Direct-ID
Keymegaplay
ID formatMAL ID or AniList ID
StreamsPlayer page → HLS resolver
AudioSub / Dub (upstream dependent)
🇮🇳
DesiDub
desidubanime.me
Multi-Audio & Dub
Keydesidub
ID formatShow slug / MAL ID
ServersMirror, VidMoly, StreamRuby, Abyss
AudioDub (Hindi/Muse/Official), Sub
API Tester
Two ways in: the guided streaming flow (search → source → server → watch), or a raw form for any of the ~35 documented endpoints.
anivault-api · tester
AniList MAL Eps
🦊
Anikoto anikoto.net
🎭
AnimeHeaven animeheaven.me
🇮🇳
DesiDub desidubanime.me
▶️
MegaPlay Direct megaplay.buzz
⚡ Auto
Select an anime + episode first to load available servers
URL will appear here
Response

            
Waiting
Fetch data first
▶
Embed preview will appear here after fetch
anivault-api · endpoint tester
← Pick an endpoint to build a request
URL Structure
Path-based is recommended. Query-based is also supported for backward compat.
Path-based (recommended)
# /api/watch/{source}/{id}/{ep}/{type}?server=Name
# id = AniList ID  OR  mal-{malId}

GET /api/watch/anikoto/20/1/sub
GET /api/watch/desidub/mal-16498/1/dub?server=VMoly
GET /api/watch/animeheaven/{heavenId}/3/sub
Query-based (compat)
GET /api/watch?source=desidub&malId=16498&ep=1&type=dub
GET /api/watch?source=anikoto&anilistId=20&ep=1&type=sub
GET /api/watch?source=animeheaven&heavenId=ukr6y&ep=5&type=sub
MAL Scraper
Direct MyAnimeList scraper — replaces Jikan for everything below. Cached, rate-limited to one request in flight at a time.
GET /api/mal/anime/{id} Full anime details ▼
ParamTypeWhereDescription
idnumberpathMAL anime ID
Example Response
{
  "malId": 16498, "title": "Shingeki no Kyojin",
  "titleEnglish": "Attack on Titan", "titleJapanese": "進撃の巨人",
  "synopsis": "...", "image": "https://cdn.myanimelist.net/images/anime/10/47347.jpg",
  "type": "TV", "episodes": 25, "status": "Finished Airing",
  "aired": "Apr 7, 2013 to Sep 29, 2013", "score": 8.55, "rank": 115,
  "genres": ["Action", "Drama"], "studios": ["Wit Studio"],
  "streamingPlatforms": [{ "name": "Crunchyroll", "url": "https://..." }]
}
GET /api/mal/anime/{id}/episodes Paginated episode list, 100/page ▼
ParamTypeWhereDescription
idnumberpathMAL anime ID
pagenumberqueryoptional default 1
Example Response
{
  "data": [
    { "malId": 1, "title": "To You, 2000 Years in the Future", "aired": "Apr 7, 2013", "filler": false, "recap": false }
  ],
  "pagination": { "currentPage": 1, "hasNextPage": false }
}
GET /api/mal/anime/{id}/episodes/{epNum} One episode's title/aired/filler/recap ▼
ParamTypeWhereDescription
idnumberpathMAL anime ID
epNumnumberpathEpisode number
Example Response
{ "data": { "malId": 1, "title": "To You, 2000 Years in the Future", "titleJapanese": "2000年後の君へ", "aired": "Apr 7, 2013", "filler": false, "recap": false } }
GET /api/mal/anime/{id}/characters Cast + voice actors for an anime ▼
ParamTypeWhereDescription
idnumberpathMAL anime ID
Example Response
{
  "data": [{
    "characterId": 40882, "name": "Yeager, Eren", "image": "https://cdn.myanimelist.net/...",
    "role": "Main",
    "voiceActors": [{ "peopleId": 118, "name": "Kaji, Yuuki", "language": "Japanese" }]
  }]
}
GET /api/mal/character/{id} Single character: bio + animeography + voice actors in one scrape ▼
ParamTypeWhereDescription
idnumberpathMAL character ID
Example Response
{
  "characterId": 45627, "name": "Levi (リヴァイ)", "nameKanji": "リヴァイ",
  "about": "Levi is known as humanity's most powerful soldier...",
  "note": "Levi is the official English translation by Kodansha.",
  "spoilers": ["It is later revealed that his full name is Levi Ackerman."],
  "favorites": 146754, "image": "https://cdn.myanimelist.net/...",
  "animeography": [{ "animeId": 16498, "title": "Shingeki no Kyojin", "role": "Supporting" }],
  "voiceActors": [{ "peopleId": 118, "name": "Kamiya, Hiroshi", "language": "Japanese" }]
}
GET /api/mal/anime/{id}/pictures Anime picture gallery ▼
ParamTypeWhereDescription
idnumberpathMAL anime ID
Example Response
{ "data": [{ "image": "https://cdn.myanimelist.net/images/anime/.../full.jpg", "thumbnail": "https://cdn.myanimelist.net/images/anime/.../small.jpg" }] }
GET /api/mal/character/{id}/pictures Character picture gallery ▼
ParamTypeWhereDescription
idnumberpathMAL character ID
Example Response
{ "data": [{ "image": "https://cdn.myanimelist.net/images/characters/.../full.jpg", "thumbnail": "https://cdn.myanimelist.net/images/characters/.../small.jpg" }] }
GET /api/mal/anime/{id}/themes Opening/ending theme credits + Spotify links ▼
ParamTypeWhereDescription
idnumberpathMAL anime ID
Example Response
{
  "opening": [{ "number": 1, "title": "Guren no Yumiya", "artist": "Linked Horizon", "episodes": "1-13", "spotifyUrl": "https://open.spotify.com/track/..." }],
  "ending": [{ "number": 1, "title": "Utsukushiki Zankoku na Sekai", "artist": "Yoko Hikasa", "episodes": "1-13", "spotifyUrl": null }]
}
GET /api/mal/anime/{id}/videos Trailers (PVs) + official music videos, with YouTube IDs ▼
ParamTypeWhereDescription
idnumberpathMAL anime ID
Example Response
{
  "musicVideos": [{ "label": "ED 1 (Artist ver.)", "youtubeId": "kgZRAyVMcB8", "embedUrl": "https://www.youtube-nocookie.com/embed/...", "songTitle": "Utsukushiki Zankoku na Sekai", "songArtist": "Yoko Hikasa" }],
  "trailers": [{ "label": "PV 1", "youtubeId": "KKzmOh4SuBc", "embedUrl": "https://www.youtube-nocookie.com/embed/...", "songTitle": null, "songArtist": null }]
}
GET /api/mal/anime/{id}/recommendations Top 12 "you might also like", vote-sorted ▼
ParamTypeWhereDescription
idnumberpathMAL anime ID
Example Response
{ "data": [{ "animeId": 28623, "title": "Koutetsujou no Kabaneri", "image": "https://cdn.myanimelist.net/...", "votes": 109 }] }
GET /api/mal/anime/{id}/external Official site + streaming/related outbound links ▼
ParamTypeWhereDescription
idnumberpathMAL anime ID
Example Response
{ "data": [{ "name": "Official Site", "url": "https://shingeki.tv/" }] }
GET /api/mal/anime/{id}/streaming Legal streaming platforms (Crunchyroll, Netflix, etc.) ▼
ParamTypeWhereDescription
idnumberpathMAL anime ID
Example Response
{ "data": [{ "name": "Crunchyroll", "url": "https://www.crunchyroll.com/..." }] }
AniList · TMDB · Kitsu
Supplementary metadata and art. All three "anime art" endpoints (/anilist/anime, /tmdb/anime, /kitsu/anime) return the same shape so they're interchangeable as fallbacks.
GET /api/anilist/season Current airing season from AniList ▼
ParamTypeRequiredDescription
malIdnumberoptionalReturn just this one show's entry from the season
Example Response
{ "season": "SUMMER", "seasonYear": 2026, "media": [{ "idMal": 16498, "title": "..." }] }
GET /api/anilist/top-banners Banner images for top-rated anime, keyed by MAL ID ▼
ParamTypeRequiredDescription
limitnumberoptionaldefault 200
malIdnumberoptionalReturn just this one entry
Example Response
{ "data": { "16498": "https://s4.anilist.co/file/anilistcdn/media/anime/banner/16498.jpg" } }
GET /api/anilist/id MAL ID → AniList ID ▼
ParamTypeRequiredDescription
malIdnumberrequiredMAL anime ID
Example Response
{ "malId": 16498, "anilistId": 16498 }
GET /api/anilist/episodes AniList's streamingEpisodes list (titles + thumbnails, last-resort fallback) ▼
ParamTypeRequiredDescription
malIdnumberrequiredMAL anime ID
epnumberoptionalReturn just this one episode
Example Response
{ "malId": 16498, "episodes": [{ "title": "Episode 1 - To You, in 2000 Years", "thumbnail": "https://s4.anilist.co/..." }] }
GET /api/{anilist|tmdb|kitsu}/anime Poster + cover art (+ logo on TMDB) — same shape across all 3 ▼
ParamTypeRequiredDescription
malIdnumberone ofMAL anime ID
titlestringone ofDirect title search, skips MAL lookup (TMDB/Kitsu only)
liststringoptional1 to skip cache (fresh lookup)
Example: /api/tmdb/anime?malId=16498
{ "data": { "poster": "https://image.tmdb.org/t/p/original/...", "cover": "https://image.tmdb.org/t/p/original/...", "logo": "https://image.tmdb.org/t/p/original/..." }, "log": ["..."] }
Example: /api/kitsu/anime?malId=16498
{ "data": { "poster": "https://media.kitsu.app/anime/poster_images/.../original.jpg", "cover": "https://media.kitsu.app/anime/cover_images/.../original.jpg" }, "log": ["..."] }
GET /api/{tmdb|kitsu}/episode-thumb Single episode still/thumbnail ▼
ParamTypeRequiredDescription
epnumberrequiredEpisode number
malIdnumberone ofMAL anime ID
titlestringone ofDirect title search
Example Response
{ "data": { "thumbnail": "https://image.tmdb.org/t/p/original/still.jpg" }, "log": ["..."] }
Combined Endpoints
One call instead of chaining several — MAL metadata merged with art/thumbnails from the fallback chain above.
GET /api/anime MAL details + poster/cover/logo, one call ▼
ParamTypeRequiredDescription
malIdnumberrequiredMAL anime ID
liststringoptional1 to skip art cache
Example Response
{
  "data": {
    "malId": 16498, "title": "Shingeki no Kyojin", "episodes": 25, "score": 8.55,
    "genres": ["Action"], "streamingPlatforms": [{ "name": "Crunchyroll", "url": "..." }],
    "poster": "https://image.tmdb.org/...", "posterSource": "tmdb",
    "cover": "https://image.tmdb.org/...", "coverSource": "tmdb",
    "logo": "https://image.tmdb.org/...", "logoSource": "tmdb"
  },
  "log": ["..."]
}
GET /api/episode MAL episode metadata + thumbnail (single episode, or the whole show) ▼
ParamTypeRequiredDescription
malIdnumberrequiredMAL anime ID
epnumberoptionalOmit for the whole show's episode list
concurrencynumberoptionalWhole-show mode only. Default 5, max 10
liststringoptional1 to skip thumbnail cache
Example: single episode (?ep=1)
{
  "data": {
    "malId": 16498, "episode": 1, "title": "To You, 2000 Years in the Future",
    "aired": "Apr 7, 2013", "filler": false, "recap": false,
    "thumbnail": "https://media.kitsu.app/...", "thumbnailSource": "kitsu"
  },
  "log": ["..."]
}
Example: whole show (no ?ep=)
{
  "malId": 16498, "title": "Attack on Titan", "count": 25,
  "episodes": [{ "episode": 1, "title": "...", "thumbnail": "...", "thumbnailSource": "tmdb" }]
}
Error Codes
All errors return { "error": "message", "detail": "..." }
StatusMeaningCommon Cause
200OKEverything worked
206Partial — dub fallbackDub not available, returned sub instead
400Bad RequestMissing or invalid params
404Not FoundAnime/episode not on that source
429Rate Limited60 req/min — slow down
502Bad GatewayAll servers returned empty responses
500Server ErrorScrape failed — site HTML may have changed
AniVault API · Built for educational use · Selectors require periodic maintenance after site updates
Megacloud keys may rotate — check aniwatch-api for updates