XVB3 Documentation
XVB3 is a browser-based IPTV player. It loads M3U playlists, matches channels against XMLTV programme guides, and presents live TV through a Google TV-inspired interface that adapts its color palette to each channel's logo.
This guide covers everything you need to set up playlists, configure EPG sources, understand playback engine selection, and avoid common compatibility issues.
What XVB3 does
- Loads M3U playlists from remote URLs or local file uploads
- Matches channels against XMLTV EPG guides using
tvg-idand display name - Extracts the dominant color from each channel logo and applies a Material You tonal palette
- Selects the correct playback engine automatically — hls.js, dash.js, mpegts.js or native HTML5
- Presents a separate desktop interface (Google TV style) and a mobile interface (YouTube style)
What XVB3 does not do
- It does not provide channels, credentials, stream URLs or IPTV subscriptions
- It does not bypass authentication, DRM systems other than ClearKey, or geo-restrictions
- It does not store stream data — everything is fetched directly by your browser
playlist_playAdding playlists
XVB3 supports two methods for loading playlists: remote URL and local file upload.
Remote URL
The most common method. The app fetches the M3U file at startup and caches a local copy. On subsequent loads it serves the cache immediately while fetching a fresh copy in the background.
Open Settings
Tap the settings icon in the top-right corner of the app. This opens the full Settings panel.
Go to Playlists
Select the Playlists tab in the left sidebar. You will see the Playlist Manager.
Add by URL
Paste your M3U URL in the Add by URL field and tap the add button. The URL must start with https://.
Reload
The app reloads automatically. Your channels appear grouped by the group-title attribute from the M3U file.
Local file upload
If your playlist is a local .m3u or .m3u8 file, use the Upload local file option in the Playlist Manager. The file is stored in localStorage — no external server is involved. File size is limited by the browser's localStorage quota (typically 5–10 MB).
Multiple playlists
XVB3 supports multiple playlists simultaneously. All channels are merged into a single channel list grouped by their group-title. Channels from different playlists can share the same group name and will appear together.
descriptionM3U format
XVB3 follows the standard extended M3U format. The following attributes on the #EXTINF line are recognised:
| Attribute | Description | Required |
|---|---|---|
| tvg-id | Channel identifier used for EPG matching. Must match the channel attribute in your XMLTV file. For channels supported by the XVB EPG service, this can also be a numeric ID (see epg-id below). | Recommended |
| tvg-name | Display name shown in the channel list. Falls back to the name after the comma if omitted. | Optional |
| tvg-logo | URL of the channel logo. Used for the card thumbnail, hero background color extraction and player background. | Optional |
| group-title | Category name. Channels are grouped and the top bar category tabs are built from this value. | Recommended |
| epg-id | Numeric channel ID for on-demand EPG lookup via the XVB EPG service. When present, this takes priority over tvg-id for EPG resolution and enables faster, more accurate programme data without loading a full XMLTV file. | Optional |
| license-details | ClearKey DRM credentials in kid_hex:key_hex format. Required only for encrypted DASH streams. | Optional |
Example
#EXTM3U # Standard HLS channel #EXTINF:-1 tvg-id="channel-one.example" tvg-name="Channel One" tvg-logo="https://example.com/logo1.png" group-title="National",Channel One https://example.com/channel1/master.m3u8 # Channel with numeric EPG ID #EXTINF:-1 epg-id="100" tvg-name="Channel Two" tvg-logo="https://example.com/logo2.png" group-title="National",Channel Two https://example.com/channel2/master.m3u8 # ClearKey DRM DASH stream #EXTINF:-1 tvg-id="channel-drm.example" license-details="a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4:0011223344556677889900aabbccddee" group-title="Premium",Premium Channel https://example.com/premium/live.mpd # Iframe embed #EXTINF:-1 tvg-name="Web Player Channel" group-title="Free",Web Player Channel https://example.com/embed/live-channel
#EXTINF line. Blank lines between them will cause the channel to be skipped.calendar_todayIncluded EPG guides
The following guides are built into XVB3 and loaded automatically at startup. No configuration is needed.
| Guide | Coverage | Update frequency |
|---|---|---|
| epg-it.xml | Italy — national DTT channels | Every 6 hours |
| epg-plutotv-it.xml | Italy — Pluto TV channels | Every 6 hours |
| epg-samsung-it.xml | Italy — Samsung TV Plus channels | Every 6 hours |
Channels with a numeric epg-id attribute use the XVB EPG service — programme data is fetched on demand when you select a channel, rather than loading a full XMLTV file at startup. This is faster and more accurate for supported channels. The service covers the majority of Italian national and satellite channels.
The United Kingdom EPG is not included by default but is available as a custom source (see below). Guides for Spain and France are available in the xvb-epg repository.
add_circleAdding custom EPG sources
You can add any XMLTV-compatible guide URL in Settings → EPG Guide. Both plain .xml and gzip-compressed .xml.gz feeds are supported.
Open Settings → EPG Guide
Tap the settings icon and select the EPG Guide tab.
Paste the URL
Enter the full XMLTV URL in the input field. You can optionally give it a name for easier identification.
Save and reload
Tap Add. The guide will be fetched the next time the app starts or EPG refreshes (every 15 minutes).
UK EPG
The UK guide is available at:
https://raw.githubusercontent.com/xvb-lab/xvb-epg/main/epg/epg-uk.xml
Add this URL in the EPG Guide settings to enable programme information for UK channels.
Using epg-id for on-demand EPG
The epg-id attribute enables a faster alternative to XMLTV-based matching. Instead of loading a full guide file, XVB3 fetches programme data on demand from the XVB EPG service when the channel is selected.
This is the recommended approach for channels with a known numeric ID, as it skips the XMLTV parsing step entirely and returns accurate, up-to-date data for that specific channel only.
Timeshift support
You can apply a time offset to any numeric epg-id by appending +N or -N (hours). This is useful for regional variants of a channel that broadcast the same content with a fixed delay:
# Same channel, delayed by 1 hour #EXTINF:-1 epg-id="100+1" tvg-name="Channel One +1" group-title="National",Channel One +1 https://example.com/channel1-plus1/master.m3u8
epg-id and tvg-id are present on the same channel, epg-id is used and XMLTV matching is skipped entirely for that channel.linkHow EPG matching works
XVB3 uses a two-track system to match channels to EPG data:
Track 1 — Numeric ID (XVB EPG service)
If a channel has a numeric epg-id attribute (e.g. epg-id="100"), XVB3 queries the XVB EPG service directly for that channel's programme data. The request is made on demand when the channel is selected and the result is cached for the session. This avoids loading large XMLTV files for channels where fast, per-channel lookups are available.
Track 2 — XMLTV matching
For all other channels, XVB3 looks up the channel in the loaded XMLTV data. The lookup uses a normalised key derived from the tvg-id attribute or, as a fallback, the channel display name. Normalisation strips accents, punctuation, common suffixes (HD, SD, UHD, UK, IT) and converts to lowercase, so Rai 1 HD and rai1 will both match Rai1.it.
tvg-id to the exact channel ID used in your XMLTV file. Relying on name matching works but is less reliable, especially for channels with common short names.EPG ID formats
| Format | Example | Source |
|---|---|---|
| Numeric | 100, 200, 350 | XVB EPG service, on demand |
| Numeric + timeshift | 100+1 | XVB EPG service, offset by N hours |
| rai-* | rai-1, rai-news-24 | XMLTV (epg-it.xml) |
| Samsung IT* | ITBA123456 | XMLTV (epg-samsung-it.xml) |
| Pluto UUID | 5f6de5b9b2631e6e... | XMLTV (epg-plutotv-it.xml) |
| *.uk, *.it | BBC1.uk, LA7.it | XMLTV from matching guide |
play_circlePlayback engines
XVB3 selects the playback engine automatically based on the stream URL. No configuration is needed in most cases.
| Format | Engine | Notes |
|---|---|---|
| .m3u8 / HLS | hls.js | Adaptive bitrate. Quality level selector available during playback. |
| .mpd / DASH | dash.js | Adaptive bitrate. ClearKey DRM via license-details. |
| .mpd + DRM (fallback) | Shaka Player | Used automatically if dash.js DRM fails. |
| .ts / MPEG-TS | mpegts.js | Live buffer mode. Low latency. |
| .mp4, .aac, .mp3 | HTML5 native | Progressive download or direct play. |
| Iframe patterns | Embedded iframe | For Pluto TV, livetvuk.com, and similar web players. |
Ambiguous URLs
If the URL has no recognised extension, XVB3 sends a HEAD request and inspects the Content-Type response header to determine the format. This adds a small delay before playback starts. To avoid it, ensure your stream URLs contain the correct extension.
Safari
Safari supports HLS natively via the <video> element. On Safari, XVB3 bypasses hls.js for HLS streams and uses native playback directly, which is more efficient and compatible with iOS fullscreen.
lockDRM / ClearKey
XVB3 supports ClearKey DRM for DASH streams. ClearKey is an open, non-proprietary scheme where the decryption key is provided directly in the playlist metadata — no license server is involved.
Format
Add the license-details attribute to your #EXTINF line with the key ID and key in hexadecimal format separated by a colon:
license-details="kid_in_hex:key_in_hex"
0x prefix. A typical KID is 32 hex characters (16 bytes); a typical key is also 32 characters.Engine fallback
XVB3 first attempts ClearKey decryption using dash.js. If that fails (for example due to a quirk in how dash.js handles the key format), it automatically retries with Shaka Player. If both fail, an error is shown.
webIframe streams
Some channels — particularly free ad-supported services like Pluto TV — cannot be played via a direct stream URL. They require their own web player to function. XVB3 handles these by embedding them in an iframe instead of using a video engine.
Recognised iframe patterns
| Pattern | Service |
|---|---|
| pluto.tv/live-tv/watch/ | Pluto TV |
| livetvuk.com/embed/ | LiveTVUK |
| livehdtv.com/ | LiveHDTV |
| app-philipsnovatek | Philips Novatek |
If the stream URL contains any of these patterns, XVB3 automatically switches to iframe mode. The URL has ?autoplay=1 appended where possible.
securityCORS — Cross-Origin Resource Sharing
CORS is the most common reason why streams and EPG guides fail silently in a browser-based player.
What is CORS?
When your browser fetches a resource from a different domain (e.g. your M3U is on cdn.example.com and the app is on xvb-app.pages.dev), the server must explicitly permit cross-origin requests by including the header:
Access-Control-Allow-Origin: *
If this header is absent, the browser blocks the request and XVB3 will silently fail to load the resource.
CORS and stream URLs
Stream URLs (.m3u8, .mpd, .ts) are subject to CORS when loaded via hls.js, dash.js or mpegts.js. Many CDN providers and IPTV servers do include the necessary headers — but not all.
CORS and EPG guides
XMLTV files hosted on GitHub raw URLs (raw.githubusercontent.com) include CORS headers and load correctly. If you host your own XMLTV file, ensure the server sets Access-Control-Allow-Origin: *.
CORS and channel logos
Logo images are loaded via <img> tags and do not require CORS for display. However, the dominant color extraction feature uses a canvas to read pixel data — this requires the image to be served with CORS headers. If the logo server does not allow cross-origin access, color extraction falls back to a default purple palette.
warningMixed content
Mixed content refers to loading http:// resources from an https:// page. Modern browsers block this by default.
The problem
XVB3 is served over HTTPS. If your stream URLs use http:// instead of https://, the browser will block the request with a mixed content error. This cannot be overridden by the application.
Solutions
- Use HTTPS streams. The best and only reliable solution. Ask your provider to enable HTTPS or use a reverse proxy that terminates TLS.
- Self-host with HTTP. If you run XVB3 locally over
http://localhost, mixed content restrictions do not apply. This is a valid workflow for local use. - Browser flag (not recommended). Some browsers allow insecure content for specific sites via a flag, but this is a security risk and not a permanent solution.
infoKnown limitations
| Limitation | Details |
|---|---|
| HTTP streams over HTTPS | Blocked by browser mixed content policy. No workaround from the app. |
| CORS-restricted streams | Streams without CORS headers fail silently. Use streams from CORS-enabled CDNs. |
| Widevine / PlayReady DRM | Not supported. Only ClearKey is available. |
| EPG for unsupported channels | Channels not covered by the XVB EPG service or your XMLTV file will show no programme data. |
| Geo-restricted streams | The app cannot bypass IP-based geo-restrictions. |
| Large local playlists | localStorage is limited to ~5–10 MB. Very large M3U files should be hosted remotely. |
| Safari iframe autoplay | Iframe streams may require a user gesture to start on Safari due to autoplay policies. |
| MPEG-TS on iOS | mpegts.js requires MSE (Media Source Extensions) which is not fully supported on iOS Safari. |
listSettings — Playlist Manager
Found under Settings → Playlists. This panel manages all playlist sources.
Download from XVB server
Pre-built playlists curated and maintained by the XVB team are available for direct download. These are tested for compatibility and include correctly formatted tvg-id and epg-id attributes.
Add by URL
Paste any publicly accessible M3U URL. The file is fetched immediately, validated and cached. The URL is stored for background refresh on future app loads.
Upload local file
Upload a .m3u file from your device. The file content is stored in localStorage. Useful for private playlists that should not be fetched over the network.
Managing saved playlists
Each saved playlist shows its name and source type. You can remove individual playlists using the delete button. The app reloads after any change.
rss_feedSettings — EPG Guide
Found under Settings → EPG Guide.
The Italy EPG and UK EPG are shown as built-in entries and are always active. Below them, you can add additional XMLTV sources by URL.
Adding a custom source
Enter a valid XMLTV URL and an optional name, then tap Add. Both .xml and .xml.gz feeds are supported. The guide is loaded on next app start.
Removing a custom source
Tap the delete icon next to any custom source in the Saved EPG sources list. Built-in guides cannot be removed.
account_circleSettings — Profile
Found under Settings → Profile. Set a display name and upload an avatar image. These are stored locally in localStorage and shown in the top bar of the app.
Tap the avatar circle to upload an image. The image is stored as a base64 string. For best results use a square image under 200 KB.
appsSettings — App shortcuts
Found under Settings → Apps (desktop only). This panel manages the icon row shown in the footer of the home screen.
Default shortcuts
XVB3 includes a default set of streaming service shortcuts: Netflix, YouTube, Prime Video, Disney+, Apple TV+, Max, Spotify, RaiPlay, Mediaset Infinity, DAZN, Now TV and YouTube Music.
Adding a custom shortcut
Enter the app name and URL. Optionally tap the icon circle to upload a custom icon image. If no image is uploaded, the favicon from the URL domain is used automatically.
Changing an icon
In the Saved apps list, tap the round icon next to any entry to upload a replacement image.
Restoring removed apps
Tap Restore removed apps to see a list of default shortcuts that have been deleted. Tap the plus button to add any of them back individually.
XVB3 is a neutral playback interface. It does not provide, host or distribute any media content, channels, credentials or IPTV subscriptions. Use it only with playlists and streams you are authorised to access. — GitHub · MIT License