How to Add a New Channel to the Free-TV/IPTV Playlist
To add a new channel to the Free-TV/IPTV playlist, edit the appropriate country-specific Markdown file in the lists/ directory to include a table row with the [>] stream marker, then commit your changes to trigger the automatic playlist.m3u8 generation.
Free-TV/IPTV is a community-driven repository that aggregates free, legal streaming television channels into a single M3U8 playlist. Unlike traditional IPTV management systems that require database access or complex configuration files, this project uses a declarative Markdown-based workflow where contributors simply edit human-readable table files. Adding a new channel requires modifying the appropriate country list in the lists/ directory to specify the stream URL, channel metadata, and verification status.
Understanding the Playlist Architecture
The repository generates its master playlist.m3u8 file automatically using the make_playlist.py script. This Python parser scans every .md file in the lists/ directory, extracting only the table rows whose Link column begins with the special marker [>]. Rows containing [x] or other prefixes are ignored, ensuring only verified, working streams appear in the final output.
How make_playlist.py Processes Channel Data
According to the Free-TV/IPTV source code, the generator enforces a strict separation between data and presentation. Channel metadata lives in plain Markdown tables, while make_playlist.py handles the compilation logic. When executed, the script reads each country file, validates the [>] prefix denotes an active stream, and concatenates the entries into the standard M3U8 format. This design ensures that editing the .md files remains safe and deterministic, with no risk of corrupting the playlist structure.
Required Table Format
Each channel entry must follow a specific five-column table structure:
| Column | Format Requirements |
|---|---|
| # | Numeric identifier (sequential or unique) |
| Channel | Human-readable name with optional quality indicators |
| Link | Must start with [>] followed by the stream URL in parentheses |
| Logo | HTML <img> tag with height="20" pointing to a public image host |
| EPG id | Optional string identifier for electronic program guide data |
The Link column is the critical filter: only URLs prefixed with [>] are included in playlist.m3u8, while [x] marks invalid or offline streams.
Step-by-Step Guide to Adding Channels
Follow this workflow to contribute new channels to the repository.
Locate the Correct Country List
Navigate to the lists/ directory and identify the appropriate Markdown file for your channel's country of origin. For example, U.S. channels belong in lists/usa.md, while German channels reside in lists/germany.md. If the country file does not exist, you will need to create one following the structure outlined below.
Format Your Channel Entry
Insert a new table row following the pipe-delimited syntax. Below is the exact format required for the make_playlist.py parser:
| # | Channel | Link | Logo | EPG id |
|:---:|:------------------:|:----------------------------:|:----------------------------------------------:|:------:|
| 43 | Example TV Ⓢ | [>](https://example.com/stream.m3u8) | <img height="20" src="https://i.imgur.com/xyz.png"/> | ExampleTV.us |
Key formatting details:
- Channel symbols: Append
Ⓢfor standard-definition (non-HD) streams,Ⓖfor geo-blocked content, orⓎfor YouTube Live streams. - Logo hosting: Use publicly accessible image URLs (Imgur is commonly used by maintainers).
- Placement: Insert the row under the appropriate technology heading (e.g., ATSC, DVB-S, Pluto) within the file.
Submit Your Changes
Commit your modified .md file and open a Pull Request. The repository's CI system automatically executes make_playlist.py upon merge, regenerating playlist.m3u8 to include your new channel. Because the generator never modifies source Markdown files, your changes remain declarative and reversible.
Creating a New Country List
To add channels from a country not currently represented, create a new file named lists/[country].md with this boilerplate:
<h1>Country Name</h1>
<h2>ATSC</h2>
| # | Channel | Link | Logo | EPG id |
|:---:|:-------:|:----------------------------:|:----------------------------------------------:|:------:|
| 1 | New Channel | [>](https://stream.url.com/live.m3u8) | <img height="20" src="https://i.imgur.com/logo.png"/> | NewChannel.cc |
After creating the file, add a reference to it in the repository's README.md under the "Free TV" table so users can discover the new list.
Testing Changes Locally
Before submitting a Pull Request, validate your additions by running the generator locally:
python make_playlist.py
This command parses all .md files in lists/ and outputs a fresh playlist.m3u8. Verify that your new channel appears in the generated file and that the stream URLs are correctly formatted.
Summary
- Free-TV/IPTV uses declarative Markdown files in
lists/to define channels rather than databases or configuration files. - The
make_playlist.pyscript only includes table rows where the Link column starts with[>], ignoring entries marked with[x]. - Required fields include a numeric ID, channel name (with optional symbols like
ⓈorⒼ), a[>]prefixed URL, and a logo image tag. - Changes are submitted via Pull Request, triggering automatic regeneration of
playlist.m3u8through the CI pipeline. - Test modifications locally by executing
python make_playlist.pyto verify the generated output.
Frequently Asked Questions
What does the [>] symbol mean in the Link column?
The [>] prefix serves as a validation marker that tells make_playlist.py to include this row in the final playlist.m3u8. According to the Free-TV/IPTV source code, this distinguishes active, verified streams from invalid or offline entries marked with [x]. Only rows containing this specific marker are concatenated into the master playlist.
Can I use any image hosting service for the channel logo?
While the parser accepts any valid URL in the Logo column's <img> tag, the project recommends using Imgur or other reliable public hosts. The logo must be accessible via HTTPS and should use the exact HTML format: <img height="20" src="..."/>. Private or temporary image hosts may result in broken icons for end users.
How do I indicate that a channel is geo-blocked or standard definition?
Append specific Unicode symbols to the channel name in the Channel column. Use Ⓢ (circled S) to indicate standard-definition streams that are not HD, Ⓖ (circled G) for geo-blocked content requiring specific regional access, or Ⓨ (circled Y) for YouTube Live streams. These markers help users identify stream characteristics before playback.
Do I need to manually update the playlist.m3u8 file?
No. The playlist.m3u8 file is generated automatically by the CI system when your Pull Request is merged. Running python make_playlist.py locally is only necessary for testing. Never manually edit the playlist.m3u8 file directly, as the generator will overwrite it with the compiled output from the Markdown source files.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →