StreamVault

April 19, 2026 · View on GitHub

A browser-based IPTV client — no app install, no subscription, bring your own service.

Try it now: https://portalheaven.stream/

Supports Xtream Codes, M3U playlists, Stalker/Ministra portals, and direct HLS/MP4 URLs.


Features

CategoryDetails
Live TVChannel grid with logos, EPG now-playing, quick channel switcher
Movies & SeriesPoster grid with year, rating, seasons/episodes, resume progress
TV GuideXMLTV EPG grid — load any provider's XML feed
Global SearchSearches live, movies, and series simultaneously
FavoritesPer-profile favorites across all content types
Continue WatchingWatch history with resume support (last 60 items)
ThemesDark, Navy, AMOLED, Forest
PlayerHLS.js + mpegts.js, keyboard shortcuts, PiP, OSD overlay
Offline-readyIndexedDB caching — channels/categories persist across sessions

Player keyboard shortcuts: Space play/pause · F fullscreen · M mute · ←→ ±10s or channels · ↑↓ volume or channels · P PiP · Esc close


Architecture

┌─────────────────────────────────────────────────────────────┐
│  Browser (React SPA)                                        │
│  streamvault/src/App.jsx                                    │
│  - IndexedDB for offline content cache                      │
│  - HLS.js / mpegts.js for playback                         │
└────────┬───────────────────────────┬────────────────────────┘
         │                           │
         ▼                           ▼
┌─────────────────────┐   ┌──────────────────────────────────┐
│  stalker-proxy       │   │  CF Worker (optional)            │
│  Express on Node.js  │   │  streamvault-worker/             │
│  - Stalker handshake │   │  - Stalker/Xtream/M3U proxy     │
│  - CORS proxy        │   │  - Stream proxy (HTTP→HTTPS)     │
│  - Stream proxy      │   │  - D1 database (persistent)      │
│  Deploy: Koyeb/      │   │  - KV cache (session paths)      │
│    Railway/Render     │   │  - Usage analytics               │
└─────────────────────┘   └──────────────────────────────────┘

You can run either the stalker-proxy (simple) or the CF Worker (full-featured), or both.


Project structure

StreamVault/
├── streamvault/              # React + Vite frontend
│   ├── src/App.jsx           # Entire app (single-file architecture)
│   ├── functions/worker.js   # CF Pages stream proxy (legacy)
│   └── .env.example
├── stalker-proxy/            # Node.js CORS proxy
│   ├── src/index.js          # Express server
│   ├── koyeb.yaml            # Koyeb deploy config
│   ├── railway.json          # Railway deploy config
│   └── .env.example
└── streamvault-worker/       # Cloudflare Worker (optional)
    ├── src/
    │   ├── index.js           # Router + CORS
    │   ├── handlers/          # stalker, stream, catalog, analytics
    │   └── utils/             # auth, cors, stalker session mgmt
    ├── migrations/            # D1 database schema
    └── wrangler.toml

Quick start (local dev)

1. Clone

git clone https://github.com/YOUR-USERNAME/StreamVault.git
cd StreamVault

2. Start the proxy (needed for Stalker portals and CORS)

cd stalker-proxy
cp .env.example .env
npm install
npm start
# Runs at http://localhost:3001

3. Start the frontend

cd streamvault
cp .env.example .env
npm install
npm run dev
# Runs at http://localhost:5173

4. Connect

Open http://localhost:5173 and choose a connection type:

TypeWhat you need
Xtream CodesServer URL, username, password
M3U PlaylistDirect .m3u or .m3u8 URL
Stalker PortalPortal URL, MAC address (proxy must be running)
Direct HLSAny .m3u8 or media URL

Environment variables

Frontend (streamvault/.env)

VariableDefaultDescription
VITE_PROXY_URLhttp://localhost:3001Stalker proxy / Koyeb backend URL
VITE_CATALOG_URLsame as PROXYCF Worker URL for catalog API (optional)
VITE_STREAM_PROXY_URLsame as PROXYStream proxy URL (optional, for split routing)

Proxy (stalker-proxy/.env)

VariableDefaultDescription
PORT3001Server port
ALLOWED_ORIGIN*CORS origin — set to your frontend URL in production

Deploying (free tier)

Frontend — Cloudflare Pages

  1. Fork this repo
  2. Go to pages.cloudflare.com → Create project → Connect to Git
  3. Root directory: streamvault · Build: npm run build · Output: dist
  4. Add env var: VITE_PROXY_URL = your proxy URL
  5. Deploy
  1. Go to koyeb.com → Create App → GitHub
  2. Select your fork, work directory: stalker-proxy
  3. Build: npm install · Run: npm start
  4. Add env var: ALLOWED_ORIGIN = your Pages URL
  5. Deploy

koyeb.yaml pre-fills these settings. Also works on Railway or Render.

CF Worker (optional, replaces proxy)

cd streamvault-worker

# Create resources
wrangler kv namespace create SV_CACHE
wrangler d1 create streamvault-db

# Add the returned IDs to wrangler.toml
# Run migrations
wrangler d1 migrations apply streamvault-db

# Deploy
wrangler deploy

Set VITE_CATALOG_URL in your frontend to the Worker URL.


Proxy API

Stalker endpoints

EndpointMethodDescription
/stalker/handshakePOSTToken handshake with portal
/stalker/channelsGETAll live channels with genres
/stalker/vod/categoriesGETVOD category list
/stalker/vodGETVOD items by category
/stalker/series/categoriesGETSeries category list
/stalker/seriesGETSeries items by category
/stalker/series/seasonsGETSeasons and episodes for a series
/stalker/streamGETResolve stream cmd to playable URL
/stalker/epgGETEPG program data
/stalker/profileGETSTB profile info
/stalker/apiGETGeneric portal API passthrough

Utility endpoints

EndpointMethodDescription
/streamGETProxy HTTP streams over HTTPS with HLS manifest rewriting
/proxyGETGeneric CORS proxy for any URL
/healthGETHealth check

All endpoints return JSON with CORS headers (Access-Control-Allow-Origin: *).


How it works

Stream routing

ProtocolPath
Stalker (HTTPS page)Browser → Proxy /stalker/play → Portal create_link → Proxy /stream → IPTV server
Xtream (HTTPS page)Browser → Proxy /proxy → Xtream API; Browser → Proxy /stream → TS/HLS stream
M3U (HTTPS page)Browser → Proxy /proxy → M3U fetch; Browser → Proxy /stream → stream
Any (HTTP page)Browser → IPTV server directly (no proxy needed)

Stalker session management

Stalker portals require a specific handshake flow:

  1. Path discovery — try multiple API paths (server/load.php, portal.php, etc.)
  2. Handshake — get a session token tied to the MAC address
  3. Token refresh — auto-refresh on 401 responses
  4. create_link — resolve channel commands to stream URLs (tokens may be IP-bound)

The proxy (and CF Worker) handle this transparently, including caching discovered paths.


Tech stack

LayerTechnology
FrontendReact 19, Vite 8, single-file App.jsx
PlayerHLS.js (adaptive), mpegts.js (raw TS), native <video>
ProxyNode.js 18+, Express, node-fetch
WorkerCloudflare Workers, D1 (SQLite), KV
StorageIndexedDB (browser), D1 (cloud sync)
StylingCSS-in-JS via template literal <style> tag

Disclaimer

StreamVault is a client application — it does not provide any IPTV content. You must supply your own IPTV service credentials. Ensure you comply with your provider's terms of service and local laws.


License

PolyForm Noncommercial 1.0.0 — free for personal and noncommercial use. Commercial use requires a separate license.