Education·8 min

By Sam Ellis

What an XMLTV EPG File Actually Looks Like (With Examples)

The fastest way to stop being confused by program guides is to open one and read it. XMLTV is plain XML — verbose, but not complicated — and ten minutes with a real example will save you hours of guessing at why your guide is empty.

This post shows a real file, decodes it tag by tag, and then uses that understanding to explain the single most common guide failure.

The honest framing: Tuneline is a media player for content you provide. It displays a guide from a schedule source you supply. It ships with no guide and no content.

The Structure in One Sentence

An XMLTV file has exactly two kinds of thing in it: <channel> elements that declare what exists, and <programme> elements that say what's on when.

That's it. Everything else is detail.

A Minimal, Complete Example

<?xml version="1.0" encoding="UTF-8"?>
<tv generator-info-name="example-grabber">

  <channel id="example.news.us">
    <display-name>Example News</display-name>
    <icon src="http://logos.example/news.png" />
  </channel>

  <programme start="20260806180000 +0000"
             stop="20260806190000 +0000"
             channel="example.news.us">
    <title lang="en">Evening Report</title>
    <desc lang="en">The day's headlines and analysis.</desc>
    <category lang="en">News</category>
  </programme>

</tv>

That is a valid, complete guide describing one source and one hour of schedule. A real file is the same two shapes repeated thousands of times.

Decoded Tag by Tag

ElementWhat it does
<tv>The root. Everything lives inside it.
<channel id="…">Declares a source. The id is the important part — it's the join key.
<display-name>Human-readable name shown in the guide.
<icon src="…">Logo URL.
<programme start stop channel>One scheduled item. channel must match a <channel id>.
<title>Program name.
<desc>Synopsis.
<category>Genre. This is what parental controls and filters act on.

The timestamp format catches everyone

start="20260806180000 +0000"

Read as YYYYMMDDHHMMSS followed by a UTC offset. So that's 6 Aug 2026, 18:00:00 UTC.

The offset is the part that matters. If a file omits it, or declares one that doesn't match reality, your guide loads perfectly and shows everything at the wrong time. That is a completely different problem from an empty guide, and it's fixed in your timezone settings, not by changing sources. (Wrong times fix.)

The Join: Why Your Guide Is Empty Even Though the File Loaded

Here's the thing worth understanding, because it explains most guide complaints.

Your playlist and your guide are two separate files that have to be matched up. The match happens on an ID.

In the M3U:

#EXTINF:-1 tvg-id="example.news.us" tvg-logo="…",Example News
http://example.com/news.m3u8

In the XMLTV:

<channel id="example.news.us">

tvg-id must equal channel id. Exactly — including case and punctuation.

When they match, the entry shows its schedule. When they don't, you get an entry with a blank guide, and the file was never at fault. (The M3U side of this.)

This is why "I added a guide and nothing happened" is usually neither the playlist's fault nor the guide's. It's that nobody made them agree on identifiers. A guide that covers a different region than your playlist will load thousands of programmes that match none of your entries.

Adding a guide source

How to Inspect a Guide Source Before Trusting It

Before you blame your player, look at the file.

1. Is it compressed? Many sources ship .xml.gz. That's normal — most players handle it. If you're inspecting by hand, decompress first.

2. Does it actually contain your sources? Search the file for one of your tvg-id values. If it isn't there, that guide doesn't cover your list, and no setting will change that.

curl -s "https://example.com/guide.xml.gz" | gunzip | grep -c "<channel "
curl -s "https://example.com/guide.xml.gz" | gunzip | grep "example.news.us"

The first tells you how many sources it declares. The second tells you whether yours is one of them.

3. Does it cover a useful time range? Check the earliest and latest start values. Some free guides carry only 24 hours; some carry two weeks. A guide that ended yesterday looks identical to a broken one.

4. How big is it? Full national guides run to tens or hundreds of megabytes uncompressed. That's normal, and it's why the first load can take minutes on a TV box. (Free XMLTV sources.)

Common Malformations

Real-world guide files break in predictable ways:

  • An HTML error page saved as .xml. Open it. If the first line is <!DOCTYPE html>, the download failed and saved the error.
  • Unescaped ampersands. A bare & instead of &amp; in a title is invalid XML and can abort the whole parse. One bad title, no guide at all.
  • Duplicate <channel id> entries. Two declarations of the same ID; behaviour depends on the player.
  • Programmes with no matching channel. Schedule entries whose channel attribute matches no declared <channel id>. They're silently dropped.
  • Missing stop times. Some grabbers omit them and expect the next programme's start to imply the end. Some players don't infer that, leaving gaps.

Can I Write or Edit One Myself?

Yes. It's XML, so any text editor works, and for a small curated setup it's entirely practical.

Useful edits:

  • Change a <channel id> to match the tvg-id your playlist already uses — often easier than editing hundreds of playlist lines.
  • Trim it down. Delete <channel> and <programme> elements you don't need. A smaller file loads much faster on constrained devices.
  • Fix the offset if every time is uniformly wrong.

Two rules: save as UTF-8, and keep it well-formed — one unescaped & can cost you the entire guide.

FAQ

What does an EPG file look like?

Plain XML with two kinds of element: <channel> declaring each source, and <programme> giving a start time, stop time and title for each scheduled item.

What format is XMLTV in?

XML, typically served as .xml or gzip-compressed .xml.gz. Timestamps are YYYYMMDDHHMMSS plus a UTC offset.

Why does my guide load but show nothing?

Almost always because your playlist's tvg-id values don't match the guide's <channel id> values. The file loaded fine; there was nothing to join it to.

How do I check whether a guide covers my sources?

Download it, decompress if needed, and search for one of your tvg-id strings. If it isn't in the file, that guide doesn't describe your list.

Why is my guide file so large?

A national guide with two weeks of schedule for hundreds of sources is genuinely tens or hundreds of megabytes. That's expected, and it's why first load is slow.

Can I edit an XMLTV file?

Yes, in any text editor. Save as UTF-8 and keep the XML well-formed — a single unescaped & can break the whole parse.

Bottom Line

  • XMLTV holds exactly two things: <channel> declarations and <programme> entries.
  • Timestamps are YYYYMMDDHHMMSS + UTC offset — a wrong offset means right data, wrong times.
  • The guide joins to your playlist on tvg-id = channel id, exactly. Mismatch is the top cause of an empty guide.
  • Inspect before blaming: decompress, grep for your ID, check the date range.
  • One unescaped & can invalidate an entire guide file.

Have a playlist and a guide URL? Download Tuneline — add both and the grid fills in. Free and ad-free.

— Sam Ellis

Share this article

The fast fix

Get Tuneline free

A clean, no-account media player for macOS, Windows, Linux, Android, TV, and iOS. Bring your own playlist.

Download free

The cross-platform media player behind these answers — new platforms, sync updates, the honest build story. No spam, unsubscribe anytime.

Tuneline is a media player application. It does not provide, host, or distribute any content. You bring your own playlist, exactly as you would with VLC.

#epg example#xmltv example#tv guide epg xml#xmltv format#epg guide url
Back to all posts