How to Handle Broken or Invalid Stream URLs in IPTV Playlists: The Free-TV/IPTV Workflow

Mark broken channels by replacing the [>] marker with [x] in the country-specific Markdown files, then regenerate the playlist using make_playlist.py to ensure only verified streams appear in the final M3U8 output.

The Free-TV/IPTV repository maintains a curated collection of public IPTV channels through a unique Markdown-based workflow. To handle broken or invalid stream URLs in IPTV playlists effectively, the project uses a simple marker system that filters out dead links during the automated build process. This approach ensures that end users receive only working streams in the generated playlist.m3u8 file.

How the Validation System Works

The [>] and [x] Marker Convention

The repository stores channel definitions in per-country Markdown files located in the lists/ directory. Each channel entry follows a strict table format where the URL column determines inclusion in the final playlist:

  • [>] — Indicates a verified, working stream URL that should be included in the output
  • [x] or [x]() — Marks a broken or invalid stream that should be excluded

When contributors identify a non-functional stream, they move the channel to an "Invalid" category within the appropriate country file and replace the [>] marker with [x]. This convention preserves the historical data while ensuring the URL never reaches production playlists.

The Channel Class and Parsing Logic

The make_playlist.py script processes these Markdown files using a dedicated Channel class that extracts metadata from each table row. The parser reads every line of the country files, extracts group titles from <h1> HTML tags, and instantiates Channel objects only for entries marked as valid.

Step-by-Step: Removing Broken Streams from Playlists

Follow this workflow when you encounter a broken stream URL:

  1. Locate the channel in the appropriate lists/[country_code].md file
  2. Move the entry to the "Invalid" section of that file to maintain organization
  3. Replace the marker — Change [>] to [x] in the URL column (use [x]() if leaving the URL empty)
  4. Submit changes — Create a pull request; the CI pipeline will automatically regenerate playlist.m3u8

The Build Script Filtering Logic

The core filtering mechanism resides in make_playlist.py. The script explicitly skips any line lacking the [>] marker before processing it as a valid channel:


# make_playlist.py – lines 50-55

for line in markup_file:
    if "<h1>" in line.lower() and "</h1>" in line.lower():
        group = re.sub('<[^<>]+>', '', line.strip())
    if "[>]" not in line:          # <-- only keep verified streams

        continue
    channel = Channel(group, line, country_code)
    m3u_line = channel.to_m3u_line()
    print(m3u_line, file=playlist)

This guard clause ensures that invalid entries are completely ignored during the build process. The continue statement prevents the script from ever instantiating a Channel object for broken URLs, meaning no #EXTINF entry gets written to the output file.

Why This Approach Keeps Playlists Clean

The marker-based system provides several technical advantages for maintaining IPTV playlists at scale:

  • Zero broken links in output: Because make_playlist.py filters at the parsing level, dead URLs never propagate to playlist.m3u8 or country-specific playlist files
  • Audit trail preservation: Using [x] instead of deletion retains the original URL and metadata, allowing future contributors to re-verify and reactivate the channel if it comes back online
  • Automated CI integration: The filtering happens during every automated build, ensuring human error (forgetting to mark broken streams) gets caught before deployment

Summary

  • Use [x] to mark broken or invalid stream URLs in the lists/*.md files
  • The make_playlist.py script automatically filters out any line without the [>] marker, preventing broken URLs from reaching the final M3U8 output
  • Preserve historical data by moving channels to "Invalid" sections rather than deleting them entirely
  • Continuous Integration handles playlist regeneration automatically once markers are updated

Frequently Asked Questions

What happens if a broken stream keeps the [>] marker?

If a contributor forgets to replace [>] with [x], the invalid URL will be included in the next build of playlist.m3u8. This creates a poor user experience as IPTV players will attempt to load a dead stream. The repository relies on community vigilance to ensure markers are updated promptly when streams fail.

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

While physically possible, deletion is discouraged. The Free-TV/IPTV contribution guidelines recommend keeping entries with [x] markers because streams sometimes come back online after temporary outages. Preserving the URL metadata allows future contributors to easily reactivate the channel by simply changing the marker back to [>].

How does the parser distinguish between markers in different columns?

The make_playlist.py script performs a simple string search for "[>]" on each line of the Markdown file. It does not validate column position specifically, so markers must be placed carefully according to the established table format. The script assumes any line containing [>] represents a valid channel entry, regardless of which column technically contains the marker.

Does the repository automatically detect broken URLs?

No, the current implementation does not include automated URL health checking. The system relies entirely on manual curation by contributors who verify streams and update markers accordingly. The if "[>]" not in line: continue logic in make_playlist.py serves as a passive gatekeeper rather than an active validation service.

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 →