How to Update Broken or Invalid Stream URLs in the Free-TV IPTV Repository

To update broken or invalid stream URLs in the Free-TV IPTV repository, edit the country-specific markdown files in the lists/ directory by replacing the [>] marker with [x], which excludes the channel from the automatically generated playlist without modifying the Python build scripts.

The Free-TV/IPTV project maintains thousands of television streams across country-specific markdown files rather than a centralized database. Understanding this workflow for updating broken or invalid stream URLs ensures contributors maintain clean git history while respecting the repository's automated generation pipeline.

How the Playlist Generation Works

The repository uses a marker-based filtering system implemented in make_playlist.py. During the build process, the script iterates through every markdown file in the lists/ directory and applies a strict filter to determine playlist inclusion.

According to the source code in make_playlist.py:


# Only lines that contain the "[>]" marker are turned into playlist entries

if "[>]" not in line:
    continue
channel = Channel(group, line, country_code)

The Channel class parses each qualifying line via Channel.__init__, extracting the stream URL, channel name, and optional EPG data. The to_m3u_line method subsequently formats this data into a valid M3U8 entry. Lines lacking the [>] marker—specifically those marked with [x]—are skipped entirely, effectively filtering out dead streams from the final output.

Step-by-Step Workflow for Updating Broken URLs

Locate the Channel Entry

Navigate to the appropriate country file within the lists/ directory. For example, United States channels reside in lists/usa.md. Each channel occupies a single table row following this pipe-delimited format:

| 1 | ABC News | [>](http://example.com/stream.m3u8) | <img src="https://i.imgur.com/abc.png" width="100"> |

Mark the URL as Invalid

Replace the [>] marker with [x] to signal the stream is broken. Retain the URL inside the parentheses for future reference and potential reactivation:

| 1 | ABC News | [x](http://example.com/broken.m3u8) | <img src="https://i.imgur.com/abc.png" width="100"> |

This marker change causes make_playlist.py to skip the entry during the next playlist generation cycle.

Submit Your Changes

Commit only the markdown source files. Do not touch playlist.m3u8 or any other generated artifacts—these files regenerate automatically via the repository's CI/CD pipeline when your pull request merges.

Reactivating Fixed Streams

When a previously broken URL becomes valid again, reverse the workflow. Locate the entry in the appropriate lists/*.md file and restore the [>] marker:

| 1 | ABC News | [>](http://example.com/working-again.m3u8) | <img src="https://i.imgur.com/abc.png" width="100"> |

The channel will automatically reappear in the next playlist build without requiring additional code changes.

Adding New Channels

To contribute a new working stream, append a line to the appropriate country file using the [>] marker:

| 99 | New Channel | [>](http://newstream.example.com/stream.m3u8) | <img src="https://i.imgur.com/new.png" width="100"> |

The script will include this entry in the generated M3U8 output as long as the [>] marker precedes the URL.

Summary

  • Single source of truth: The markdown files in lists/ contain the definitive channel data; never edit the generated playlist.m3u8 directly.
  • Marker system: [>] indicates valid active streams; [x] marks broken or invalid URLs for exclusion from playlist generation.
  • Build logic: make_playlist.py implements the filter via if "[>]" not in line: continue, processes valid entries through the Channel class, and produces M3U8 output via to_m3u_line.
  • Preservation: Keep broken URLs in the markdown with [x] markers rather than deleting lines entirely, enabling easy reactivation when streams recover.

Frequently Asked Questions

What happens if I edit playlist.m3u8 directly?

Direct modifications to playlist.m3u8 are overwritten by the automated CI/CD pipeline. This file is generated deterministically from the markdown sources in lists/ every time changes merge to the default branch. Always edit the source markdown files instead.

Can I delete broken URLs instead of marking them with [x]?

While deletion is possible, the repository convention recommends using [x] to preserve the URL for future reference. This practice allows contributors to test the link later or update it without reconstructing the entire table row, including the channel number and logo reference.

How does make_playlist.py determine which channels to include?

The script applies a strict string filter in make_playlist.py: if "[>]" not in line: continue. Only lines containing the [>] marker proceed to the Channel constructor and subsequent to_m3u_line conversion. Lines with [x] or no marker are ignored during M3U8 generation.

Do I need to run make_playlist.py locally before submitting a PR?

No. The repository automation handles playlist generation server-side. Contributors only need to edit the markdown files in lists/ and submit the pull request. The automated workflow validates changes and regenerates playlist.m3u8 after merge.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →