Skip to content

SH0MIK/animetsu-scraper

Β 
Β 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

26 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Anime Scraper

A self-hostable, multi-provider anime scraper + web UI that extracts m3u8 (HLS) streams, MP4 streams, and WebVTT subtitles from multiple upstream anime sites, enriched with AniList metadata.

Built with Next.js 16 Β· TypeScript Β· Tailwind CSS Β· shadcn/ui Β· hls.js. Deploys to Vercel in one click or runs anywhere with Docker.

⚠️ Educational project. Streams are proxied from upstream providers for personal use only. The maintainer does not host any media content. Support the official release when available in your region.


Features

  • πŸŽ›οΈ Multi-provider architecture β€” switch between upstreams from the UI with one click
    • Animetsu β€” animetsu.live Β· soft sub Β· 4 servers (kite / dio / sage / meg) Β· HLS m3u8
    • Anikuro β€” anikuro.ru Β· aggregates 11 upstreams (animeverse / animegg / anikoto / animepahe / reanime / animedao / anidb / animedunya / animeverse / allani / senshi / animix) Β· MP4 + HLS
  • πŸ” Search β€” instant debounced search across the active provider's catalog
  • 🎬 Universal media player β€” hls.js for HLS, native HTML5 for MP4, with quality switcher and VTT subtitle selector
  • πŸ…°οΈ Sub / Dub toggle β€” switch between subtitled and dubbed sources per episode
  • ⏭️ Skip intro / outro β€” auto-detected skip markers surface as in-player buttons
  • 🧠 AniList enrichment β€” characters, studios, recommendations, YouTube trailer, next-airing countdown
  • πŸ”₯ Trending now β€” pulled from the AniList GraphQL API on the home page
  • πŸ†• Recently released β€” live from animetsu.live
  • πŸ›‘οΈ Cloudflare-friendly β€” built-in CORS proxy rewrites all upstream URIs through your own domain, with retry + fallback logic for 403/429/503 challenges, and per-upstream Referer support
  • 🐳 One-command Docker β€” docker compose up and you're done
  • β–² One-click Vercel β€” pure Node.js runtime, no native deps

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         Browser (you)                            β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  /  β†’  Home (search Β· trending Β· recent)                  β”‚   β”‚
β”‚  β”‚        [Provider switcher: Animetsu ⇄ Anikuro]            β”‚   β”‚
β”‚  β”‚  ↓ click anime                                           β”‚   β”‚
β”‚  β”‚  /?anime=<id>  β†’  Details (info Β· episodes Β· trailer)    β”‚   β”‚
β”‚  β”‚  ↓ click episode                                         β”‚   β”‚
β”‚  β”‚  /?watch=<id>&ep=<n>  β†’  MediaPlayer (HLS or MP4)         β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                β”‚  fetch (same origin, ?provider=…)
                                β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      Next.js (your domain)                       β”‚
β”‚                                                                  β”‚
β”‚  /api/scrape/providers    β†’  list of registered providers        β”‚
β”‚  /api/scrape/search       ─┐                                     β”‚
β”‚  /api/scrape/info          β”‚                                     β”‚
β”‚  /api/scrape/episodes      β”‚  β†’  dispatches to the active        β”‚
β”‚  /api/scrape/servers       β”‚     provider (animetsu or anikuro)  β”‚
β”‚  /api/scrape/sources      β”€β”˜                                     β”‚
β”‚                                                                  β”‚
β”‚  /api/scrape/anilist      β†’  AniList GraphQL (enrichment)        β”‚
β”‚  /api/scrape/recent       β†’  animetsu recent releases            β”‚
β”‚                                                                  β”‚
β”‚  /api/proxy/m3u8?url=…&referer=…                                β”‚
β”‚       β”‚  Handles both HLS playlists and MP4 streams              β”‚
β”‚       β”‚  - HLS: rewrites relative URIs through itself            β”‚
β”‚       β”‚  - MP4: passes through with Range support                β”‚
β”‚       β”‚  - Sets the right Referer per upstream                   β”‚
β”‚       β–Ό                                                          β”‚
β”‚   Provider abstraction:                                          β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                             β”‚
β”‚   β”‚  Animetsu    β”‚  β”‚  Anikuro     β”‚                             β”‚
β”‚   β”‚  /v2/api/    β”‚  β”‚  /api/v1/    β”‚                             β”‚
β”‚   β”‚  anime/*     β”‚  β”‚  anime/*     β”‚                             β”‚
β”‚   β”‚              β”‚  β”‚              β”‚                             β”‚
β”‚   β”‚  ↳ kite      β”‚  β”‚  ↳ 11 upstreams                            β”‚
β”‚   β”‚  ↳ dio       β”‚  β”‚    tried in parallel                       β”‚
β”‚   β”‚  ↳ sage      β”‚  β”‚    MP4 preferred                            β”‚
β”‚   β”‚  ↳ meg       β”‚  β”‚                                              β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Key files

Path Purpose
src/lib/providers/types.ts Unified Provider interface β€” every backend implements this
src/lib/providers/index.ts Provider registry β€” single source of truth
src/lib/providers/animetsu.ts Animetsu adapter (wraps the animetsu client)
src/lib/providers/anikuro.ts Anikuro adapter (multi-provider fan-out, MP4 preference)
src/lib/animetsu/client.ts Raw HTTP client for animetsu.live
src/lib/anilist/client.ts AniList GraphQL client (cached, rate-limit-friendly)
src/app/api/scrape/* API routes β€” all accept `?provider=animetsu
src/app/api/proxy/m3u8/route.ts Universal CORS proxy (HLS + MP4 + VTT, per-upstream Referer)
src/components/animetsu/media-player.tsx Universal player β€” HLS via hls.js, MP4 via native <video>
src/app/page.tsx Single-page UI with provider switcher

Quick start (local dev)

git clone <this-repo> anime-scraper
cd anime-scraper
bun install                 # or: npm install / pnpm install
cp .env.example .env.local  # optional β€” defaults already work
bun run dev                 # β†’ http://localhost:3000

Deploy to Vercel

  1. Push this repo to GitHub.
  2. Go to vercel.com/new and import the repo.
  3. Vercel auto-detects Next.js β€” no build config needed.
  4. (Optional) Set environment variables from .env.example in Project β†’ Settings β†’ Environment Variables.
  5. Click Deploy. Done.

vercel.json already bumps the /api/proxy/m3u8 function to 60 s maxDuration + 1 GB RAM so it can stream long episodes without timing out.


Self-host with Docker

docker compose up -d --build
# β†’ http://localhost:3000

The Dockerfile uses Next.js standalone output β€” the final image is ~150 MB and runs as a non-root user.

Env var Default Purpose
ANIMETSU_API_BASE https://animetsu.live/v2/api/anime Override the animetsu JSON API base
SWIFTSTREAM_PROXY https://swiftstream.top/proxy Override the animetsu m3u8 / subtitle proxy
ANIKURO_BASE https://anikuro.ru Override the anikuro API base
ANIKURO_PROXY https://proxy.anikuro.ru Override the anikuro MP4 / m3u8 proxy
FALLBACK_PROXY (empty) Optional cors-anywhere-style proxy used when Cloudflare returns a 403/429/503

API reference

All routes are GET. Responses are JSON unless noted. All /api/scrape/* routes accept a ?provider=animetsu|anikuro query param (defaults to animetsu).

GET /api/scrape/providers

Returns the list of registered providers.

{
  "providers": [
    { "id": "animetsu", "label": "Animetsu", "description": "…", "defaultServer": "kite", "supportsDub": true },
    { "id": "anikuro",  "label": "Anikuro",  "description": "…", "defaultServer": "animeverse", "supportsDub": true }
  ]
}

GET /api/scrape/search?q=<query>&provider=<id>

Returns results[] with the provider-specific id, title, cover image, year, score, etc.

GET /api/scrape/info?id=<id>&provider=<id>&enrich=1

Returns the full anime info, optionally merged with AniList data when enrich=1 (default).

GET /api/scrape/episodes?id=<id>&provider=<id>

Returns the list of episodes.

GET /api/scrape/servers?id=<id>&ep=<epNum>&provider=<id>

Returns the available streaming servers for that episode.

  • Animetsu: kite (default, soft sub) Β· dio Β· sage Β· meg
  • Anikuro: animeverse (default, MP4) Β· animegg Β· anikoto Β· animepahe Β· reanime Β· animedao Β· animegg Β· anidb Β· animedunya Β· animeverse Β· allani Β· senshi Β· animix

GET /api/scrape/sources?id=<id>&ep=<epNum>&server=<server>&type=sub|dub&provider=<id>

Returns a player-ready payload:

{
  "sources": [
    { "url": "/api/proxy/m3u8?url=…", "type": "master", "quality": "auto", "isMaster": true },
    { "url": "/api/proxy/m3u8?url=…", "type": "hls",    "quality": "1080p" },
    // OR
    { "url": "https://proxy.anikuro.ru/…", "type": "mp4", "quality": "720p" }
  ],
  "subtitles": [{ "lang": "English", "url": "/api/proxy/m3u8?format=vtt&url=…" }],
  "skips": { "intro": { "start": 0, "end": 0 }, "outro": { "start": 0, "end": 0 } },
  "server": "animeverse",
  "provider": "anikuro",
  "qualities": [{ "label": "1080p", "resolution": "1920x1080", "url": "…" }]
}

For anikuro, if server is omitted or set to auto/default, the provider fans out to a curated subset of upstreams in parallel and returns the best playable source (preferring MP4 over HLS).

GET /api/proxy/m3u8?url=<encoded>&referer=<encoded>&format=<vtt|m3u8>

Universal CORS proxy for upstream m3u8 / MP4 / VTT URLs. Auto-detects content type:

  • application/vnd.apple.mpegurl content β†’ rewrites all relative URIs in the playlist back through /api/proxy/m3u8 (preserving the &referer= if provided)
  • video/mp4 content β†’ streamed through with Range support
  • text/vtt content β†’ passed through with text/vtt; charset=utf-8
  • Binary segments (TS / fMP4) β†’ streamed through with upstream content-type

The optional ?referer= param sets the Referer header sent to the upstream β€” required for anikuro HLS streams that come from referer-locked CDNs.

GET /api/scrape/anilist?id=<anilistId> | ?search=<q> | ?trending=1

Direct AniList GraphQL passthrough. Cached for 30 min.


Adding a new provider

The provider abstraction makes it trivial to add a new upstream site:

  1. Create src/lib/providers/<name>.ts and implement the Provider interface:
    export const myProvider: Provider = {
      meta: { id: "mine", label: "Mine", /* … */ },
      async search(query) { /* … */ return []; },
      async getInfo(id) { /* … */ return null; },
      async getEpisodes(id) { /* … */ return []; },
      async getServers(id, ep) { /* … */ return []; },  // optional
      async getSources(opts) { /* … */ return { sources, subtitles, server, provider: "mine" }; },
    };
  2. Register it in src/lib/providers/index.ts:
    export const providers: Record<ProviderId, Provider> = {
      animetsu: animetsuProvider,
      anikuro: anikuroProvider,
      mine: myProvider,  // ← add here
    };
  3. Add the provider id to the ProviderId union type in src/lib/providers/types.ts.

The UI and API routes will pick it up automatically β€” no other changes needed.


How each provider works

Animetsu

  1. The animetsu.live frontend is a Vite SPA. Its main bundle reveals the API base: window.b = https://animetsu.live/v2 and an axios instance at ole = ${b}/api.
  2. All API calls are routed through ${ole}/anime/<key>. The interesting keys are:
    • search/?query=<q>
    • info/<id>
    • eps/<id>
    • servers/<id>/<ep>
    • oppai/<id>/<ep>?server=<s>&source_type=sub|dub ← returns { sources, subs, skips }
  3. The sources[].url is a relative path like /oppai/kite/<token>. When need_proxy === true, the host is https://swiftstream.top/proxy.
  4. The master playlist contains relative token paths for each quality (360p / 720p / 1080p).
  5. Subtitles come back as full https://swiftstream.top/proxy/oppai/kite/<token> URLs in WebVTT format.

Anikuro

  1. Anikuro.ru is a Next.js-style site with a clean JSON API at /api/v1/* that aggregates 11 upstream anime providers.
  2. Endpoints used:
    • discovery/search?query=<q> β†’ search
    • anime/<id> β†’ info (id is the AniList id)
    • anime/<id>/episodes β†’ episode list
    • sources/<provider>/<animeId>:<epNum> β†’ stream sources for a specific upstream provider
  3. Stream URLs come back pre-wrapped through https://proxy.anikuro.ru/<base64>.m3u8|referer?proxy=0 where the base64 decodes to <streamUrl>|<upstreamReferer>.
  4. As of 2026-06, anikuro's m3u8 proxy returns HTTP 500, but the MP4 proxy works with Range support. The provider prefers MP4 sources (animeverse, animegg) and falls back to HLS (anikoto, animix) routed through our own /api/proxy/m3u8 with the upstream Referer set.
  5. When server=auto (the default), the provider fans out to a curated subset of 4 upstreams in parallel (~600 ms total), then falls back to the remaining 7 if no hit was found.

Tech stack

Layer Choice Why
Framework Next.js 16 (App Router) One codebase for API + UI, deploys to Vercel out of the box
Language TypeScript 5 Strict typing for upstream payloads
UI Tailwind CSS 4 + shadcn/ui Fast, accessible, themeable
Player hls.js + native HTML5 <video> HLS for adaptive streaming, native for MP4
State React hooks (no global store needed) App is a single-page flow
Caching In-memory LRU + Cache-Control headers No external cache infra required
Container Docker (Node 22-alpine, standalone) ~150 MB final image
Host Vercel or any Node host Pure JS β€” no native deps

License

MIT β€” see LICENSE. The project is provided for educational purposes. Use responsibly and in accordance with the laws of your jurisdiction.

About

Multi-provider anime streaming API + interactive docs (animetsu, anikuro, animeyubi, miruro)

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages