diff --git a/README.md b/README.md index c5e2748..fa709e6 100644 --- a/README.md +++ b/README.md @@ -19,8 +19,8 @@ AniList GraphQL Vercel License - Version - Endpoints + Version + Endpoints Providers

@@ -44,7 +44,7 @@ > [!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. +> 3. All anime data, images, and content belong to their respective owners (AniList, Miruro). This project is not affiliated with Miruro. --- @@ -84,7 +84,7 @@ ### Why MiruroAPI? -- ๐ŸŽฌ **44 Endpoints** โ€” Complete anime data coverage +- ๐ŸŽฌ **46 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 @@ -98,6 +98,15 @@ - ๐Ÿ”’ **CORS Enabled** โ€” Works from any frontend, no proxy needed - ๐Ÿš€ **Zero-Config Deploy** โ€” One click to Vercel, or run standalone with Express +### ๐Ÿ”„ Self-Healing System (v2.3.0) + +When Cloudflare blocks streaming requests, the API automatically tries fallback methods: +- **Direct** โ†’ Mirror rotation across 4 domains +- **ScraperAPI** โ†’ Free proxy bypass (1K req/month) +- **FlareSolverr** โ†’ Self-hosted browser proxy + +Zero-config: works out of the box. Add `SCRAPER_API_KEY` env var for automatic Cloudflare bypass. + ### How It Works ```mermaid @@ -108,7 +117,7 @@ flowchart TD C -- MISS --> E{"๐Ÿ” Which Source?"} E -- Metadata --> F["๐Ÿ“ก AniList GraphQL
graphql.anilist.co"] - E -- Streaming --> G["๐Ÿ“บ Miruro Pipe
miruro.tv/api/secure/pipe"] + E -- Streaming --> G["๐Ÿ“บ Miruro Pipe
miruro.{to,ru,bz,tv}/api/secure/pipe"] F --> H["AniList Response
JSON"] G --> I["Pipe Response
base64url + gzip"] @@ -222,10 +231,10 @@ flowchart TD | Source | Domain | Data | |:---|:---|:---| -| ๐Ÿ“บ **Miruro** | `miruro.tv` | Episodes, streaming sources (M3U8 URLs) | -| ๐Ÿ“บ **Miruro** | `miruro.to` | Mirror domain | -| ๐Ÿ“บ **Miruro** | `miruro.bz` | Mirror domain | +| ๐Ÿ“บ **Miruro** | `miruro.to` | Episodes, streaming sources (M3U8 URLs) | | ๐Ÿ“บ **Miruro** | `miruro.ru` | Mirror domain | +| ๐Ÿ“บ **Miruro** | `miruro.bz` | Mirror domain | +| ๐Ÿ“บ **Miruro** | `miruro.tv` | Mirror domain | ### ๐ŸŽฌ Streaming Providers @@ -494,7 +503,7 @@ console.log(resp.data); "success": true, "results": { "status": "healthy", - "version": "2.1.4", + "version": "2.3.0", "uptime": "0h 0m 34s", "uptimeSeconds": 34, "timestamp": "2026-06-09T09:55:00.884Z", @@ -1412,6 +1421,7 @@ docker run -p 3000:3000 miruroapi | Version | Date | Key Changes | |:---|:---|:---| +| **2.3.0** | 2026-07-02 | Self-healing fallback system โ€” multi-method pipe recovery, /api/pipe-health endpoint, ScraperAPI + FlareSolverr support | | **2.1.4** | 2026-06-25 | Security hardening โ€” XOR keys to env vars, CORS restriction, input sanitization, bug fixes (multi-search, deepTranslate, getBestStream) | | **2.1.3** | 2026-06-25 | Diagnostic sweep โ€” tags, random, character/staff 404 fixes, pipe retry with backoff, security headers | | **2.1.2** | 2026-06-25 | Streaming architecture โ€” pru proxy decode, CDN CORS proxy, raw stream URLs | @@ -1607,7 +1617,7 @@ git push origin feature/amazing-feature | Source | About | |:---|:---| | [AniList](https://anilist.co) | Anime metadata API (GraphQL) | -| [Miruro](https://miruro.tv) | Anime streaming site โ€” source for episodes and streaming | +| [Miruro](https://www.miruro.to) | Anime streaming site โ€” source for episodes and streaming | | [Miruro TO](https://miruro.to) | Mirror domain | | [Miruro BZ](https://miruro.bz) | Mirror domain | | [Miruro RU](https://miruro.ru) | Mirror domain | diff --git a/api/proxy.js b/api/proxy.js index f99ba82..75e2299 100644 --- a/api/proxy.js +++ b/api/proxy.js @@ -120,7 +120,7 @@ const decodePruUrl = (pruUrl) => { * @returns {string} Full PRU proxy URL * * @example - * const pruUrl = encodeForPru("https://cdn.example.com/v.m3u8", "https://miruro.tv/"); + * const pruUrl = encodeForPru("https://cdn.example.com/v.m3u8", "https://miruro.to/"); */ const encodeForPru = (rawUrl, referer) => { const urlEnc = base64urlXor(rawUrl); @@ -189,7 +189,7 @@ const rewriteM3U8 = (m3u8, targetReferer) => { * @query {string} referer - Optional referer header for the target * * @example - * GET /api/proxy?url=https://example.com/video.m3u8&referer=https://miruro.tv/ + * GET /api/proxy?url=https://example.com/video.m3u8&referer=https://miruro.to/ */ module.exports = async function handler(req, res) { // NOTE: CORS headers for browser requests diff --git a/docs/architecture.md b/docs/architecture.md index 043e836..128ed47 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -62,7 +62,7 @@ MiruroAPI/ | Runtime | Node.js | | Framework | Express.js | | Metadata | AniList GraphQL (`graphql.anilist.co`) | -| Streaming | Miruro pipe (`miruro.tv/api/secure/pipe`) | +| Streaming | Miruro pipe (`miruro.{to,ru,bz,tv}/api/secure/pipe`) | | Deployment | Vercel (Serverless) | | Caching | In-memory Map with 1-5 min TTL | | Static Files | Express static middleware | @@ -120,11 +120,21 @@ Play M3U8 in HLS player (hls.js, video.js, native) ### Miruro Pipe -- **Endpoint:** `https://miruro.tv/api/secure/pipe` +- **Endpoint:** `https://miruro.{to,ru}/api/secure/pipe` - **Data:** Episodes, streaming sources (M3U8 URLs) - **Encoding:** Base64url + gzip compressed request/response - **Providers:** kiwi, pewe, bee, bonk, bun, ally, nun, twin, cog, moo, hop, telli +## Self-Healing Fallback System (v2.3.0) + +When Cloudflare blocks streaming requests, the API automatically tries fallback methods in order: + +1. **Direct** โ†’ Mirror rotation across 4 domains (miruro.to, miruro.ru, miruro.bz, miruro.tv) +2. **ScraperAPI** โ†’ Free proxy bypass via ScraperAPI (1K req/month, requires `SCRAPER_API_KEY`) +3. **FlareSolverr** โ†’ Self-hosted browser proxy for full Cloudflare bypass + +The system tracks success/failure rates per method and auto-rotates to the most reliable option. Check status via `/api/pipe-health`. + ## Vercel Configuration ```json diff --git a/docs/endpoints.md b/docs/endpoints.md index 14f3dfb..c76c048 100644 --- a/docs/endpoints.md +++ b/docs/endpoints.md @@ -1,6 +1,6 @@ # API Endpoints Reference -Complete documentation for all 35 MiruroAPI v2.0.1 endpoints. +Complete documentation for all 45 MiruroAPI v2.3.0 endpoints. --- @@ -591,12 +591,12 @@ API health status, version, uptime, memory, cache stats. "success": true, "results": { "status": "healthy", - "version": "2.0.0", + "version": "2.3.0", "uptime": "0h 0m 34s", "node": "v24.14.1", "memory": { "used": "13MB", "total": "15MB", "rss": "25MB" }, "cache": { "size": 12, "maxSize": 100 }, - "endpoints": 35, + "endpoints": 45, "providers": ["kiwi","pewe","bee","bonk","bun","ally","nun","twin","cog","moo","hop","telli"] } } @@ -604,6 +604,16 @@ API health status, version, uptime, memory, cache stats. --- +## Pipe Health + +``` +GET /api/pipe-health +``` + +Returns the status of the self-healing fallback system โ€” mirror availability, ScraperAPI/FlareSolverr status, and last successful method. + +--- + ## Stats ``` diff --git a/docs/index.md b/docs/index.md index 6341c4a..282f917 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,6 +1,6 @@ # MiruroAPI Documentation -> Free REST API for anime streaming data. 18 endpoints, 12 providers, M3U8 URLs. No API key required. +> Free REST API for anime streaming data. 46 endpoints, 12 providers, M3U8 URLs. No API key required. ## Overview @@ -48,7 +48,7 @@ curl "https://mirurotvapi.vercel.app/api/episodes/20" ## Features -- **18 Endpoints** โ€” Search, info, episodes, streaming, characters, relations, and more +- **46 Endpoints** โ€” Search, info, episodes, streaming, characters, relations, and more - **12 Streaming Providers** โ€” M3U8 URLs with resolution, codec, fansub info - **No API Key** โ€” Just make requests, no registration needed - **In-Memory Cache** โ€” 1-5 minute TTL for fast responses diff --git a/docs/streaming.md b/docs/streaming.md index 7c9c134..80cf91b 100644 --- a/docs/streaming.md +++ b/docs/streaming.md @@ -234,5 +234,14 @@ const dubEps = kiwi.dub; // [{ id: "watch/kiwi/20/dub/...", ... }] |-------|----------| | "No episodes found" | Check the AniList ID is correct (use `/api/search` first) | | "No providers" | The anime may not be available on any provider | -| Stream URL 403 | Some servers require specific referrer headers | +| Stream URL 403 | Some servers require specific referrer headers โ€” the self-healing system auto-rotates mirrors | | CORS error | Use a proxy or access from server-side | + +## Self-Healing Fallback (v2.3.0) + +When Cloudflare blocks streaming requests, the API automatically tries fallback methods: +- **Direct** โ†’ Mirror rotation across 4 domains (miruro.to, miruro.ru, miruro.bz, miruro.tv) +- **ScraperAPI** โ†’ Free proxy bypass (1K req/month, set `SCRAPER_API_KEY` env var) +- **FlareSolverr** โ†’ Self-hosted browser proxy for full Cloudflare bypass + +Check the fallback system status: `GET /api/pipe-health` diff --git a/public/docs.html b/public/docs.html index af6ed0f..2112e69 100644 --- a/public/docs.html +++ b/public/docs.html @@ -9,14 +9,14 @@ - + - + diff --git a/public/index.html b/public/index.html index fe6dffb..dcf5b1b 100644 --- a/public/index.html +++ b/public/index.html @@ -10,7 +10,7 @@ - + @@ -26,13 +26,13 @@ - + - + @@ -278,7 +278,7 @@ "@context": "https://schema.org", "@type": "WebAPI", "name": "MiruroAPI", - "description": "Free RESTful API for anime streaming data. 44 endpoints, 12 providers, M3U8 streaming URLs.", + "description": "Free RESTful API for anime streaming data. 46 endpoints, 12 providers, M3U8 streaming URLs.", "url": "https://mirurotvapi.vercel.app", "image": "https://mirurotvapi.vercel.app/og-image.png", "documentation": "https://mirurotvapi.vercel.app/docs", @@ -326,7 +326,7 @@
Free · No API key · Open source

The Anime Streaming API
for Your Next Project

-

Search, discover, and stream anime with M3U8 URLs. Powered by AniList GraphQL + Miruro providers. 44 endpoints, 12 providers, zero config.

+

Search, discover, and stream anime with M3U8 URLs. Powered by AniList GraphQL + Miruro providers. 46 endpoints, 12 providers, zero config.

@@ -370,7 +370,7 @@ fetch("https://mirurotvapi.vercel.app/api/search?query=naruto")
-
0
API Endpoints
+
0
API Endpoints
0
Streaming Providers
0
Anime Indexed
M3U8
Stream Format
@@ -778,6 +778,7 @@ fetch("https://mirurotvapi.vercel.app/api/search?query=naruto") // ---- FEATURE: System ---- { id: 'health', title: 'Health', desc: 'Health check โ€” returns version, uptime, and environment.', path: '/health', params: [], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/health"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/health");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/health")\nprint(r.json())' } }, + { id: 'pipe-health', title: 'Pipe Health', desc: 'Pipe health check โ€” returns fallback system status and mirror availability.', path: '/pipe-health', params: [], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/pipe-health"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/pipe-health");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/pipe-health")\nprint(r.json())' } }, { id: 'stats', title: 'Stats', desc: 'API statistics โ€” total requests, cache size, uptime.', path: '/stats', params: [], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/stats"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/stats");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/stats")\nprint(r.json())' } }, { id: 'providers', title: 'Providers', desc: 'List all available streaming providers.', path: '/providers', params: [], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/providers"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/providers");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/providers")\nprint(r.json())' } }, { id: 'openapi', title: 'OpenAPI Spec', desc: 'Raw OpenAPI 3.0.3 specification.', path: '/openapi', params: [], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/openapi"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/openapi");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/openapi")\nprint(r.json())' } }, diff --git a/public/manifest.json b/public/manifest.json index fd1651c..0c74421 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -1,7 +1,7 @@ { "name": "MiruroAPI", "short_name": "MiruroAPI", - "description": "Free REST API for anime streaming data. 18 endpoints, 12 providers, M3U8 URLs. No API key required.", + "description": "Free REST API for anime streaming data. 46 endpoints, 12 providers, M3U8 URLs. No API key required.", "start_url": "/", "display": "standalone", "id": "/", diff --git a/public/openapi.json b/public/openapi.json index d78004c..8202d0c 100644 --- a/public/openapi.json +++ b/public/openapi.json @@ -434,6 +434,12 @@ "summary": "Health check" } }, + "/api/pipe-health": { + "get": { + "tags": ["System"], + "summary": "Pipe fallback method health check" + } + }, "/api/stats": { "get": { "tags": ["System"], diff --git a/public/privacy.html b/public/privacy.html index 50278df..66d4617 100644 --- a/public/privacy.html +++ b/public/privacy.html @@ -60,7 +60,7 @@

3. Third-Party Data Sources

-

The Service fetches data from graphql.anilist.co (AniList) and miruro.tv (streaming providers). This data (anime titles, descriptions, images, episode information) belongs to the respective content owners. We do not claim ownership of this data.

+

The Service fetches data from graphql.anilist.co (AniList) and Miruro streaming providers across multiple domains (miruro.to, miruro.ru, miruro.bz, miruro.tv). This data (anime titles, descriptions, images, episode information) belongs to the respective content owners. We do not claim ownership of this data.

If you are a content owner and wish to have your data removed from this API, please open an issue on our GitHub repository.

4. Data Storage

diff --git a/public/tos.html b/public/tos.html index 2c86af5..32ff0a3 100644 --- a/public/tos.html +++ b/public/tos.html @@ -58,7 +58,7 @@

The Service is built and maintained for educational and learning purposes only. It demonstrates API design, GraphQL integration, and serverless deployment techniques.

4. No Affiliation

-

The Service is not affiliated with, endorsed by, or connected to miruro.tv, Miruro, or any of its subsidiaries or affiliates. All trademarks and content belong to their respective owners.

+

The Service is not affiliated with, endorsed by, or connected to Miruro or any of its subsidiaries or affiliates across multiple domains (miruro.to, miruro.ru, miruro.bz, miruro.tv). All trademarks and content belong to their respective owners.

5. Third-Party Content

All anime data, images, descriptions, and other content displayed through the API belong to their respective copyright holders (AniList, Miruro). The Service does not host, store, or distribute any copyrighted media.

diff --git a/src/routes/apiRoutes.js b/src/routes/apiRoutes.js index 316a88d..07c3a71 100644 --- a/src/routes/apiRoutes.js +++ b/src/routes/apiRoutes.js @@ -1138,7 +1138,7 @@ const createApiRoutes = (jsonResponse, jsonError, startTime) => { size: require("../helpers/cache").getCacheSize(), maxSize: 100, }, - endpoints: 36, + endpoints: 46, providers: ["kiwi", "pewe", "bee", "bonk", "bun", "ally", "nun", "twin", "cog", "moo", "hop", "telli"], }, }); @@ -1198,7 +1198,7 @@ const createApiRoutes = (jsonResponse, jsonError, startTime) => { currentSize: require("../helpers/cache").getCacheSize(), description: "Map-based cache with TTL expiration and FIFO eviction", }, - endpoints: 36, + endpoints: 46, timestamp: new Date().toISOString(), }, }); diff --git a/test.js b/test.js index 36711dd..2c4d5dd 100644 --- a/test.js +++ b/test.js @@ -4,8 +4,8 @@ * Repository: https://github.com/Shineii86/MiruroAPI * * @description - * Integration test suite for MiruroAPI v2.1.4 endpoints. - * Tests all 44 endpoints for correct response format. + * Integration test suite for MiruroAPI v2.3.0 endpoints. + * Tests all 45 endpoints for correct response format. * Runs sequentially to avoid rate limiting. * * @author Shinei Nouzen @@ -152,7 +152,7 @@ async function runTest(test) { * API_URL=http://localhost:3000/api node test.js # Run against local */ async function runAll() { - console.log(`\n๐Ÿงช MiruroAPI v2.1.4 โ€” Running ${tests.length} tests...\n`); + console.log(`\n๐Ÿงช MiruroAPI v2.3.0 โ€” Running ${tests.length} tests...\n`); // NOTE: Sequential execution โ€” parallel requests would hit rate limiter for (const test of tests) {