diff --git a/.gitignore b/.gitignore
index f48416b..1223355 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
node_modules/
.env
.DS_Store
-*.log
\ No newline at end of file
+*.log
+*.pid
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e3de49b..fee16b4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,45 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [2.5.1] - 2026-10-13
+
+### Added
+- **Direct Embed Providers**: New `GET /api/stream/embeds` endpoint returning iframe-ready player URLs for **Megavid** (megavid.buzz), **AniXo** (anixo.buzz) and **MegaPlay** (megaplay.buzz) — bypasses Cloudflare entirely since playback happens in the provider's own iframe, no source-site AJAX scraping needed at watch time
+- **Provider Config**: New `src/configs/embedProviders.config.js` — provider registry with URL builders (patterns verified against aluukill/AniCult's provider registry)
+- **Embed Extractor**: New `src/extractors/embedProviders.extractor.js` — resolves MAL ID from the site's episode list (`data-mal`), looks up AniList ID via the public AniList GraphQL API (cached 60min), builds provider URLs
+- **Embed Controller**: New `src/controllers/embedProviders.controller.js` — supports `?slug=`, `?mal=`, `?anilist=` (direct IDs skip slug scraping entirely), `?ep=`, `?lang=sub|dub`, `?provider=` comma filter, with 400 errors for unknown providers
+- **IDs Cache TTL**: New `TTL.ids` (60min) for MAL/AniList ID mappings — these never change per anime
+- **OpenAPI**: Registered `/stream/embeds` in the spec
+- **Info External IDs**: `GET /api/info` responses now include `externalIds: { animeId, malId, anilistId }` — resolved server-side via the episode-list + AniList lookups (60min cache), best-effort (failed resolution returns nulls, never breaks the response); lets clients feed IDs straight into `/api/stream/embeds`
+- **Latest-Episode Checker**: New `GET /api/episodes/latest?slug=` endpoint (new `episodeLatest.controller.js`) — returns only `latest: { episode_no, title, id, server_ids, mal_id, ... }` plus `animeId`/`totalEpisodes`, built for bot polling (10min cache, registered before `/episodes/:id` so the literal path wins)
+- **Tests**: Added `Embed Providers`, `Embed (direct MAL)`, `Info External IDs` and `Latest Episode` cases to test.js
+
+### Fixed
+- **Spotlight Carousel Selectors (BREAKING drift)**: Source site redesigned the `#hotest` carousel — updated `homeInfo.extractor.js` and `spotlight.extractor.js` for the new markup (`swiper-slide` without `.item`, `a.btn.btn-primary` instead of `a.play`, `.cover img` instead of `.image div[style]`, `h2.ak-title` instead of `h2.title`, `.ak-desc` instead of `.desc`, type/date/rating packed into `.ak-detail span.it`). Old-layout selectors kept as fallbacks (dual-selector). Spotlight was returning 0 items before this fix; now returns 9.
+- **Spotlight Rating**: New layout packs rating into the `.ak-detail` list alongside year/date — numeric-with-decimal matching prevents the year (e.g. 2026) from being mistaken for the rating (e.g. 7.84)
+- **Diagnostic Sweep Fixes**: Full-repo deep scan caught stale counts — README endpoints badge, docs/index.md badge/table/tree/sample counts (38→39 endpoints, 28→29 scrapers/handlers), docs/endpoints.md sample `/stats` response, public/index.html animated stat counter, docs/architecture.md extractor count and Episode & Stream category now list `embedProviders` (39 reached at that sweep, then 40 with the info-ID and latest-episode additions)
+- **render.yaml**: Added missing trailing newline (EOF)
+
+### Changed
+- **Version**: Bumped to 2.5.1 (single release consolidating domain sync, embed providers, docs pass and diagnostic sweep)
+- **Mirror Domains Synced**: Verified all mirror domains against the official AniKoto domain hub (https://anikoto.site/#domains) — live check confirmed all 5 official domains return HTTP 200; replaced dead `anikoto.se` with official `anikototv.se` in `dataUrl.js` ALT_DOMAINS, `render.yaml` and README domain tables
+- **Documentation Style**: Full repo-style pass on embed modules — inline `NOTE`/`TIP` markers for cache-first lookups, MAL-ID dedup, failure-tolerant AniList resolution, direct-ID fast path, input sanitization, cache-key composition; corrected JSDoc examples to current AniList ID values
+- **Docs Sync**: `/api/stream/embeds` in docs/streaming.md (Direct Embed Providers section + TOC) and README streaming status table; project trees in README.md and docs/architecture.md list the new modules; `/episodes/latest` documented in docs/endpoints.md; all endpoint counts synced to 40 (README badge/highlights/checklist, landing-page metas and stat counter, docs/index.md badge/tables, docs/architecture.md controller counts, `/api/stats`); top-rankings `?sort=day|week|month` confirmed already supported — docs matched, no code change needed
+- **Dockerfile**: Base image `node:18-alpine` → `node:22-alpine` — Node 18 is EOL (Sept 2025); aligns with README's Node 20+ guidance and current LTS
+
+### Example
+```
+GET /api/stream/embeds?slug=one-piece-odmau&ep=1150
+GET /api/stream/embeds?mal=21&ep=1&lang=dub&provider=megavid,megaplay
+```
+
+### Verified
+- All 77 JS files pass `node --check`; all relative imports resolve
+- Official domains (all HTTP 200): `anikototv.to` (primary), `anikoto.cz`, `anikoto.me`, `anikoto.net`, `anikototv.se`; dead `anikoto.se` confirmed offline
+- All 3 embed provider URLs live-verified HTTP 200 (Megavid serves embed-only page by design)
+- Live smoke test 9/9 extractors passed; full API suite 38 passed / 0 failed / 2 optional skips (upstream AJAX blocks, documented)
+- No secrets tracked in git
+
## [2.4.1] - 2026-08-27
### Security
diff --git a/Dockerfile b/Dockerfile
index d9f967c..9f12415 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,4 +1,4 @@
-FROM node:18-alpine
+FROM node:22-alpine
WORKDIR /app
diff --git a/README.md b/README.md
index d9e12eb..a88d9f1 100644
--- a/README.md
+++ b/README.md
@@ -23,7 +23,7 @@
-
+
@@ -88,7 +88,7 @@
### Why AniKotoAPI?
-- 🎬 **38 Endpoints** — Complete coverage of anikototv.to data
+- 🎬 **40 Endpoints** — Complete coverage of anikototv.to data
- 🔍 **Full-Text Search** — Search anime by keyword with suggestions
- 📺 **Episode Lists** — AJAX-loaded episode data with server info
- 🎯 **Smart Filtering** — Genre, type, status, rating, sort, season, year
@@ -133,6 +133,8 @@ flowchart TD
> **Streaming endpoints (`/api/servers`, `/api/stream`, `/api/stream/resolve`) return errors when anikototv.to blocks AJAX requests from server-side IPs.**
>
> This is expected behavior when scraping from datacenter IPs (including Vercel's). AniKoto's bot protection blocks non-browser requests to their AJAX endpoints. Metadata endpoints (home, search, info, trending, etc.) work perfectly — only streaming is affected.
+>
+> **✅ Alternative: `/api/stream/embeds` never touches AniKoto's AJAX layer** — it returns iframe-ready player URLs for Megavid/AniXo/MegaPlay built from MAL/AniList IDs, so playback works from any environment with zero Cloudflare friction.
| What Works | What's Blocked |
|:---|:---|
@@ -164,7 +166,8 @@ FLARESOLVERR_URL=http://your-flaresolverr-host:8191
### ⚡ Core
- **Real-time scraping** from anikototv.to
- **Smart caching** with LRU and configurable TTL per endpoint
-- **38 RESTful endpoints** covering all data
+- **40 RESTful endpoints** covering all data
+- **Direct embed providers** (Megavid/AniXo/MegaPlay) — Cloudflare-free iframe playback
- **AJAX episode loading** for accurate data
- **Mapper API integration** for extra servers
- **Graceful error handling** per endpoint
@@ -215,7 +218,7 @@ FLARESOLVERR_URL=http://your-flaresolverr-host:8191
| Feature | Description | Status |
|:---|:---|:---:|
-| 🎬 38 API Endpoints | Complete coverage of anime data | ✅ |
+| 🎬 40 API Endpoints | Complete coverage of anime data | ✅ |
| 🔍 Full-Text Search | Keyword search with pagination | ✅ |
| 📺 Episode Lists | AJAX-loaded episode data | ✅ |
| 🎯 Advanced Filtering | Genre, type, status, rating, sort, season | ✅ |
@@ -240,7 +243,7 @@ FLARESOLVERR_URL=http://your-flaresolverr-host:8191
| **AniKoto** | `anikoto.cz` | ✅ Active | Mirror domain |
| **AniKoto** | `anikoto.me` | ✅ Active | Mirror domain |
| **AniKoto** | `anikoto.net` | ✅ Active | Mirror domain |
-| **AniKoto** | `anikoto.se` | ✅ Active | Mirror domain |
+| **AniKoto** | `anikototv.se` | ✅ Active | Mirror domain |
### Data Available
@@ -333,7 +336,7 @@ AniKotoAPI/
│ │
│ ├── 📂 docs/ # 📚 API documentation
│ │ ├── 📄 index.md # Overview, quick start
-│ │ ├── 📄 endpoints.md # Full API reference (38 endpoints)
+│ │ ├── 📄 endpoints.md # Full API reference (40 endpoints)
│ │ ├── 📄 streaming.md # Streaming flow guide + proxy
│ │ ├── 📄 examples.md # Code examples (cURL, JS, Python)
│ │ ├── 📄 architecture.md # Project structure, tech stack
@@ -344,32 +347,36 @@ AniKotoAPI/
│ ├── 📂 configs/ # 🔧 Configuration files
│ │ ├── 📄 dataUrl.js # 🌐 URL patterns for anikototv.to
│ │ ├── 📄 header.config.js # 📋 Request headers
-│ │ └── 📄 ids.config.js # 🏷️ Genre/Type/Status/Source/Season ID mappings
+│ │ ├── 📄 ids.config.js # 🏷️ Genre/Type/Status/Source/Season ID mappings
+│ │ └── 📄 embedProviders.config.js # 🆕 Direct embed provider registry (Megavid/AniXo/MegaPlay)
│ │
-│ ├── 📂 controllers/ # 🎮 Route handlers (28 files)
+│ ├── 📂 controllers/ # 🎮 Route handlers (30 files)
│ │ ├── 📄 homeInfo.controller.js
│ │ ├── 📄 animeInfo.controller.js
│ │ ├── 📄 search.controller.js
│ │ ├── 📄 episodeList.controller.js
+│ │ ├── 📄 episodeLatest.controller.js # 🆕 Latest-episode checker (bots)
│ │ ├── 📄 episodeListAjax.controller.js
│ │ ├── 📄 streamInfo.controller.js
│ │ ├── 📄 streamResolver.controller.js # 🆕 Stream URL resolution + quality detection
+│ │ ├── 📄 embedProviders.controller.js # 🆕 Direct embed provider URLs
│ │ ├── 📄 filter.controller.js
│ │ ├── 📄 watchPage.controller.js
-│ │ └── 📄 ... (15 more)
+│ │ └── 📄 ... (17 more)
│ │
-│ ├── 📂 extractors/ # 🔍 HTML scrapers (28 files)
+│ ├── 📂 extractors/ # 🔍 HTML scrapers (29 files)
│ │ ├── 📄 homeInfo.extractor.js # 🏠 Home page data
│ │ ├── 📄 search.extractor.js # 🔍 Search results
│ │ ├── 📄 animeInfo.extractor.js # 📺 Anime details
│ │ ├── 📄 streamInfo.extractor.js # 📡 Streaming servers
│ │ ├── 📄 streamResolver.extractor.js # 🔗 Stream URL resolution, M3U8 parser
+│ │ ├── 📄 embedProviders.extractor.js # 🆕 MAL/AniList ID resolution + embed URLs
│ │ ├── 📄 filter.extractor.js # 🎯 Filtered results
│ │ ├── 📄 watchPage.extractor.js # ▶️ Watch page data
│ │ ├── 📄 seasons.extractor.js # 📅 Season info from watch page
│ │ ├── 📄 watchOrder.extractor.js # 📋 Watch order from sidebar
│ │ ├── 📄 episodeList.extractor.js # 📋 Episode lists
-│ │ └── 📄 ... (16 more)
+│ │ └── 📄 ... (17 more)
│ │
│ ├── 📂 helper/ # 🛠️ Utility functions
│ │ ├── 📄 cache.helper.js # 💾 In-memory caching
@@ -384,7 +391,7 @@ AniKotoAPI/
│ │ └── 📄 creatorInfo.js # ✍️ Creator attribution injection
│ │
│ └── 📂 routes/ # 🛤️ Express routes
-│ ├── 📄 apiRoutes.js # 🌐 Main API routes (38 endpoints)
+│ ├── 📄 apiRoutes.js # 🌐 Main API routes (40 endpoints)
│ └── 📄 category.route.js # 🏷️ Category routes
│
├── 📄 server.js # 🚀 Express server entry point
@@ -2344,6 +2351,7 @@ CMD ["node", "server.js"]
| Version | Date | Key Changes |
|:---|:---|:---|
+| **2.5.1** | 2026-10-13 | Domain sync vs official hub, spotlight carousel fix, direct embed providers (`/api/stream/embeds`), info `externalIds` + latest-episode checker, full docs pass, diagnostic sweep, Dockerfile Node 22 |
| **2.4.1** | 2026-08-27 | Security: fixed SSRF in stream proxies, dotenv load order fix, SECURITY.md |
| **2.2.0** | 2026-07-28 | Streaming resolver, M3U8/TS proxy, 5 new endpoints, bug fixes, full diagnostic sweep |
| **1.7.2** | 2026-06-08 | Full rebrand AniKotoAPI → AniKotoAPI, docs folder with real data, streaming fix |
@@ -2457,7 +2465,7 @@ The API can access 10,000+ anime titles from anikototv.to. The most-popular endp
### ✅ Completed
-- [x] 🎬 38 API endpoints covering all data
+- [x] 🎬 40 API endpoints covering all data
- [x] 🔍 Full-text search with pagination
- [x] 📺 Episode lists via AJAX loading
- [x] 🎯 Advanced filtering (genre, type, status, rating, sort, season, year)
@@ -2560,7 +2568,8 @@ git push origin feature/amazing-feature
| [AniKoto CZ](https://anikoto.cz) | Mirror domain |
| [AniKoto ME](https://anikoto.me) | Mirror domain |
| [AniKoto NET](https://anikoto.net) | Mirror domain |
-| [AniKoto SE](https://anikoto.se) | Mirror domain |
+| [AniKoto SE](https://anikototv.se) | Mirror domain |
+| [AniKoto Hub](https://anikoto.site) | Official domain verification hub |
### 🛠️ Technologies
diff --git a/docs/architecture.md b/docs/architecture.md
index 0b2e11f..e1fe611 100644
--- a/docs/architecture.md
+++ b/docs/architecture.md
@@ -67,13 +67,13 @@
* │ │ │ │ │
* │ │ ▼ │ │
* │ │ ┌──────────────────────────────────────────────────────────┐ │ │
- * │ │ │ CONTROLLER LAYER (28 controllers) │ │ │
+ * │ │ │ CONTROLLER LAYER (30 controllers) │ │ │
* │ │ │ Validation · Parameter parsing · Response formatting │ │ │
* │ │ └──────────────────────┬───────────────────────────────────┘ │ │
* │ │ │ │ │
* │ │ ▼ │ │
* │ │ ┌──────────────────────────────────────────────────────────┐ │ │
- * │ │ │ EXTRACTOR / SCRAPER LAYER (28 extractors) │ │ │
+ * │ │ │ EXTRACTOR / SCRAPER LAYER (29 extractors) │ │ │
* │ │ │ HTML fetching · Cheerio parsing · Data transformation │ │ │
* │ │ └──────────────────────┬───────────────────────────────────┘ │ │
* │ │ │ │ │
@@ -180,15 +180,18 @@
* ├── src/
* │ ├── configs/
* │ │ ├── header.config.js # Default HTTP headers for upstream requests
- * │ │ └── ids.config.js # Genre / Type / Status numeric ID mappings
- * │ ├── controllers/ # 28 route handlers (one per endpoint)
+ * │ │ ├── ids.config.js # Genre / Type / Status numeric ID mappings
+ * │ │ └── embedProviders.config.js # Direct embed provider registry (Megavid/AniXo/MegaPlay)
+ * │ ├── controllers/ # 30 route handlers (one per endpoint)
* │ │ ├── homeInfo.controller.js
* │ │ ├── animeInfo.controller.js
* │ │ ├── search.controller.js
* │ │ ├── episodeList.controller.js
+ * │ │ ├── episodeLatest.controller.js
* │ │ ├── episodeListAjax.controller.js
* │ │ ├── streamInfo.controller.js
* │ │ ├── streamResolver.controller.js
+ * │ │ ├── embedProviders.controller.js
* │ │ ├── schedule.controller.js
* │ │ ├── spotlight.controller.js
* │ │ ├── trending.controller.js
@@ -210,7 +213,7 @@
* │ │ ├── recentlyUpdatedTabs.controller.js
* │ │ ├── completedAnime.controller.js
* │ │ └── category.controller.js
- * │ ├── extractors/ # 28 HTML scrapers (one per data source)
+ * │ ├── extractors/ # 29 HTML scrapers (one per data source)
* │ │ ├── homeInfo.extractor.js
* │ │ ├── animeInfo.extractor.js
* │ │ ├── search.extractor.js
@@ -218,6 +221,7 @@
* │ │ ├── episodeListAjax.extractor.js
* │ │ ├── streamInfo.extractor.js
* │ │ ├── streamResolver.extractor.js
+ * │ │ ├── embedProviders.extractor.js
* │ │ ├── schedule.extractor.js
* │ │ ├── spotlight.extractor.js
* │ │ ├── trending.extractor.js
@@ -308,7 +312,7 @@
* └────────────────────────────────────────────────────────────────────────┘
*
* ┌────────────────────────────────────────────────────────────────────────┐
- * │ Extractors (28 scrapers) │
+ * │ Extractors (29 scrapers) │
* ├────────────────────────────────────────────────────────────────────────┤
* │ One extractor per data source on the target site. Responsibilities: │
* │ • Build the upstream URL (via mirror.helper) │
@@ -861,7 +865,8 @@
* │ Search & Filter │ search, filter, azList, category │
* │ Anime Detail │ animeInfo, watchPage, status │
* │ Episode & Stream │ episodeList, episodeListAjax, │
- * │ │ streamInfo, streamResolver, download │
+ * │ │ streamInfo, streamResolver, download,│
+ * │ │ embedProviders │
* │ Lists │ newRelease, trendingSidebar, │
* │ │ topAnimeRankings, recentlyUpdated, │
* │ │ completedAnime, upcomingAnime │
diff --git a/docs/endpoints.md b/docs/endpoints.md
index 32b8447..2febe49 100644
--- a/docs/endpoints.md
+++ b/docs/endpoints.md
@@ -164,7 +164,7 @@ curl "https://anikototvapi.vercel.app/api/search?keyword=naruto"
## GET /info
-Get detailed info about an anime.
+Get detailed info about an anime. Includes `externalIds` (MAL/AniList IDs) that can be passed directly to `/stream/embeds`.
| Param | Type | Required | Description |
|-------|------|----------|-------------|
@@ -172,6 +172,8 @@ Get detailed info about an anime.
> **Important:** Slugs now include random hashes (e.g., `one-piece-odmau`). Get valid slugs from `/search` or `/most-popular` results.
+> **Note:** `externalIds` is resolved server-side (cached 60 min) and is best-effort — if ID resolution fails it comes back as `null` values, the rest of the response is unaffected.
+
**Request:**
```bash
@@ -203,7 +205,12 @@ curl "https://anikototvapi.vercel.app/api/info?id=naruto-shippuuden-movie-6-road
"producers": ["TV Tokyo", "Shueisha"],
"genres": ["Action", "Comedy", "Supernatural"],
"rating": "PG-13",
- "reviewCount": "0"
+ "reviewCount": "0",
+ "externalIds": {
+ "animeId": 1642,
+ "malId": "21",
+ "anilistId": "21"
+ }
}
}
```
@@ -254,6 +261,46 @@ curl "https://anikototvapi.vercel.app/api/episodes/958"
---
+## GET /episodes/latest
+
+Latest-episode checker — returns only the newest episode plus summary counts. Built for bots and notification jobs ("is there a new episode?") that shouldn't download the full episode list.
+
+| Param | Type | Required | Description |
+|-------|------|----------|-------------|
+| `slug` | string | Yes | Anime slug or animeId |
+
+**Request:**
+
+```bash
+curl "https://anikototvapi.vercel.app/api/episodes/latest?slug=one-piece-odmau"
+```
+
+**Response:**
+
+```json
+{
+ "success": true,
+ "results": {
+ "slug": "one-piece-odmau",
+ "animeId": 1642,
+ "totalEpisodes": 1165,
+ "latest": {
+ "episode_no": 1165,
+ "title": "",
+ "id": "50167",
+ "slug": "1165",
+ "href": "#",
+ "server_ids": "dXNCT3hNQzk3THhSTW8ySnM5...",
+ "mal_id": "21"
+ }
+ }
+}
+```
+
+> **Tip:** Poll this endpoint, compare `results.latest.episode_no` with your stored value, and call `/servers?ids=results.latest.server_ids` only when it changes. Responses are cached for 10 minutes.
+
+---
+
## GET /servers
Get available servers for an episode.
@@ -835,6 +882,48 @@ Returns array of quality objects with url, quality label, resolution, bandwidth,
---
+## GET /stream/embeds
+
+Direct embed provider URLs (Megavid / AniXo / MegaPlay) — iframe-ready players that bypass Cloudflare entirely. Playback happens inside the provider's own iframe; no source-site AJAX scraping at watch time.
+
+| Param | Type | Required | Description |
+|-------|------|----------|-------------|
+| `slug` | string | One of* | Anime slug — MAL/AniList IDs resolved automatically |
+| `mal` | string | One of* | Direct MAL ID (skips slug lookup) |
+| `anilist` | string | One of* | Direct AniList ID (skips slug lookup) |
+| `ep` | number | No | Episode number (default 1) |
+| `lang` | string | No | `sub` or `dub` (default `sub`) |
+| `provider` | string | No | Comma-separated filter: `megaplay`, `anixo`, `megavid` |
+
+\* Provide at least one of `slug`, `mal`, or `anilist`.
+
+```bash
+curl "https://anikototvapi.vercel.app/api/stream/embeds?slug=one-piece-odmau&ep=1"
+curl "https://anikototvapi.vercel.app/api/stream/embeds?mal=21&ep=1&lang=dub&provider=megavid"
+```
+
+Returns resolved IDs plus iframe-ready URLs per provider:
+
+```json
+{
+ "success": true,
+ "results": {
+ "slug": "one-piece-odmau",
+ "episode": 1,
+ "lang": "sub",
+ "ids": { "animeId": 1642, "malId": "21", "anilistId": "21" },
+ "providers": [
+ { "id": "megaplay", "name": "MegaPlay", "url": "https://megaplay.buzz/stream/mal/21/1/sub", "iframeReady": true },
+ { "id": "anixo", "name": "AniXo", "url": "https://anixo.buzz/embed/ani/21/1/sub?color=%23e63946", "iframeReady": true },
+ { "id": "megavid", "name": "Megavid", "url": "https://megavid.buzz/mal/21/1/sub?color=%23e63946&autoplay=true", "iframeReady": true }
+ ],
+ "unavailable": []
+ }
+}
+```
+
+---
+
## GET /stream/proxy
M3U8 playlist proxy — rewrites relative URLs to proxy endpoints for CORS-free playback.
@@ -924,7 +1013,7 @@ curl "https://anikototvapi.vercel.app/api/stats"
"ttl": "5 minutes",
"description": "Map-based cache with TTL expiration"
},
- "endpoints": 38,
+ "endpoints": 40,
"timestamp": "2026-07-30T02:20:46.205Z"
}
}
diff --git a/docs/index.md b/docs/index.md
index a6b5c7e..6e3dd56 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -7,7 +7,7 @@


-
+

> A fast, free REST API that scrapes anime data from **anikototv.to**.
@@ -70,9 +70,9 @@ That's it. No API keys required.
| Feature | Description |
|---|---|
-| **38+ Endpoints** | Full coverage of anime data, streaming, and discovery |
-| **28 HTML Scrapers** | Cheerio-based scrapers for robust data extraction |
-| **28 Route Handlers** | Organized controllers with clean separation of concerns |
+| **40+ Endpoints** | Full coverage of anime data, streaming, and discovery |
+| **29 HTML Scrapers** | Cheerio-based scrapers for robust data extraction |
+| **30 Route Handlers** | Organized controllers with clean separation of concerns |
| **5 Mirror Domains** | Automatic failover across multiple source domains |
| **LRU Cache** | Per-endpoint TTL caching for performance |
| **Rate Limiting** | 100 requests per 15 minutes per IP |
@@ -194,12 +194,12 @@ AniKotoAPI/
│ ├── info.js # Anime info
│ ├── search.js # Search
│ ├── stream.js # Streaming
-│ └── ... # 38+ route handlers
+│ └── ... # 40 route handlers
├── scrapers/ # Cheerio HTML scrapers
│ ├── home.js
│ ├── info.js
│ ├── search.js
-│ └── ... # 28 scrapers
+│ └── ... # 29 scrapers
├── utils/ # Shared utilities
│ ├── cache.js # LRU cache with TTL
│ ├── rateLimit.js # IP-based rate limiter
@@ -218,8 +218,8 @@ AniKotoAPI/
### Key Design Patterns
-- **Scraping Layer**: 28 Cheerio-based scrapers parse HTML from anikototv.to, isolating page-specific logic from route handlers.
-- **Controller Layer**: 28 route handlers map HTTP requests to scraper calls, handle validation, and format responses.
+- **Scraping Layer**: 29 Cheerio-based scrapers parse HTML from anikototv.to, isolating page-specific logic from route handlers.
+- **Controller Layer**: 30 route handlers map HTTP requests to scraper calls, handle validation, and format responses.
- **Cache Layer**: LRU cache with per-endpoint TTL reduces redundant scraping. Hot endpoints cache for 2–5 minutes; cold endpoints for 10+ minutes.
- **Mirror Layer**: 5 source domains with automatic failover. If one domain is slow or down, requests transparently fall back to the next mirror.
- **Rate Limiter**: Token bucket algorithm, 100 requests per 15-minute window per client IP.
@@ -350,7 +350,7 @@ All errors return JSON with a consistent structure:
| File | Description |
|------|-------------|
-| [endpoints.md](./endpoints.md) | Full API reference for all 38+ endpoints |
+| [endpoints.md](./endpoints.md) | Full API reference for all 40+ endpoints |
| [streaming.md](./streaming.md) | Complete streaming workflow guide |
| [examples.md](./examples.md) | Working code examples in cURL, JS, Python |
| [architecture.md](./architecture.md) | Project structure and design patterns |
diff --git a/docs/streaming.md b/docs/streaming.md
index edfe796..8b4eb5f 100644
--- a/docs/streaming.md
+++ b/docs/streaming.md
@@ -15,6 +15,8 @@ This document covers the complete streaming workflow for AniKotoAPI — from sea
## ⚠️ Streaming Status
> **Streaming endpoints (`/api/servers`, `/api/stream`, `/api/stream/resolve`) return errors when anikototv.to blocks AJAX requests from server-side IPs.**
+>
+> **✅ Alternative: `/api/stream/embeds` never touches AniKoto's AJAX layer** — see [Direct Embed Providers](#direct-embed-providers).
| What Works | What's Blocked |
|:---|:---|
@@ -24,6 +26,7 @@ This document covers the complete streaming workflow for AniKotoAPI — from sea
| Top 10, most popular, new release | `/api/mapper-servers` — gogoanime servers |
| AZ list, random, genre list | All AJAX-dependent endpoints |
| All HTML-scraped endpoints | |
+| **`/api/stream/embeds` — direct provider iframes** | |
**To fix streaming**, set one of these environment variables:
@@ -35,17 +38,55 @@ SCRAPER_API_KEY=your_scraperapi_key
FLARESOLVERR_URL=http://your-flaresolverr-host:8191
```
+Or use the Cloudflare-free embed providers below — no proxy needed.
+
+---
+
+## Direct Embed Providers
+
+`GET /api/stream/embeds` builds iframe-ready player URLs for three third-party providers. Playback happens inside the provider's own iframe, so nothing ever requests AniKoto's Cloudflare-protected AJAX endpoints at watch time.
+
+| Provider | URL pattern | Requires |
+|:---|:---|:---|
+| **MegaPlay** | `megaplay.buzz/stream/mal\|ani/{id}/{ep}/{lang}` | MAL or AniList ID |
+| **AniXo** | `anixo.buzz/embed/ani/{anilistId}/{ep}/{lang}` | AniList ID |
+| **Megavid** | `megavid.buzz/{mal\|ani}/{id}/{ep}/{lang}` | MAL or AniList ID |
+
+```bash
+# From an AniKoto slug (MAL/AniList IDs resolved automatically, cached 60min)
+curl ".../api/stream/embeds?slug=one-piece-odmau&ep=1"
+
+# From direct IDs — zero scraping, instant response
+curl ".../api/stream/embeds?mal=21&ep=1&lang=dub&provider=megavid,megaplay"
+```
+
+```json
+{
+ "results": {
+ "ids": { "animeId": 1642, "malId": "21", "anilistId": "21" },
+ "providers": [
+ { "id": "megaplay", "url": "https://megaplay.buzz/stream/mal/21/1/sub", "iframeReady": true },
+ { "id": "anixo", "url": "https://anixo.buzz/embed/ani/21/1/sub?color=%23e63946", "iframeReady": true },
+ { "id": "megavid", "url": "https://megavid.buzz/mal/21/1/sub?color=%23e63946&autoplay=true", "iframeReady": true }
+ ]
+ }
+}
+```
+
+Drop any `url` straight into an `