diff --git a/README.md b/README.md index 0633430..b74a106 100644 --- a/README.md +++ b/README.md @@ -1,84 +1,1113 @@ -# MiruroAPI +
+ + -Free RESTful API for anime streaming data. Powered by AniList GraphQL and Miruro streaming providers. +
-## Live +

+ Stars + Forks + Issues + Pull Requests + Last Commit + License +

-- **API**: `https://mirurotvapi.vercel.app` -- **Docs**: `https://mirurotvapi.vercel.app/docs` (Swagger UI) -- **OpenAPI**: `https://mirurotvapi.vercel.app/openapi.json` -- **GitHub**: `https://github.com/Shineii86/MiruroAPI` +

+ Node.js + Express + AniList GraphQL + Vercel + License + Version + Endpoints + Providers +

+ +

+ Free 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 +

+ +--- + +> ## Disclaimer +> +> 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](#-overview) +- [Features](#-features) +- [Data Sources](#-data-sources) +- [Tech Stack](#-tech-stack) +- [Architecture](#-architecture) +- [Project Structure](#-project-structure) +- [Quick Start](#-quick-start) +- [Configuration](#-configuration) +- [API Endpoints](#-api-endpoints) +- [Streaming Flow](#-streaming-flow) +- [Response Schema](#-response-schema) +- [Deployment](#-deployment) +- [Performance](#-performance) +- [FAQ](#-faq) +- [Contributing](#-contributing) +- [License](#-license) +- [Author](#-author) + +--- + +## 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 +- **AniList GraphQL** — Rich metadata: scores, characters, relations, recommendations +- **12 Streaming Providers** — kiwi, pewe, bee, bonk, bun, ally, nun, twin, cog, moo, hop, telli +- **M3U8 URLs** — Direct streaming links with resolution, codec, fansub info +- **Skip Timestamps** — OP/ED skip data for supported anime +- **Smart Caching** — In-memory Map with TTL reduces API load +- **CORS Enabled** — Works from any frontend, no proxy needed +- **Swagger UI** — Interactive API documentation at `/docs` +- **Docker Ready** — One-command containerized deployment + +### How It Works + +```mermaid +flowchart TD + A["Client Request
(Browser / App / curl)"] --> B["Express Server
CORS - Security Headers"] + B --> C{"Cache Check
(In-Memory Map)"} + C -- HIT --> D["Return Cached
~50ms"] + C -- MISS --> E{"Which Source?"} + + E -- Metadata --> F["AniList GraphQL
graphql.anilist.co"] + E -- Streaming --> G["Miruro Pipe
miruro.tv/api/secure/pipe"] + + F --> H["AniList Response
JSON"] + G --> I["Pipe Response
base64url + gzip"] + + H --> J["Cache + Respond"] + I --> J + + style A fill:#0f172a,stroke:#38bdf8,color:#e2e8f0 + style B fill:#0f172a,stroke:#818cf8,color:#e2e8f0 + style C fill:#0f172a,stroke:#f43f5e,color:#e2e8f0 + style D fill:#0f172a,stroke:#22c55e,color:#e2e8f0 + style E fill:#0f172a,stroke:#a855f7,color:#e2e8f0 + style F fill:#0f172a,stroke:#02a6e4,color:#e2e8f0 + style G fill:#0f172a,stroke:#eab308,color:#e2e8f0 + style H fill:#0f172a,stroke:#06b6d4,color:#e2e8f0 + style I fill:#0f172a,stroke:#eab308,color:#e2e8f0 + style J fill:#0f172a,stroke:#22c55e,color:#e2e8f0 +``` + +--- ## Features -- 16 API endpoints -- AniList GraphQL for metadata (search, trending, info, filter, schedule) -- 12 streaming providers (kiwi, pewe, bee, bonk, bun, ally, nun, twin, cog, moo, hop, telli) -- M3U8 streaming URLs with subtitles and skip timestamps -- In-memory caching with TTL -- CORS enabled -- Swagger UI interactive docs -- Docker support -- Health endpoint + + + + + + + + + +
-## Endpoints +### 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) -### Search & Discovery + -| Endpoint | Description | -|---|---| -| `GET /api/search?query=naruto` | Search anime by name | -| `GET /api/suggestions?query=naruto` | Autocomplete suggestions | -| `GET /api/filter?genre=Action` | Advanced filter | +### 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 -### Collections - -| Endpoint | Description | -|---|---| -| `GET /api/trending` | Trending anime | -| `GET /api/popular` | Most popular anime | -| `GET /api/upcoming` | Upcoming anime | -| `GET /api/recent` | Currently airing anime | -| `GET /api/spotlight` | Spotlight/featured anime | -| `GET /api/schedule` | Airing schedule | - -### Anime Details - -| Endpoint | Description | -|---|---| -| `GET /api/info/:id` | Full anime info by AniList ID | -| `GET /api/anime/:id/characters` | Characters with voice actors | -| `GET /api/anime/:id/relations` | Related anime | -| `GET /api/anime/:id/recommendations` | Recommendations | +
### 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 -| Endpoint | Description | -|---|---| -| `GET /api/episodes/:id` | Episode list from all providers | -| `GET /api/sources?episodeId=...&provider=...&anilistId=...` | Streaming sources (detailed) | -| `GET /api/watch/:provider/:anilistId/:category/:slug` | Streaming sources (simple) | + + +### 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 | Done | +| AniList GraphQL | Rich metadata from AniList | Done | +| 12 Streaming Providers | M3U8 streaming sources | Done | +| Full-Text Search | Keyword search with pagination | Done | +| Autocomplete Suggestions | Fast search suggestions | Done | +| Advanced Filtering | Genre, year, season, format, sort | Done | +| Characters + Voice Actors | Full character data from AniList | Done | +| Relations & Recommendations | Related anime discovery | Done | +| Skip Timestamps | OP/ED skip data | Done | +| Smart Caching | In-memory Map with TTL | Done | +| Swagger UI Docs | Interactive API documentation | Done | +| Docker Support | Containerized deployment | Done | + +--- + +## 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 | +|:---|:---|:---| +| [Node.js](https://nodejs.org/) | JavaScript runtime | >= 20 | +| [Express](https://expressjs.com/) | HTTP server framework | 4.21 | +| [AniList GraphQL](https://anilist.gitbook.io/anilist-apiv2-docs/) | Anime metadata API | — | +| [Axios](https://axios-http.com/) | HTTP client | 1.8 | +| [Vercel Functions](https://vercel.com/docs/functions) | Serverless deployment | — | +| [cors](https://github.com/expressjs/cors) | CORS middleware | 2.8 | +| [dotenv](https://github.com/motdotla/dotenv) | Environment variables | 16.4 | + +### Dependencies + +```json +{ + "express": "^4.21.0", + "axios": "^1.8.0", + "cors": "^2.8.5", + "dotenv": "^16.4.0" +} +``` + +--- + +## 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 + +| Cache Type | TTL | Max Size | Eviction | +|:---|:---|:---|:---| +| Search results | 1 min | 100 entries | FIFO | +| Collection lists | 2-5 min | 100 entries | FIFO | +| Episode lists | 2 min | 100 entries | FIFO | +| Streaming sources | 1 min | 100 entries | FIFO | + +> 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 +│ ├── docs.html # Swagger UI 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/ +│ ├── helpers/ +│ │ ├── anilist.js # AniList GraphQL integration +│ │ ├── pipe.js # Miruro pipe integration +│ │ └── cache.js # In-memory cache with TTL +│ └── routes/ +│ └── apiRoutes.js # All 18 route definitions +│ +├── server.js # Express server entry point +├── package.json # Dependencies & scripts +├── vercel.json # Vercel routing config +├── Dockerfile # Docker support +├── 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 | + +### Installation + +```bash +# 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](http://localhost:3000) in your browser. + +### Production + +```bash +npm start +``` + +### Alternative Package Managers + +```bash +# yarn +yarn install && yarn dev + +# pnpm +pnpm install && pnpm dev + +# bun +bun install && bun dev +``` + +--- + +## Configuration + +### Environment Variables + +| Variable | Default | Description | +|:---|:---|:---| +| `PORT` | `3000` | Server port | +| `ALLOWED_ORIGINS` | `*` | Comma-separated allowed origins | + +### Vercel Configuration + +The `vercel.json` 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: + +```json +{ + "success": true, + "results": { ... } +} +``` + +--- + +### Health Check + +```bash +GET /api/health +``` + +```bash +curl "https://mirurotvapi.vercel.app/api/health" +``` + +
+Response + +```json +{ + "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"] + } +} +``` +
+ +--- + +### Search + +```bash +GET /api/search?query=naruto&per_page=2 +``` + +| Param | Type | Default | Description | +|:---|:---|:---|:---| +| `query` | string | **required** | Search keyword | +| `page` | number | 1 | Page number | +| `per_page` | number | 20 | Results per page | + +```bash +curl "https://mirurotvapi.vercel.app/api/search?query=naruto&per_page=2" +``` + +```javascript +const res = await fetch("https://mirurotvapi.vercel.app/api/search?query=naruto&per_page=2"); +const data = await res.json(); +console.log(data.results); // { page, perPage, total, hasNextPage, results: [...] } +``` + +
+Response + +```json +{ + "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"] + } + ] + } +} +``` +
+ +--- + +### Suggestions + +```bash +GET /api/suggestions?query=naruto +``` + +| Param | Type | Default | Description | +|:---|:---|:---|:---| +| `query` | string | **required** | Search keyword | + +```bash +curl "https://mirurotvapi.vercel.app/api/suggestions?query=naruto" +``` + +
+Response + +```json +{ + "success": true, + "results": [ + { "id": 20, "title": "Naruto", "title_romaji": "NARUTO", "poster": "...", "format": "TV", "status": "FINISHED", "year": 2002, "episodes": 220 }, + { "id": 1735, "title": "Naruto: Shippuden", "title_romaji": "NARUTO: Shippuuden", "poster": "...", "format": "TV", "status": "FINISHED", "year": 2007, "episodes": 500 } + ] +} +``` +
+ +--- + +### Filter + +```bash +GET /api/filter?genre=Action&sort=POPULARITY_DESC&per_page=1 +``` + +| Param | Type | Default | Description | +|:---|:---|:---|:---| +| `genre` | string | — | Genre name (e.g. "Action") | +| `tag` | string | — | Tag name | +| `year` | number | — | Release year | +| `season` | string | — | FALL, WINTER, SPRING, SUMMER | +| `format` | string | — | TV, MOVIE, OVA, ONA, SPECIAL, MUSIC | +| `status` | string | — | RELEASING, FINISHED, NOT_YET_RELEASED, CANCELLED | +| `sort` | string | POPULARITY_DESC | Sort order | +| `page` | number | 1 | Page number | +| `per_page` | number | 20 | Results per page | + +```bash +curl "https://mirurotvapi.vercel.app/api/filter?genre=Action&year=2024&season=WINTER&per_page=3" +``` + +
+Response + +```json +{ + "success": true, + "results": { + "page": 1, + "perPage": 3, + "total": 5000, + "hasNextPage": true, + "results": [ ... ] + } +} +``` +
+ +--- + +### Trending + +```bash +GET /api/trending?per_page=10 +``` + +| Param | Type | Default | Description | +|:---|:---|:---|:---| +| `per_page` | number | 20 | Results per page | + +```bash +curl "https://mirurotvapi.vercel.app/api/trending?per_page=3" +``` + +--- + +### Popular + +```bash +GET /api/popular?per_page=10 +``` + +--- + +### Upcoming + +```bash +GET /api/upcoming?per_page=10 +``` + +--- + +### Recent + +```bash +GET /api/recent?per_page=10 +``` + +--- + +### Spotlight + +```bash +GET /api/spotlight +``` + +Returns featured/spotlight anime for the hero carousel. + +
+Response + +```json +{ + "success": true, + "results": [ + { + "id": 21, + "title": { "romaji": "ONE PIECE", "english": "One Piece" }, + "coverImage": { "large": "..." }, + "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..." + } + ] +} +``` +
+ +--- + +### Schedule + +```bash +GET /api/schedule?date=2026-06-09 +``` + +| Param | Type | Default | Description | +|:---|:---|:---|:---| +| `date` | string | today | Date in YYYY-MM-DD format | + +--- + +### Anime Info + +```bash +GET /api/info/:id +``` + +| Param | Type | Default | Description | +|:---|:---|:---|:---| +| `id` | number | **required** | AniList anime ID | + +```bash +curl "https://mirurotvapi.vercel.app/api/info/20" +``` + +```javascript +const res = await fetch("https://mirurotvapi.vercel.app/api/info/20"); +const data = await res.json(); +console.log(data.results.title); // { romaji: "NARUTO", english: "Naruto" } +``` + +
+Response + +```json +{ + "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 } + } +} +``` +
+ +--- + +### Characters + +```bash +GET /api/anime/:id/characters +``` + +| Param | Type | Default | Description | +|:---|:---|:---|:---| +| `id` | number | **required** | AniList anime ID | + +```bash +curl "https://mirurotvapi.vercel.app/api/anime/20/characters" +``` + +
+Response + +```json +{ + "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" + } + ] + } + ] + } +} +``` +
+ +--- + +### Relations + +```bash +GET /api/anime/:id/relations +``` + +Returns related anime (sequels, prequels, side stories, etc.). + +--- + +### Recommendations + +```bash +GET /api/anime/:id/recommendations +``` + +Returns recommended anime based on the given ID. + +--- + +### Episodes + +```bash +GET /api/episodes/:id +``` + +| Param | Type | Default | Description | +|:---|:---|:---|:---| +| `id` | number | **required** | AniList anime ID | + +```bash +curl "https://mirurotvapi.vercel.app/api/episodes/20" +``` + +
+Response + +```json +{ + "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" + } + ] + } + } + } + } +} +``` +
+ +--- + +### Watch (Streaming Sources) + +```bash +GET /api/watch/:provider/:anilistId/:category/:slug +``` + +| Param | Type | Default | Description | +|:---|:---|:---|:---| +| `provider` | string | **required** | Provider name (kiwi, pewe, etc.) | +| `anilistId` | number | **required** | AniList anime ID | +| `category` | string | **required** | sub or dub | +| `slug` | string | **required** | Episode slug from episodes response | + +```bash +curl "https://mirurotvapi.vercel.app/api/watch/kiwi/20/sub/animepahe-1" +``` + +```javascript +const res = await fetch("https://mirurotvapi.vercel.app/api/watch/kiwi/20/sub/animepahe-1"); +const data = await res.json(); +const streams = data.results.streams; +// streams[0].url = "https://vault-01.uwucdn.top/stream/.../uwu.m3u8" +// streams[0].quality = "360p" +// streams[0].type = "hls" +``` + +
+Response + +```json +{ + "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 -1. `GET /api/episodes/:anilistId` — get episode list with provider IDs -2. `GET /api/watch/:provider/:anilistId/:category/:slug` — get M3U8 URL -3. Play M3U8 in any HLS player - -## Setup +To get a stream URL, follow these 3 steps: ```bash +# 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