Skip to content

Shineii86/MiruroAPI

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

21 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Stars Forks Issues Pull Requests Last Commit License

Node.js Express AniList GraphQL Vercel License Version Endpoints Providers

A complete RESTful API for anime streaming data powered by AniList GraphQL and Miruro providers
Search, browse, filter, watch β€” every endpoint returns fresh data with smart caching.
18 endpoints, 12 streaming providers, M3U8 URLs with subtitles and skip timestamps.

Table of Contents β€’ Features β€’ API Docs β€’ Quick Start β€’ Deployment β€’ Contributing


Warning

  1. This API does not store any files β€” it only links to media hosted on 3rd party services.
  2. This API is explicitly made for educational purposes only and not for commercial usage. This repo will not be responsible for any misuse of it.
  3. All anime data, images, and content belong to their respective owners (AniList, Miruro). This project is not affiliated with miruro.tv.

πŸ“– Table of Contents


🌸 Overview

MiruroAPI is a serverless anime data API that fetches real-time information from AniList GraphQL and streaming data from Miruro providers β€” including anime details, episode lists, M3U8 streaming URLs with subtitles and skip timestamps, search, filtering, characters, and more β€” all through a clean REST API with zero database.

πŸ’‘ No database, no auth, no complex setup. Just deploy to Vercel and you have a production API.

Why MiruroAPI?

  • 🎬 18 Endpoints β€” Complete anime data coverage
  • πŸ” Full-Text Search β€” Search anime by keyword with suggestions
  • 🎭 Characters & Voice Actors β€” Full character data from AniList
  • 🎯 Advanced Filtering β€” Genre, year, season, format, sort
  • πŸ† Trending & Popular β€” Discover what's hot right now
  • πŸ“… Airing Schedule β€” See what's airing on any date
  • πŸ“‘ 12 Streaming Providers β€” M3U8 streaming sources
  • ⏭️ Skip Timestamps β€” OP/ED skip data
  • ⚑ Smart Caching β€” In-memory Map with configurable TTL
  • πŸ”’ CORS Enabled β€” Works from any frontend, no proxy needed
  • πŸš€ Zero-Config Deploy β€” One click to Vercel, or run standalone with Express

How It Works

flowchart TD
    A["🌐 Client Request<br/>(Browser / App / curl)"] --> B["πŸ›‘οΈ Express Server<br/>CORS Β· Security Headers Β· Rate Limiting"]
    B --> C{"πŸ’Ύ Cache Check<br/>(In-Memory Map)"}
    C -- HIT --> D["⚑ Return Cached Response<br/>~50ms"]
    C -- MISS --> E{"πŸ” Which Source?"}

    E -- Metadata --> F["πŸ“‘ AniList GraphQL<br/>graphql.anilist.co"]
    E -- Streaming --> G["πŸ“Ί Miruro Pipe<br/>miruro.tv/api/secure/pipe"]

    F --> H["AniList Response<br/>JSON"]
    G --> I["Pipe Response<br/>base64url + gzip"]

    H --> J["Cache + Respond<br/>JSON"]
    I --> J

    style A fill:#1e1e2e,stroke:#a78bfa,color:#f1f5f9
    style B fill:#1e1e2e,stroke:#6366f1,color:#f1f5f9
    style C fill:#1e1e2e,stroke:#f43f8e,color:#f1f5f9
    style D fill:#1e1e2e,stroke:#22c55e,color:#f1f5f9
    style E fill:#1e1e2e,stroke:#a855f7,color:#f1f5f9
    style F fill:#1e1e2e,stroke:#06b6d4,color:#f1f5f9
    style G fill:#1e1e2e,stroke:#eab308,color:#f1f5f9
    style H fill:#1e1e2e,stroke:#06b6d4,color:#f1f5f9
    style I fill:#1e1e2e,stroke:#eab308,color:#f1f5f9
    style J fill:#1e1e2e,stroke:#22c55e,color:#f1f5f9
Loading

✨ Features

⚑ Core

  • AniList GraphQL for rich metadata

  • Miruro pipe for streaming sources

  • Smart caching with configurable TTL

  • 18 RESTful endpoints

  • Graceful error handling per endpoint

  • Rate limiting (100 req/min per IP)

πŸ” Data

  • Full-text search with pagination

  • Autocomplete suggestions for search

  • Advanced filtering β€” genre, year, season, format, sort

  • Characters with voice actors

  • Relations and Recommendations

  • Airing schedule by date

πŸ“‘ Streaming

  • Episode lists from 12 providers

  • M3U8 streaming URLs with resolution info

  • Skip timestamps (OP/ED)

  • Download links when available

  • Sub/Dub support per provider

  • Codec and fansub metadata

πŸ›‘οΈ Reliability

  • CORS enabled β€” works from any frontend

  • Error responses with descriptive messages

  • Input validation β€” required params checked

  • Timeout protection β€” per request

  • In-memory caching β€” survives warm starts

  • Zero database β€” pure API + cache

🌟 Feature Highlights

Feature Description Status
🎬 18 API Endpoints Complete anime data coverage βœ…
πŸ” Full-Text Search Keyword search with pagination βœ…
πŸ’‘ Search Suggestions Fast autocomplete βœ…
🎯 Advanced Filtering Genre, year, season, format, sort βœ…
🎭 Characters + Voice Actors Full character data from AniList βœ…
πŸ”— Relations & Recommendations Related anime discovery βœ…
⏭️ Skip Timestamps OP/ED skip data βœ…
πŸ“‘ 12 Streaming Providers M3U8 streaming sources βœ…
πŸ”„ Smart Caching In-memory Map with TTL βœ…
πŸš€ One-Click Deploy Vercel button deployment βœ…
πŸ—οΈ Express Mode Standalone server with npm start βœ…
🐳 Docker Support Containerized deployment βœ…

πŸ—žοΈ Data Sources

Metadata Source

Source API Data
🌸 AniList graphql.anilist.co Search, info, characters, relations, recommendations, filter, schedule

Streaming Source

Source Domain Data
πŸ“Ί Miruro miruro.tv Episodes, streaming sources (M3U8 URLs)
πŸ“Ί Miruro miruro.to Mirror domain
πŸ“Ί Miruro miruro.bz Mirror domain
πŸ“Ί Miruro miruro.ru Mirror domain

🎬 Streaming Providers

Provider Provider Provider Provider
πŸ₯ kiwi 🐝 pewe 🐻 bee 🍯 bonk
🍌 bun 🀝 ally πŸ¦„ nun πŸ‘― twin
βš™οΈ cog πŸ„ moo 🐰 hop πŸ“Ί telli

πŸ› οΈ Tech Stack

Technology Purpose Version Documentation
🟒 Node.js JavaScript runtime >= 20 Docs
⚑ Express HTTP server framework 4.21 Docs
β–² Vercel Functions Serverless deployment β€” Docs
🌸 AniList GraphQL Anime metadata API β€” Docs
🌐 Axios HTTP client 1.8 Docs
πŸ”§ dotenv Environment variables 16.4 Docs
πŸ”’ cors CORS middleware 2.8 Docs

πŸ“¦ Key Dependencies

{
  "express": "^4.21.0",        // HTTP server
  "axios": "^1.8.0",         // HTTP client
  "cors": "^2.8.5",           // CORS middleware
  "dotenv": "^16.4.0"         // Environment variables
}

πŸ—οΈ Architecture

Request Flow

Stage Component Description
1 Client Browser, app, or curl sends request
2 Express Server Routes request, applies CORS + security headers + rate limiting
3 Cache Check In-memory Map with TTL β€” hit = instant response
4 Fetch Data AniList GraphQL or Miruro pipe endpoint
5 Decode Pipe responses decoded: base64url β†’ gunzip β†’ JSON
6 Cache + Respond Store in cache, return JSON response

Caching Architecture

flowchart TD
    A["πŸ“₯ Request"] --> B{"🧠 Memory Cache<br/>(Map + TTL)"}
    B -- HIT --> C["⚑ Return Cached<br/>~50ms"]
    B -- MISS --> D["πŸ“‘ Fetch from<br/>AniList / Miruro"]
    D --> E["πŸ” Decode<br/>base64url + gzip"]
    E --> F["πŸ’Ύ Cache Result<br/>(1-5 min TTL)"]
    F --> G["πŸ“€ Return Fresh"]

    style A fill:#1e1e2e,stroke:#a78bfa,color:#f1f5f9
    style B fill:#1e1e2e,stroke:#f43f8e,color:#f1f5f9
    style C fill:#1e1e2e,stroke:#22c55e,color:#f1f5f9
    style D fill:#1e1e2e,stroke:#6366f1,color:#f1f5f9
    style E fill:#1e1e2e,stroke:#06b6d4,color:#f1f5f9
    style F fill:#1e1e2e,stroke:#a855f7,color:#f1f5f9
    style G fill:#1e1e2e,stroke:#22c55e,color:#f1f5f9
Loading

πŸ’‘ Serverless functions have read-only filesystems except /tmp. The cache uses in-memory Map which survives across warm invocations.


πŸ“ Project Structure

MiruroAPI/
β”œβ”€β”€ πŸ“‚ public/                              # 🌐 Static files
β”‚   β”œβ”€β”€ πŸ“„ index.html                       #    πŸ“– Premium landing page (real Miruro icons)
β”‚   β”œβ”€β”€ πŸ“„ docs.html                        #    πŸ“˜ Swagger UI interactive documentation
β”‚   β”œβ”€β”€ πŸ“„ openapi.json                     #    πŸ“‹ OpenAPI 3.0 spec
β”‚   β”œβ”€β”€ πŸ“„ icon-dark.svg                    #    πŸŒ™ Miruro dark mode favicon
β”‚   β”œβ”€β”€ πŸ“„ icon-light.svg                   #    β˜€οΈ Miruro light mode favicon
β”‚   β”œβ”€β”€ πŸ“„ icon-512x512.png                 #    πŸ“± Miruro app icon
β”‚   β”œβ”€β”€ πŸ“„ favicon.ico                      #    πŸ”– Classic favicon
β”‚   β”œβ”€β”€ πŸ“„ apple-touch-icon-180x180.png     #    🍎 iOS home screen icon
β”‚   └── πŸ“„ og-image.png                     #    πŸ–ΌοΈ OG/Twitter share image
β”‚
β”œβ”€β”€ πŸ“‚ assets/                              # 🎨 Scraped Miruro assets
β”‚   β”œβ”€β”€ πŸ“‚ favicons/                        #    πŸ”– All favicon variants
β”‚   β”œβ”€β”€ πŸ“‚ logos/                           #    🏷️ Status page logo
β”‚   β”œβ”€β”€ πŸ“‚ fonts/                           #    πŸ”€ Inter + FontAwesome
β”‚   └── πŸ“‚ media/                           #    πŸ–ΌοΈ Testimonial avatars
β”‚
β”œβ”€β”€ πŸ“‚ src/                                 # βš™οΈ Core logic
β”‚   β”œβ”€β”€ πŸ“‚ helpers/                         #    πŸ› οΈ Integration modules
β”‚   β”‚   β”œβ”€β”€ πŸ“„ anilist.js                   #       🌸 AniList GraphQL integration
β”‚   β”‚   β”œβ”€β”€ πŸ“„ pipe.js                      #       πŸ“Ί Miruro pipe integration
β”‚   β”‚   └── πŸ“„ cache.js                     #       πŸ’Ύ In-memory cache with TTL
β”‚   β”‚
β”‚   └── πŸ“‚ routes/                          #    πŸ›€οΈ Express routes
β”‚       └── πŸ“„ apiRoutes.js                 #       🌐 Main API routes (18 endpoints)
β”‚
β”œβ”€β”€ πŸ“„ server.js                            # πŸš€ Express server entry point
β”œβ”€β”€ πŸ“„ package.json                         # πŸ“¦ Dependencies & scripts
β”œβ”€β”€ πŸ“„ vercel.json                          # β–² Vercel routing config
β”œβ”€β”€ πŸ“„ Dockerfile                           # 🐳 Docker support
β”œβ”€β”€ πŸ“„ .dockerignore                        # 🐳 Docker ignore
β”œβ”€β”€ πŸ“„ CHANGELOG.md                         # πŸ“ Version history
└── πŸ“„ README.md                            # πŸ“– This file

πŸš€ Quick Start

Prerequisites

Requirement Minimum Recommended
πŸ“¦ Node.js 20.x 20.x LTS
πŸ“¦ npm 9.0+ 10.x
πŸ’» OS Windows, macOS, Linux Any

πŸ”§ Installation

# 1️⃣ Clone the repository
git clone https://github.com/Shineii86/MiruroAPI.git
cd MiruroAPI

# 2️⃣ Install dependencies
npm install

# 3️⃣ Start development server
npm run dev

🌐 Open http://localhost:3000 in your browser.

πŸ—οΈ Build for Production

# Start production server
npm start

🐳 Alternative Package Managers

# Using yarn
yarn install
yarn dev

# Using pnpm
pnpm install
pnpm dev

# Using bun
bun install
bun dev

βš™οΈ Configuration

Environment Variables

Variable Default Description
PORT 3000 Server port (Express mode only)
ALLOWED_ORIGINS * Comma-separated allowed origins

Vercel Configuration

The vercel.json file handles:

  • Builds β€” Maps server.js to @vercel/node
  • Routes β€” All requests forwarded to Express

πŸ“‘ API Endpoints

Base URL

https://mirurotvapi.vercel.app/api

Response Format

All endpoints return:

{
  "success": true,
  "results": { ... }
}

Streaming Flow

To get a stream URL, follow these 3 steps:

# Step 1: Get episodes (returns provider slugs)
curl "https://mirurotvapi.vercel.app/api/episodes/20"

# Step 2: Get streaming sources (pass provider + anilistId + category + slug)
curl "https://mirurotvapi.vercel.app/api/watch/kiwi/20/sub/animepahe-1"

# Step 3: Play M3U8 in any HLS player
# Use hls.js, video.js, or native <video> with hls support

Sub & Dub Switch

Providers return both sub and dub episode lists:

const eps = await fetch("/api/episodes/20").then(r => r.json());
const kiwi = eps.results.providers.kiwi.episodes;

// Pick sub or dub
const subEps = kiwi.sub;  // [{ id: "watch/kiwi/20/sub/anikoto-1", ... }]
const dubEps = kiwi.dub;  // [{ id: "watch/kiwi/20/dub/...", ... }]

// Get stream URL
const stream = await fetch(`/api/watch/kiwi/20/sub/animepahe-1`).then(r => r.json());
// stream.results.streams[0].url = "https://...m3u8"

πŸ₯ GET Health Check

Endpoint

/health

Parameters

No parameters required.

Example of request

curl "https://mirurotvapi.vercel.app/api/health"
import axios from "axios";
const resp = await axios.get("https://mirurotvapi.vercel.app/api/health");
console.log(resp.data);

Sample Response

{
  "success": true,
  "results": {
    "status": "healthy",
    "version": "1.2.0",
    "uptime": "0h 0m 34s",
    "uptimeSeconds": 34,
    "timestamp": "2026-06-09T09:55:00.884Z",
    "node": "v24.14.1",
    "memory": { "used": "13MB", "total": "15MB" },
    "endpoints": 16,
    "providers": ["kiwi","pewe","bee","bonk","bun","ally","nun","twin","cog","moo","hop","telli"]
  }
}

πŸ“Š GET Stats

Endpoint

/stats

Parameters

No parameters required.

Example of request

curl "https://mirurotvapi.vercel.app/api/stats"
import axios from "axios";
const resp = await axios.get("https://mirurotvapi.vercel.app/api/stats");
console.log(resp.data);

Sample Response

{
  "success": true,
  "results": {
    "uptime": "0h 0m 34s",
    "requests": { "total": 156, "errors": 3, "successRate": "98.1%" },
    "cache": { "size": 12, "maxSize": 100, "ttl": "1 min" },
    "endpoints": 16,
    "timestamp": "2026-06-09T09:55:00.884Z"
  }
}

πŸ” GET Search

Endpoint

/search

Parameters

Parameter Type Mandatory Default Description
query string Yes βœ”οΈ β€” Search keyword
page number No 1 Page number
per_page number No 20 Results per page

Example of request

curl "https://mirurotvapi.vercel.app/api/search?query=naruto&per_page=2"
import axios from "axios";
const resp = await axios.get("https://mirurotvapi.vercel.app/api/search", {
  params: { query: "naruto", per_page: 2 }
});
console.log(resp.data);

Sample Response

{
  "success": true,
  "results": {
    "page": 1,
    "perPage": 2,
    "total": 5000,
    "hasNextPage": true,
    "results": [
      {
        "id": 20,
        "title": { "romaji": "NARUTO", "english": "Naruto", "native": "NARUTO -γƒŠγƒ«γƒˆ-" },
        "coverImage": { "large": "https://s4.anilist.co/file/anilistcdn/media/anime/cover/medium/bx20-dE6UHbFFg1A5.jpg" },
        "format": "TV",
        "season": "FALL",
        "seasonYear": 2002,
        "episodes": 220,
        "status": "FINISHED",
        "averageScore": 80,
        "genres": ["Action","Adventure","Comedy","Drama","Fantasy","Supernatural"]
      }
    ]
  }
}

πŸ’‘ GET Search Suggestions

Endpoint

/suggestions

Parameters

Parameter Type Mandatory Default Description
query string Yes βœ”οΈ β€” Search keyword

Example of request

curl "https://mirurotvapi.vercel.app/api/suggestions?query=naruto"
import axios from "axios";
const resp = await axios.get("https://mirurotvapi.vercel.app/api/suggestions", {
  params: { query: "naruto" }
});
console.log(resp.data);

Sample Response

{
  "success": true,
  "results": [
    { "id": 20, "title": "Naruto", "title_romaji": "NARUTO", "poster": "https://s4.anilist.co/file/...", "format": "TV", "status": "FINISHED", "year": 2002, "episodes": 220 },
    { "id": 1735, "title": "Naruto: Shippuden", "title_romaji": "NARUTO: Shippuuden", "poster": "https://s4.anilist.co/file/...", "format": "TV", "status": "FINISHED", "year": 2007, "episodes": 500 }
  ]
}

🎯 GET Filter

Endpoint

/filter

Parameters

Parameter Type Mandatory Default Description
genre string No β€” Genre name (e.g. "Action")
tag string No β€” Tag name
year number No β€” Release year
season string No β€” FALL, WINTER, SPRING, SUMMER
format string No β€” TV, MOVIE, OVA, ONA, SPECIAL, MUSIC
status string No β€” RELEASING, FINISHED, NOT_YET_RELEASED, CANCELLED
sort string No POPULARITY_DESC Sort order
page number No 1 Page number
per_page number No 20 Results per page

Example of request

curl "https://mirurotvapi.vercel.app/api/filter?genre=Action&year=2024&season=WINTER&per_page=3"
import axios from "axios";
const resp = await axios.get("https://mirurotvapi.vercel.app/api/filter", {
  params: { genre: "Action", year: 2024, season: "WINTER", per_page: 3 }
});
console.log(resp.data);

Sample Response

{
  "success": true,
  "results": {
    "page": 1,
    "perPage": 3,
    "total": 5000,
    "hasNextPage": true,
    "results": [
      {
        "id": 21,
        "title": { "romaji": "ONE PIECE", "english": "One Piece" },
        "coverImage": { "large": "https://..." },
        "format": "TV",
        "status": "RELEASING",
        "averageScore": 85
      }
    ]
  }
}

πŸ“ˆ GET Trending

Endpoint

/trending

Parameters

Parameter Type Mandatory Default Description
per_page number No 20 Results per page

Example of request

curl "https://mirurotvapi.vercel.app/api/trending?per_page=3"
import axios from "axios";
const resp = await axios.get("https://mirurotvapi.vercel.app/api/trending", {
  params: { per_page: 3 }
});
console.log(resp.data);

Sample Response

{
  "success": true,
  "results": {
    "page": 1,
    "perPage": 3,
    "total": 5000,
    "hasNextPage": true,
    "results": [
      {
        "id": 21,
        "title": { "romaji": "ONE PIECE", "english": "One Piece" },
        "coverImage": { "large": "https://..." },
        "format": "TV",
        "status": "RELEASING",
        "averageScore": 85
      }
    ]
  }
}

πŸ† GET Popular

Endpoint

/popular

Parameters

Parameter Type Mandatory Default Description
per_page number No 20 Results per page

Example of request

curl "https://mirurotvapi.vercel.app/api/popular?per_page=3"
import axios from "axios";
const resp = await axios.get("https://mirurotvapi.vercel.app/api/popular", {
  params: { per_page: 3 }
});
console.log(resp.data);

πŸ“… GET Upcoming

Endpoint

/upcoming

Parameters

Parameter Type Mandatory Default Description
per_page number No 20 Results per page

Example of request

curl "https://mirurotvapi.vercel.app/api/upcoming?per_page=3"
import axios from "axios";
const resp = await axios.get("https://mirurotvapi.vercel.app/api/upcoming", {
  params: { per_page: 3 }
});
console.log(resp.data);

πŸ†• GET Recent

Endpoint

/recent

Parameters

Parameter Type Mandatory Default Description
per_page number No 20 Results per page

Example of request

curl "https://mirurotvapi.vercel.app/api/recent?per_page=3"
import axios from "axios";
const resp = await axios.get("https://mirurotvapi.vercel.app/api/recent", {
  params: { per_page: 3 }
});
console.log(resp.data);

⭐ GET Spotlight

Endpoint

/spotlight

Parameters

No parameters required.

Example of request

curl "https://mirurotvapi.vercel.app/api/spotlight"
import axios from "axios";
const resp = await axios.get("https://mirurotvapi.vercel.app/api/spotlight");
console.log(resp.data);

Sample Response

{
  "success": true,
  "results": [
    {
      "id": 21,
      "title": { "romaji": "ONE PIECE", "english": "One Piece" },
      "coverImage": { "large": "https://..." },
      "bannerImage": "https://...",
      "format": "TV",
      "episodes": null,
      "status": "RELEASING",
      "averageScore": 85,
      "genres": ["Action","Adventure","Comedy","Fantasy"],
      "description": "Gol D. Roger was known as the Pirate King..."
    }
  ]
}

πŸ“… GET Schedule

Endpoint

/schedule

Parameters

Parameter Type Mandatory Default Description
date string No today Date in YYYY-MM-DD format

Example of request

curl "https://mirurotvapi.vercel.app/api/schedule?date=2026-06-09"
import axios from "axios";
const resp = await axios.get("https://mirurotvapi.vercel.app/api/schedule", {
  params: { date: "2026-06-09" }
});
console.log(resp.data);

ℹ️ GET Anime Info

Endpoint

/info/:id

Parameters

Parameter Type Mandatory Default Description
id number Yes βœ”οΈ β€” AniList anime ID

Example of request

curl "https://mirurotvapi.vercel.app/api/info/20"
import axios from "axios";
const resp = await axios.get("https://mirurotvapi.vercel.app/api/info/20");
console.log(resp.data);

Sample Response

{
  "success": true,
  "results": {
    "id": 20,
    "idMal": 20,
    "title": { "romaji": "NARUTO", "english": "Naruto", "native": "NARUTO -γƒŠγƒ«γƒˆ-" },
    "description": "Naruto Uzumaki, a hyperactive and knuckle-headed ninja...",
    "coverImage": { "large": "https://s4.anilist.co/file/..." },
    "bannerImage": "https://s4.anilist.co/file/...",
    "format": "TV",
    "season": "FALL",
    "seasonYear": 2002,
    "episodes": 220,
    "duration": 23,
    "status": "FINISHED",
    "averageScore": 80,
    "popularity": 694959,
    "genres": ["Action","Adventure","Comedy","Drama","Fantasy","Supernatural"],
    "studios": [{ "name": "Studio Pierrot", "isAnimationStudio": true }],
    "startDate": { "year": 2002, "month": 10, "day": 3 },
    "endDate": { "year": 2007, "month": 2, "day": 8 }
  }
}

🎭 GET Characters

Endpoint

/anime/:id/characters

Parameters

Parameter Type Mandatory Default Description
id number Yes βœ”οΈ β€” AniList anime ID

Example of request

curl "https://mirurotvapi.vercel.app/api/anime/20/characters"
import axios from "axios";
const resp = await axios.get("https://mirurotvapi.vercel.app/api/anime/20/characters");
console.log(resp.data);

Sample Response

{
  "success": true,
  "results": {
    "edges": [
      {
        "role": "MAIN",
        "node": {
          "id": 17,
          "name": { "full": "Naruto Uzumaki", "native": "γ†γšγΎγγƒŠγƒ«γƒˆ" },
          "image": { "large": "https://s4.anilist.co/file/..." }
        },
        "voiceActors": [
          {
            "id": 95015,
            "name": { "full": "Junko Takeuchi", "native": "竹内順子" },
            "languageV2": "Japanese"
          }
        ]
      }
    ]
  }
}

πŸ”— GET Relations

Endpoint

/anime/:id/relations

Parameters

Parameter Type Mandatory Default Description
id number Yes βœ”οΈ β€” AniList anime ID

Example of request

curl "https://mirurotvapi.vercel.app/api/anime/20/relations"
import axios from "axios";
const resp = await axios.get("https://mirurotvapi.vercel.app/api/anime/20/relations");
console.log(resp.data);

πŸ’‘ GET Recommendations

Endpoint

/anime/:id/recommendations

Parameters

Parameter Type Mandatory Default Description
id number Yes βœ”οΈ β€” AniList anime ID

Example of request

curl "https://mirurotvapi.vercel.app/api/anime/20/recommendations"
import axios from "axios";
const resp = await axios.get("https://mirurotvapi.vercel.app/api/anime/20/recommendations");
console.log(resp.data);

πŸ“Ί GET Episodes

Endpoint

/episodes/:id

Parameters

Parameter Type Mandatory Default Description
id number Yes βœ”οΈ β€” AniList anime ID

Example of request

curl "https://mirurotvapi.vercel.app/api/episodes/20"
import axios from "axios";
const resp = await axios.get("https://mirurotvapi.vercel.app/api/episodes/20");
console.log(resp.data);

Sample Response

{
  "success": true,
  "results": {
    "providers": {
      "kiwi": {
        "meta": { "id": "1571", "title": "Naruto", "type": "TV" },
        "episodes": {
          "sub": [
            {
              "id": "watch/kiwi/20/sub/anikoto-1",
              "number": 1,
              "title": "Enter: Naruto Uzumaki!",
              "image": "https://image.tmdb.org/t/p/original/...",
              "airDate": "2002-10-03",
              "audio": "sub",
              "filler": false,
              "fillerType": "manga_canon"
            }
          ]
        }
      }
    }
  }
}

πŸ“‘ GET Watch (Streaming Sources)

Endpoint

/watch/:provider/:anilistId/:category/:slug

Parameters

Parameter Type Mandatory Default Description
provider string Yes βœ”οΈ β€” Provider name (kiwi, pewe, etc.)
anilistId number Yes βœ”οΈ β€” AniList anime ID
category string Yes βœ”οΈ β€” sub or dub
slug string Yes βœ”οΈ β€” Episode slug from episodes response

Example of request

curl "https://mirurotvapi.vercel.app/api/watch/kiwi/20/sub/animepahe-1"
import axios from "axios";
const resp = await axios.get("https://mirurotvapi.vercel.app/api/watch/kiwi/20/sub/animepahe-1");
console.log(resp.data);

Sample Response

{
  "success": true,
  "results": {
    "streams": [
      {
        "url": "https://vault-01.uwucdn.top/stream/.../uwu.m3u8",
        "type": "hls",
        "quality": "360p",
        "resolution": { "width": 640, "height": 360 },
        "codec": "h264",
        "audio": "sub",
        "fansub": "df68",
        "isActive": false,
        "referer": "https://kwik.cx/e/..."
      },
      {
        "url": "https://kwik.cx/e/...",
        "type": "embed",
        "quality": "360p",
        "codec": "h264",
        "audio": "sub",
        "fansub": "df68",
        "isActive": false
      }
    ],
    "download": "https://pahe.win/LJmbA"
  }
}

🎬 Streaming Flow

To get a stream URL, follow these 3 steps:

# Step 1: Get episodes (returns provider slugs)
curl "https://mirurotvapi.vercel.app/api/episodes/20"
# => providers.kiwi.episodes.sub[0].id = "watch/kiwi/20/sub/anikoto-1"

# Step 2: Get streaming sources
curl "https://mirurotvapi.vercel.app/api/watch/kiwi/20/sub/animepahe-1"
# => streams[0].url = "https://...m3u8"

# Step 3: Play M3U8 in any HLS player
# Use hls.js, video.js, or native <video> with hls support

πŸ“Ί Sub & Dub

Providers return both sub and dub episode lists:

const eps = await fetch("/api/episodes/20").then(r => r.json());
const providers = eps.results.providers;

// Pick provider
const kiwi = providers.kiwi.episodes;

// Get sub episodes
const subEps = kiwi.sub; // [{ id: "watch/kiwi/20/sub/anikoto-1", ... }]

// Get dub episodes (if available)
const dubEps = kiwi.dub || []; // [{ id: "watch/kiwi/20/dub/...", ... }]

πŸŽ₯ HLS Player Example

<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
<video id="player" controls></video>
<script>
  const video = document.getElementById('player');
  const streamUrl = 'https://...m3u8'; // From /api/watch response
  
  if (Hls.isSupported()) {
    const hls = new Hls();
    hls.loadSource(streamUrl);
    hls.attachMedia(video);
  } else if (video.canPlayType('application/vnd.apple.mpegurl')) {
    video.src = streamUrl; // Native HLS (Safari)
  }
</script>

πŸ“‹ API Response Schema

Success Response

{
  "success": true,
  "results": { ... }
}

Error Response

{
  "success": false,
  "message": "Error description"
}

Anime Item Object

Field Type Description Example
id number AniList ID 20
title object { romaji, english, native } { "romaji": "NARUTO" }
coverImage object { large } { "large": "https://..." }
format string Anime format "TV"
status string Release status "FINISHED"
episodes number Total episodes 220
averageScore number AniList score 80
genres string[] Genre list ["Action","Adventure"]

Episode Object

Field Type Description Example
id string Watch slug "watch/kiwi/20/sub/anikoto-1"
number number Episode number 1
title string Episode title "Enter: Naruto Uzumaki!"
image string Thumbnail URL "https://..."
airDate string Air date "2002-10-03"
audio string sub or dub "sub"
filler boolean Is filler episode false

Stream Object

Field Type Description Example
url string M3U8 or embed URL "https://...m3u8"
type string hls or embed "hls"
quality string Video quality "720p"
resolution object { width, height } { "width": 1280, "height": 720 }
codec string Video codec "h264"
audio string sub or dub "sub"
fansub string Fansub group "df68"
isActive boolean Is active stream false
referer string Referer URL "https://kwik.cx/e/..."

🌐 Deployment

β–² Vercel (Recommended)

Deploy with Vercel

  1. Click the button above (or import manually on vercel.com)
  2. Vercel auto-detects the project β€” no config needed
  3. Your API is live! πŸŽ‰
# Or use Vercel CLI
npx vercel --prod

πŸ–₯️ Standalone Server

# Clone and install
git clone https://github.com/Shineii86/MiruroAPI.git
cd MiruroAPI && npm install

# Start production server
npm start
# β†’ http://localhost:3000

🐳 Docker

# Build
docker build -t miruroapi .

# Run
docker run -p 3000:3000 miruroapi

πŸ“œ Available Scripts

Command Description Details
npm run dev πŸ”₯ Start development server Runs on localhost:3000
npm start πŸš€ Start production server node server.js

⚑ Performance

Metric Value
⚑ Cold start ~500ms
πŸ”„ Warm response ~50-200ms
πŸ’Ύ Cache hit ~10ms
πŸ’Ύ Cache TTL 1-5 minutes
⏱️ Rate limit 100 req/min/IP
πŸ’» Memory usage ~15MB
πŸ“¦ Cache max size 100 entries

Optimization Features

  • πŸ’Ύ In-memory cache β€” Map-based with TTL expiration
  • ⚑ Pipe decoding β€” Efficient base64url + gzip decompression
  • 🎯 Selective fetching β€” Only AniList GraphQL or Miruro pipe
  • πŸ“ Minimal deps β€” Only 4 production dependencies
  • πŸ”„ Graceful fallback β€” Empty arrays on error, never crashes

πŸ“ Changelog Highlights

Version Date Key Changes
1.2.0 2026-06-09 Critical response format fix, full endpoint diagnostic, 18/18 passing
1.1.0 2026-06-09 Swagger UI docs, OpenAPI spec, mappings field, Docker, landing page
1.0.0 2026-06-09 Initial release β€” 16 endpoints, AniList GraphQL + Miruro pipe, caching

πŸ“ See CHANGELOG.md for the full version history.


πŸ”§ Troubleshooting

Problem Cause Solution
❌ npm install fails Node.js version too old Upgrade to Node.js 20+ (node -v)
❌ CORS errors Frontend domain blocked CORS is * β€” check browser extension
❌ 404 on API routes Wrong URL format Use /api/ prefix, not just /
❌ Empty episodes Provider not available Check which providers return data for the anime
❌ Deploy fails on Vercel Build error Check node server.js locally first
❌ Slow first request Serverless cold start Normal β€” first request after idle takes ~500ms
❌ Rate limited Too many requests Cache reduces this β€” wait for TTL expiry

πŸ› Debug Mode

# Run with verbose logging
NODE_ENV=development npm run dev

# Test specific endpoint
curl http://localhost:3000/api/health
curl http://localhost:3000/api/search?query=naruto
curl http://localhost:3000/api/episodes/20

❓ FAQ

πŸ” How do I search for anime?
Use /api/search?query=your+search. Results include title, cover, format, status, episodes, and score. For autocomplete suggestions, use /api/suggestions?query=your+search which returns fast suggestions.
πŸ“Ί How do I get episode lists?
Use /api/episodes/:id where :id is the AniList anime ID (e.g., 20 for Naruto). The response includes all providers with sub/dub episode lists.
🎯 How does filtering work?
Use /api/filter with query params. Combine genre, year, season, format, status, and sort for advanced filtering. All params are optional.
πŸ“‘ Can I use this in my frontend app?
Yes! CORS is enabled for all origins (*). Just make fetch requests to the API endpoints. No API key needed. Example: fetch('https://mirurotvapi.vercel.app/api/search?query=naruto')
πŸ”„ How often does the data refresh?
The cache TTL is 1-5 minutes depending on the endpoint. After that, the next request triggers a fresh fetch from AniList/Miruro.
🌐 Can I self-host this?
Yes! Use npm start to run the Express server on any VPS, Docker container, or PaaS. The Vercel serverless functions are optional β€” server.js handles everything.
🎬 Which streaming providers are available?
12 providers: kiwi, pewe, bee, bonk, bun, ally, nun, twin, cog, moo, hop, telli. Not all anime are available on every provider.

πŸ—ΊοΈ Roadmap

🎯 Planned Features

  • πŸ” API key authentication β€” Per-user rate limits
  • πŸ“Š Analytics endpoint β€” Usage statistics
  • πŸŒ™ Dark/light mode β€” Theme toggle for landing page
  • πŸ“± PWA support β€” Install as app on mobile
  • πŸ”” Webhook notifications β€” Push new episodes to Discord
  • πŸ—„οΈ Redis cache β€” Persistent caching for serverless
  • 🌐 Multi-language β€” Sub/dub language metadata
  • πŸ“¦ NPM package β€” Client SDK for easy integration

βœ… Completed

  • 🎬 18 API endpoints covering all data
  • πŸ” Full-text search with pagination
  • πŸ’‘ Search suggestions for autocomplete
  • 🎯 Advanced filtering (genre, year, season, format, sort)
  • 🎭 Characters + voice actors from AniList
  • πŸ”— Relations and recommendations
  • ⏭️ Skip timestamps (OP/ED)
  • πŸ“‘ 12 streaming providers with M3U8 URLs
  • πŸ”„ Smart caching with configurable TTL
  • πŸš€ One-click Vercel deployment
  • 🐳 Docker support
  • πŸ“˜ Swagger UI interactive docs
  • πŸ“– Comprehensive documentation with real API data

🀝 Contributing

Contributions are welcome and appreciated! Here's how you can help:

πŸ› Report Bugs

Found something broken?

Open an Issue

πŸ’‘ Suggest Features

Have an idea?

Start a Discussion

πŸ”€ Submit PRs

Ready to contribute code?

Fork & Submit

πŸ”„ How to Contribute

# 1️⃣ Fork the repository
# Click the "Fork" button on GitHub

# 2️⃣ Clone your fork
git clone https://github.com/YOUR_USERNAME/MiruroAPI.git
cd MiruroAPI

# 3️⃣ Create a feature branch
git checkout -b feature/amazing-feature

# 4️⃣ Make your changes
# Edit files, add features, fix bugs...

# 5️⃣ Commit your changes
git commit -m 'feat: add amazing feature'

# 6️⃣ Push to your fork
git push origin feature/amazing-feature

# 7️⃣ Open a Pull Request
# Go to GitHub and create a PR

πŸ“‹ Guidelines

  • βœ… Follow the existing code style and documentation conventions
  • βœ… Write meaningful commit messages (use conventional commits)
  • βœ… Update CHANGELOG.md with your changes
  • βœ… Keep PRs focused β€” one feature or fix per PR
  • βœ… Add JSDoc comments for new functions
  • ❎ Don't commit node_modules or cache files
  • ❎ Don't add unrelated changes to a single PR

πŸ™ Acknowledgements

🎬 Data Sources

Source About
AniList Anime metadata API (GraphQL)
Miruro Anime streaming site β€” source for episodes and streaming
Miruro TO Mirror domain
Miruro BZ Mirror domain
Miruro RU Mirror domain

πŸ› οΈ Technologies

  • Express β€” Fast, unopinionated web framework
  • AniList GraphQL β€” Rich anime metadata
  • Axios β€” Promise-based HTTP client
  • Vercel β€” Serverless deployment platform

πŸ“ Resources


πŸ“„ License

License: MIT

This project is licensed under the MIT License.

Free to use, modify, and distribute β€” see the LICENSE file for details.


πŸ‘€ Author

Shinei Nouzen
Full-Stack Developer & Anime Enthusiast

GitHub Telegram Instagram Email


⭐ Star History

Star History Chart

⭐ If you found this project useful, please consider giving it a star!


Made With ❀️ For The Anime Community

Β© Shinei Nouzen. All Rights Reserved.