# How to Integrate EPG (Electronic Program Guide) with IPTV Channels in Free-TV/IPTV

> Learn to integrate EPG with IPTV channels using Free-TV/IPTV. Configure global EPG sources and add EPG IDs to your channel entries for a seamless viewing experience.

- Repository: [Free TV/IPTV](https://github.com/Free-TV/IPTV)
- Tags: how-to-guide
- Published: 2026-06-26

---

**Integrating EPG with IPTV channels in the Free-TV/IPTV repository requires configuring global EPG sources in [`epglist.txt`](https://github.com/Free-TV/IPTV/blob/main/epglist.txt) and adding EPG IDs to channel entries in the Markdown list files, which [`make_playlist.py`](https://github.com/Free-TV/IPTV/blob/main/make_playlist.py) automatically converts into M3U playlist attributes.**

The **Free-TV/IPTV** project generates M3U playlists from Markdown-based channel lists. EPG integration is handled automatically by the [`make_playlist.py`](https://github.com/Free-TV/IPTV/blob/main/make_playlist.py) script, which embeds global EPG URLs in the playlist header and injects `tvg-id` attributes into individual channel entries based on the sixth column of the source tables.

## How EPG Integration Works in Free-TV/IPTV

The repository implements a two-layer EPG integration strategy that separates global source configuration from per-channel identifier assignment.

### Global EPG Sources via [`epglist.txt`](https://github.com/Free-TV/IPTV/blob/main/epglist.txt)

The [`epglist.txt`](https://github.com/Free-TV/IPTV/blob/main/epglist.txt) file contains URLs of publicly available EPG XML files. During playlist generation, the `main()` function in [`make_playlist.py`](https://github.com/Free-TV/IPTV/blob/main/make_playlist.py) (lines 31-34) reads this file, joins the URLs with commas, and injects them into the M3U header using the `x-tvg-url` attribute:

```python
processed_epg_list = ", ".join(epg_urls)
head_playlist = f'#EXTM3U x-tvg-url="{processed_epg_list}"\n'

```

### Channel-Level EPG IDs

Individual channels specify their EPG mappings through the **Channel** class defined in [`make_playlist.py`](https://github.com/Free-TV/IPTV/blob/main/make_playlist.py). The `__init__()` method (lines 94-112) parses Markdown table rows and extracts the sixth column (index 5) as the EPG identifier:

```python
if len(parts) > 6:
    self.epg = parts[5].strip()  # Extract EPG ID from sixth column

else:
    self.epg = None

```

The `to_m3u_line()` method (lines 115-121) conditionally adds the `tvg-id` attribute when rendering the EXTINF line:

```python
if self.epg is None:
    return f'#EXTINF:-1 tvg-name="{self.name}" tvg-logo="{self.logo}"...'
else:
    return f'#EXTINF:-1 tvg-name="{self.name}" tvg-logo="{self.logo}" tvg-id="{self.epg}"...'

```

## Step-by-Step Implementation Guide

### Configure Global EPG Sources

Edit [`epglist.txt`](https://github.com/Free-TV/IPTV/blob/main/epglist.txt) in the repository root to add or update EPG XML URLs. Append one URL per line:

```text
https://epgshare01.online/epgshare01/epg_ripper_US1.xml.gz
https://epgshare01.online/epgshare01/epg_ripper_US2.xml.gz

```

These URLs populate the `x-tvg-url` header attribute in generated playlists, enabling EPG-aware players like Kodi, Plex, or VLC to retrieve program data.

### Assign EPG IDs to Individual Channels

Open the appropriate Markdown file in the `lists/` directory (e.g., [`lists/usa.md`](https://github.com/Free-TV/IPTV/blob/main/lists/usa.md)). Add the EPG identifier as the **sixth column** in the pipe-delimited table:

```markdown
| 12 | News Channel | (http://stream.example.com/news.m3u8) | <img src="logo.png"> | epg_news_01 |

```

The column order is: channel number, name, stream URL, logo, EPG ID. If the EPG ID is present, the [`make_playlist.py`](https://github.com/Free-TV/IPTV/blob/main/make_playlist.py) script extracts it and assigns it to the channel's `tvg-id` attribute.

### Regenerate the Playlists

Execute the playlist generator to apply your changes:

```bash
python3 make_playlist.py

```

The script outputs:
- `playlist.m3u8` – the master playlist containing all channels
- `playlists/playlist_*.m3u8` – per-country playlists

Each generated file includes the global EPG header and individual `tvg-id` attributes for channels that have EPG mappings defined.

## Code Implementation Details

The complete transformation from Markdown entry to M3U line follows this execution path in [`make_playlist.py`](https://github.com/Free-TV/IPTV/blob/main/make_playlist.py):

```python
class Channel:
    def __init__(self, group, md_line, country_code=""):
        parts = md_line.split('|')
        # ... parsing logic for name, url, logo ...

        
        if len(parts) > 6:
            self.epg = parts[5].strip()  # EPG ID extraction

        else:
            self.epg = None

    def to_m3u_line(self):
        chno = f' tvg-chno="{self.chno}"' if self.chno else ""
        country = f' tvg-country="{self.country}"' if self.country else ""
        
        if self.epg is None:
            return f'#EXTINF:-1 tvg-name="{self.name}" tvg-logo="{self.logo}"{chno}{country} group-title="{self.group}",{self.name}\n{self.url}'
        else:
            # Include tvg-id when EPG is defined

            return f'#EXTINF:-1 tvg-name="{self.name}" tvg-logo="{self.logo}" tvg-id="{self.epg}"{chno}{country} group-title="{self.group}",{self.name}\n{self.url}'

```

This produces playlist entries like:

```

#EXTM3U x-tvg-url="https://epgshare01.online/epgshare01/epg_ripper_US1.xml.gz"
#EXTINF:-1 tvg-name="News Channel" tvg-logo="logo.png" tvg-id="epg_news_01" group-title="USA",News Channel
http://stream.example.com/news.m3u8

```

## Summary

- **Global EPG configuration** happens in [`epglist.txt`](https://github.com/Free-TV/IPTV/blob/main/epglist.txt), which [`make_playlist.py`](https://github.com/Free-TV/IPTV/blob/main/make_playlist.py) reads to populate the `x-tvg-url` playlist header.
- **Per-channel EPG mapping** uses the sixth column in Markdown list files, parsed by the `Channel` class as the `tvg-id` attribute.
- **Automatic generation** occurs when running `python3 make_playlist.py`, producing M3U files ready for EPG-compatible players.
- The implementation supports **multiple EPG sources** through comma-separated URLs and **selective channel mapping** via optional EPG ID columns.

## Frequently Asked Questions

### What file format does Free-TV/IPTV use for EPG data?

The repository references standard **XMLTV format** files (typically `.xml` or `.xml.gz`) through the [`epglist.txt`](https://github.com/Free-TV/IPTV/blob/main/epglist.txt) configuration. The [`make_playlist.py`](https://github.com/Free-TV/IPTV/blob/main/make_playlist.py) script does not parse the EPG content itself; it only embeds the source URLs in the M3U header using the `x-tvg-url` attribute, leaving XML parsing to the IPTV player.

### Where exactly do I add the EPG ID in the channel list?

Add the EPG ID as the **sixth column** (fifth pipe-delimited field) in the Markdown table files located in `lists/`. The `Channel.__init__()` method in [`make_playlist.py`](https://github.com/Free-TV/IPTV/blob/main/make_playlist.py) extracts `parts[5]` (zero-indexed) when parsing each line, assigning it to `self.epg` only if the column exists and contains data.

### Can I use multiple EPG sources simultaneously?

Yes. The [`make_playlist.py`](https://github.com/Free-TV/IPTV/blob/main/make_playlist.py) script concatenates all URLs from [`epglist.txt`](https://github.com/Free-TV/IPTV/blob/main/epglist.txt) into a single comma-separated string for the `x-tvg-url` attribute. This allows players to query multiple EPG repositories to resolve program data for different channel sets or regions.

### How do I verify that EPG integration is working correctly?

After running `python3 make_playlist.py`, inspect the generated `playlist.m3u8` file. Verify that the header contains `#EXTM3U x-tvg-url="..."` with your EPG URLs, and that specific channels include `tvg-id="your_epg_id"` attributes. Load the playlist in an EPG-aware player like Kodi or VLC to confirm program guide data appears alongside the channels.