masqueradarr
concepts · 01 start from zero

What is IPTV — and what is masqueradarr?

No prior knowledge assumed. We'll define every word first, then show what masqueradarr does with them, and how it grew out of TVApp2.

01 Start from zero — the vocabulary

Seven words that unlock everything else

IPTV has a small vocabulary. Learn these seven and the rest of the docs read easily.

IPTVInternet Protocol TV
Live TV channels delivered over the internet instead of over cable, satellite or an antenna. The "channel" is just a video feed reachable at a URL.
PlaylistM3U / M3U8
A plain-text list of channels — each with a name, logo, group and where its stream lives. The .m3u file is the channel lineup your player loads. masqueradarr produces one for you.
GuideEPG / XMLTV
The Electronic Program Guide — the "what's on, and when" grid. XMLTV is the standard file format that carries it. It pairs with the playlist by matching channel IDs.
Stream
The actual moving video for one channel. On the modern web it almost always arrives as a series of short clips the player fetches back-to-back (see HLS).
HLSHTTP Live Streaming
The common way live video is delivered: a small playlist of short video segments the player pulls one after another, re-checking for new ones. How masqueradarr serves the bytes — HLS vs. a raw stream — is the Video Proxy Engine story.
Aggregator
Software that gathers channels and guides from many separate services and presents them as one combined lineup. That's masqueradarr's core job.
Single, trusted identity
Instead of juggling many logins and URLs across providers, your media apps talk to one endpoint (masqueradarr) with one credential. It fans out to the real sources behind the scenes — that's the "masquerade".
the mental model

A playlist (.m3u) is which channels. A guide (XMLTV) is what's on them. A stream is the video itself. masqueradarr's job is to collect all three from many providers and hand your apps one of each.

02 What masqueradarr actually does

Many scattered sources in, one clean lineup out

The problem masqueradarr solves: IPTV channels are scattered across dozens of services, each with its own format, its own login, its own quirks. Pointing every media app at every provider is a mess. masqueradarr sits in the middle and does the collecting.

the aggregation pipeline providers → one catalog → your client
Pull
providers
M3U + EPG from ~17 sources & your imports
Normalize
one schema
dedupe · unify · store in MongoDB
Catalog
channels + guide
editable; your edits survive re-sync
Compose
.m3u + XMLTV
per-user, tokenized export
Play
your client
in-app player · TiviMate · Plex · …

Crucially, masqueradarr does not write dead stream URLs to disk. It stores an opaque pointer for each channel and resolves the real stream at the moment you press play. That single design choice is what lets it serve sources that need a login, an expiring token, or a rotating mirror — things static-file tools simply can't do.

03 From TVApp2 to masqueradarr

The same promise, rebuilt from the ground up

masqueradarr is the direct successor to TVApp2, which is now deprecated. It is not a fork or a patch — it's a ground-up re-architecture of the same idea, carrying the project into the *arr self-hosted media family (Sonarr, Radarr, …) it's named for.

● where it started · TVApp2

A static-file regenerator

One Docker container that, on a schedule, scraped a handful of providers and regenerated flat .m3u and .xml files for Jellyfin / Plex / Emby to ingest. It did one thing well: keep static playlists fresh.

But streams were static URLs baked into files — so anything behind a login, device check, expiring token or rotating mirror couldn't be served. No database, no real UI, no per-user access, no live view of who's watching.

● where it's going · masqueradarr

A live delivery platform

Keeps the original promise — aggregate scattered IPTV into one playlist + guide — and rebuilds everything under it to lift those ceilings.

Static files become a resolve-on-demand engine; flat config becomes MongoDB + a Vue 3 SPA; bespoke scrapers become a source-agnostic adapter framework; and blind scheduling becomes live observability.

What got lifted

  • Static files → a live, resolve-on-demand engine. Streams resolve at play time through an HLS proxy — the thing that makes authenticated and rotating sources possible.
  • Flat config → MongoDB + a real management SPA. State lives in MongoDB; the front end is a full Vue 3 single-page app.
  • Bespoke scrapers → a source-agnostic adapter framework. Adding a provider is one adapter file plus one registry line; the generic core never branches per source.
  • File server → an API + a live video proxy. An in-app player and M3U / XMLTV export, with playback served by a rebuilt, durable Rust engine (masq-proxy).
  • Env-var toggles → users, roles & per-user access. Real scrypt authentication, session vs. stream tokens, and per-user tokenized playlist access.
  • Blind scheduling → live observability. WebSocket-pushed viewer / bandwidth / buffering telemetry, live system stats, and MongoDB-backed logs.
coming from TVApp2?

There is no in-place upgrade path. masqueradarr is a new application with a new data model (MongoDB instead of flat files) — stand it up fresh and re-add your sources through the UI.

04 At a glance

TVApp2 vs. masqueradarr

The full before/after, feature by feature.

TVApp2 (deprecated)masqueradarr
RoleStatic M3U/XMLTV regeneratorLive IPTV aggregator + delivery platform
StreamsStatic URLs written to filesResolve-on-demand via HLS proxy
StateFlat files, no DBMongoDB (Mongoose 8)
FrontendLinks to generated filesVue 3 + Vite management SPA
BackendNode.js scriptsExpress 4 API (ESM, TypeScript)
SourcesHard-coded scrapersPluggable adapters + URL / HDHomeRun / file imports
Guide dataOne bundled XMLTV grabberGracenote, EPG-PW, Jesmann, Custom XMLTV + self-EPG
AuthNonescrypt users, roles, per-user access lists
Auth'd sourcesNot possibleSupported (streamed-login session capture)
External clientsPass-through onlyM3U / XMLTV export + live Rust HLS / raw-TS proxy
Video engineNone (static URLs)Remux-free Rust data-plane proxy (retry / failover / raw-TS)
ObservabilityLogsLive WS telemetry, history / metrics, system stats, app logs
BackupNoneFull-system gzip backup / restore + scheduled backups
Base imageAlpine + s6-overlayDebian bookworm (glibc) + tini
ConfigEnvironment variablesDB-backed settings + minimal .env bootstrap
05 The shape of it

How the pieces fit together

Everything above lives in one container that runs two processes. Your apps talk to the Node control plane; a Rust data-plane sidecar moves the actual stream bytes. Keep this picture in mind — the rest of the docs zoom into each box.

primary architecture clients · container · upstream
clients
Browser
Vue 3 management SPA
IPTV clients
TiviMate · VLC · Plex · Jellyfin
/api/* · WS · .m3u · bytes
masqueradarr container
one image · two processes
Express API — Node
control plane · the brains
gate + relay ↓
masq-proxy — Rust
data plane · the muscle
internal seams ↑ loopback
MongoDB
all the state
resolve · fetch · rewrite · pipe
upstream
Upstream IPTV sources
dulo · DaddyLive · Pluto · Roku · …
honest scope

The rename and re-architecture are effectively complete — codebase, brand, runtime and Docker images are all masqueradarr. Playback is live over the Rust engine (HLS + raw-TS); the few remaining remux-dependent paths (e.g. HDHomeRun TS→HLS) are still pending a rebuild.

README.md · What is masqueradarr · Evolution · At a glance Primary Architecture · the two-plane container next → Getting started
masqueradarr · concepts next → getting started