Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 

Repository files navigation

kenpyTV

Free anime streaming site — FastAPI (Python) backend + React (Vite) frontend with a custom hls.js player. Scrapes anikoto.cz, proxies its HLS streams and poster images, and serves a modern mobile-friendly UI.

Brand: kenpyTV · "The K-way to watch anime" · by kenpydev

Features

  • 🎬 Custom hls.js player with quality selector (all master-playlist variants), subtitle (CC) menu, and skip intro/outro buttons
  • 🗣️ Sub / Dub tabs — servers grouped by language, with per-language server bars
  • 🔀 Random anime — "Random" button in the nav picks a random title
  • 📺 Episode picker — search + pagination (60/page) on the detail page; a modal on the Watch page that opens on the page of the episode you're watching and scrolls it into view
  • 🛟 Original-embed fallback — when HLS fails, per-server backup: iframe the original player or open it in a new tab
  • 🔍 Search, paginated browse tabs (New Release, Top Airing, Most Popular, Recently Added, Completed), home hero slider with left/right arrows
  • ⚡ Fast backend — parallel server resolution, threaded search, aggressive caching (streams 30 min, meta 24h), fast-fail timeouts
  • 📱 Fully responsive with a hamburger menu on mobile

Architecture

backend/   FastAPI — scrapes anikoto.cz, exposes JSON APIs + HLS/image proxies
frontend/  React (Vite) — Home, Browse/Search, Anime detail, Watch page with player
Browser ──▶ React (Vite) ──▶ FastAPI /api ──▶ anikoto.cz (scrape)
                 │                 │
                 │            /api/hls-proxy (rewrites m3u8, chains segments)
                 └──▶ hls.js ───▶ CDN segments (via proxy)

How streams work

  1. GET /api/stream resolves the episode's servers (server-list + mapper endpoints, in parallel).
  2. Each server's HLS URL is wrapped as /api/redirect?id=.../api/hls-proxy?url=....
  3. /api/hls-proxy fetches the master playlist, rewrites every variant/segment URL back through itself (adding the correct Referer/Origin headers to bypass 403s), and serves it to hls.js.
  4. Subtitles (VTT) and download links get the same proxying treatment.

API endpoints

Route Description
GET /api Home page sections (featured, latest, new release, upcoming, top anime…)
GET /api/info?id=<slug> Anime details + episode list + recommendations
GET /api/listing?type=<slug>&page=<n> Paginated listing. Types: new-release, status/currently-airing, most-viewed, latest-updated, status/finished-airing
GET /api/search?q=<query> Search (3 parallel candidate URLs)
GET /api/random Random anime (follows anikoto.cz /random redirect)
GET /api/episodes?id=<slug> Raw episode list
GET /api/stream?id=<slug>&ep=<n> Stream servers (HLS + subtitles + skip data + downloads)
GET /api/schedule?date= Airing schedule
GET /api/hls-proxy?url=&referer= Proxies + rewrites HLS playlists (master & segments)
GET /api/redirect?id= Temporary 302 redirect for stream/subtitle URLs
GET /api/image-proxy?url= Proxies poster images (per-domain Referer handling)
GET /api/health Health check (service: kenpyTV)

Run locally

cd backend
pip install -r requirements.txt
python app.py          # or: uvicorn app:app --reload
cd frontend
npm install
npm run dev

Open http://localhost:5173. The Vite dev server proxies /api to http://localhost:8000 (see frontend/vite.config.js).

Verify your changes

  • Frontend: npm run build (must succeed before shipping)
  • Backend: python -m py_compile app.py scraper.py
  • Smoke test the API while the server runs:
    curl "http://localhost:8000/api/random"
    curl "http://localhost:8000/api/listing?type=status/currently-airing&page=1"

Project structure

.
├── .gitignore
├── README.md
├── backend/
│   ├── app.py            # FastAPI routes, HLS/image/redirect proxies, caching
│   ├── scraper.py        # anikoto.cz scraping + stream resolution
│   ├── requirements.txt
│   ├── Procfile          # Railway / Heroku start command
│   ├── Dockerfile        # Fly.io / any Docker host
│   └── render.yaml       # Render blueprint (one-click backend)
└── frontend/
    ├── index.html        # brand, fonts, meta
    ├── vite.config.js    # dev proxy
    ├── vercel.json       # SPA rewrites for Vercel
    ├── .env.example      # VITE_API_URL sample
    └── src/
        ├── App.jsx       # nav, mobile menu, random, routes
        ├── index.css     # full theme (black + orange "juice" palette)
        ├── api.js        # API client + imgProxy helper
        ├── pages/        # Home, Browse, Anime, Watch
        └── components/   # Card, VideoPlayer, EpisodePicker

Deploy

kenpyTV is two deployables: the FastAPI backend (persistent Python process) and the React frontend (static files). They connect through VITE_API_URL. The repo ships ready-to-use configs for the most common hosts.

1. Backend — pick one Python host

The backend must be a persistent process (not serverless) because it streams large HLS responses and keeps a hot cache. Container/VM hosts work best.

  • Render — use backend/render.yaml (Blueprints): Import repo → it builds & runs uvicorn app:app automatically.
  • Railway — add a service from the backend/ directory. Railway reads backend/Procfile; set the start command if needed: uvicorn app:app --host 0.0.0.0 --port $PORT.
  • Fly.io / any Docker hostbackend/Dockerfile is provided: fly launch from backend/, or docker build -t kenpytv-api backend && docker run -p 8000:8000 kenpytv-api.
  • Any VPSuvicorn app:app --host 0.0.0.0 --port 8000 behind nginx/Caddy.

CORS is already wide open (allow_origins=["*"]), and all proxy URLs are built from the incoming request host, so the same backend works on any deployed domain.

2. Frontend — Vercel (or any static host)

Vercel:

  1. Import the repo, set Root Directory to frontend.
  2. Vite is auto-detected; frontend/vercel.json adds an SPA rewrite so deep links like /anime/<id> work.
  3. Add an environment variable:
    • VITE_API_URL = your backend URL, e.g. https://your-api.onrender.com
  4. Deploy. Each deploy runs npm run build with that env baked in.

Netlify / Cloudflare Pages / GitHub Pages: same idea — build frontend with npm run build, set VITE_API_URL at build time, and add an SPA rewrite to index.html (Netlify: _redirects with /* /index.html 200).

The Vite /api proxy only exists for local dev (frontend/vite.config.js). In production the app calls the backend via VITE_API_URL (see frontend/.env.example).

Gotcha: no-URL proxies

If you leave VITE_API_URL empty in production, the frontend will call /api/* on its own domain and get 404s. Always set VITE_API_URL to the backend URL.

Notes / gotchas

  • Some embed hosts send X-Frame-Options/frame-ancestors headers — the "Original player" iframe fallback may be blocked for them, but "Open in New Tab" always works.
  • HLS raw CDN URLs return 403 without a proper Referer — always go through /api/hls-proxy.
  • The orange-on-black theme is pure CSS (index.css :root tokens); tweak the palette there.

About

Free anime streaming site — FastAPI (Python) backend + React (Vite) frontend with a custom hls.js player. Scrapes [anikoto.cz](https://anikoto.cz), proxies its HLS streams and poster images, and serves a modern mobile-friendly UI.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages