# How Channel Numbers Are Assigned and Used in the Free‑TV IPTV Playlist

> Discover how channel numbers are assigned and used in IPTV playlists. Learn how the tvg-chno attribute enables numeric display and direct selection in your IPTV client.

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

---

**Channel numbers in the Free‑TV IPTV playlist are defined manually in Markdown tables, parsed by [`make_playlist.py`](https://github.com/Free-TV/IPTV/blob/main/make_playlist.py), and exported as the `tvg-chno` attribute in the generated M3U‑8 file, allowing IPTV clients to display channels in numeric order and support direct channel selection.**

The Free‑TV/IPTV repository maintains a collaborative collection of public streaming channels organized by country. Understanding how channel numbers are assigned and used in the IPTV playlist requires examining the build pipeline that transforms human-editable Markdown tables into machine-readable M3U‑8 format.

## How Channel Numbers Are Defined in Source Markdown

Channel numbers originate in the `lists/*.md` files that populate the repository. Each Markdown file represents a country or region and contains a table where the first column (`#`) holds the channel number.

### The Markdown Table Structure

In the source files, the `#` column is treated as the authoritative channel identifier. For example, in [`lists/usa.md`](https://github.com/Free-TV/IPTV/blob/main/lists/usa.md), the table defines channels with specific numeric assignments:

```markdown
| #   | Channel        | Link  | Logo | EPG id |

|:---:|:--------------:|:-----:|:----:|:------:|
| 1   | Buzzr Ⓖ        | [>](https://buzzrota-ono.amagi.tv/playlist1080.m3u8) | <img src=".../Buzzr_logo.svg.png"/> | Buzzr.us |
| 2   | Retro TV       | [>](https://bcovlive-a.akamaihd.net/…) | <img src="https://i.imgur.com/PNTYOgg.png"/> | RetroTVEast.us |

```

Only rows containing the `[>]` link marker are processed into the final playlist, as noted in the repository documentation.

## How make_playlist.py Processes Channel Numbers

The transformation from Markdown table to M3U entry occurs in [`make_playlist.py`](https://github.com/Free-TV/IPTV/blob/main/make_playlist.py), which iterates through the Markdown files and extracts the channel metadata.

### Parsing and Normalization

When processing each line of a Markdown table, the script splits the row on the pipe character (`|`). According to lines 99-101 of [`make_playlist.py`](https://github.com/Free-TV/IPTV/blob/main/make_playlist.py), the second field (`parts[1]`) represents the channel number:

```python

# From make_playlist.py (lines 99-101)

parts = line.split('|')
chno = parts[1].strip()

```

The script normalizes the extracted value at lines 107-108. If the field is empty or contains `0`, the channel is treated as **unnumbered**:

```python

# Normalization logic (lines 107-108)

if chno == '' or chno == '0':
    chno = None

```

### Generating the tvg-chno Attribute

The `Channel` class encapsulates the channel data, and its `to_m3u_line()` method (lines 15-18) conditionally includes the `tvg-chno` attribute only when a number is present:

```python

# Channel.to_m3u_line() builds the EXTINF line

if self.chno:
    m3u_line += f' tvg-chno="{self.chno}"'

```

Additionally, the script derives the `tvg-country` attribute from the filename (e.g., [`usa.md`](https://github.com/Free-TV/IPTV/blob/main/usa.md) becomes `US`) and determines the `group-title` from either the filename or an `<h1>` tag in the Markdown file (lines 44-46).

## The Role of tvg-chno in IPTV Clients

The `tvg-chno` attribute in the final `playlist.m3u8` serves as a stable numeric identifier that IPTV clients utilize for:

- **Numeric ordering**: Sorting the channel list according to the author's defined sequence rather than alphabetical order.
- **Direct access**: Allowing users to jump to specific channels by entering the number (e.g., typing "001" to access the first channel).
- **Persistent identification**: Maintaining a consistent reference even if the channel name or stream URL changes.

When a channel lacks a number (empty or `0` in the source), the generated M3U entry omits the `tvg-chno` attribute entirely:

```m3u
#EXTINF:-1 tvg-name="Some Channel" tvg-logo="https://example.com/logo.png" tvg-country="US" group-title="USA",Some Channel
https://example.com/stream.m3u8

```

In contrast, a numbered channel includes the attribute as shown in this excerpt from the generated playlist:

```m3u
#EXTINF:-1 tvg-name="Buzzr Ⓖ" tvg-logo="https://upload.wikimedia.org/.../Buzzr_logo.svg.png" tvg-chno="1" tvg-country="US" group-title="USA",Buzzr Ⓖ
https://buzzrota-ono.amagi.tv/playlist1080.m3u8

```

## Summary

- Channel numbers are defined manually in the `#` column of Markdown tables within `lists/*.md`.
- The [`make_playlist.py`](https://github.com/Free-TV/IPTV/blob/main/make_playlist.py) script parses these tables, treating empty or `0` values as unnumbered channels.
- Valid channel numbers are exported as the `tvg-chno` attribute in the M3U‑8 format via the `Channel.to_m3u_line()` method.
- IPTV clients use `tvg-chno` to enable numeric channel surfing and ordered channel lists.
- Unnumbered channels simply omit the `tvg-chno` attribute in the final playlist.

## Frequently Asked Questions

### What happens if a channel number is set to 0 or left empty?

According to the normalization logic in [`make_playlist.py`](https://github.com/Free-TV/IPTV/blob/main/make_playlist.py) (lines 107-108), if the `#` column contains `0` or is empty, the script sets `chno = None`. This results in the `tvg-chno` attribute being omitted from the final M3U entry, and the IPTV client treats the channel as unnumbered.

### Where does the channel number appear in the final M3U file?

The channel number appears as the `tvg-chno` attribute within the `#EXTINF` line of the M3U‑8 playlist. For example, `tvg-chno="1"` indicates channel number 1. This is generated by the `Channel.to_m3u_line()` method in [`make_playlist.py`](https://github.com/Free-TV/IPTV/blob/main/make_playlist.py) only when a valid number exists.

### Can I assign duplicate channel numbers in the same playlist?

While the [`make_playlist.py`](https://github.com/Free-TV/IPTV/blob/main/make_playlist.py) script does not enforce uniqueness constraints on the `#` column values, duplicate channel numbers may cause unpredictable behavior in IPTV clients. Players typically expect unique `tvg-chno` values for direct channel access features to function correctly.

### How does the script handle the country code for grouped channels?

The script derives the `tvg-country` attribute from the Markdown filename (e.g., [`usa.md`](https://github.com/Free-TV/IPTV/blob/main/usa.md) becomes `US`) and determines the `group-title` from either the filename or an `<h1>` tag present in the Markdown file (lines 44-46). This ensures channels are properly categorized by geographic region in the final playlist.