# How to Test IPTV Stream URLs Before Adding Them to the Playlist

> Learn how to test IPTV stream URLs effectively before adding them to your playlist. Discover automated validation techniques and essential tools.

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

---

**The Free-TV/IPTV repository automatically validates every stream URL through a CI pipeline that runs `m3u-linter` for syntax checking and `iptv-checker` with FFmpeg to verify stream availability, latency, and geo-blocking before any pull request can be merged.**

Testing IPTV stream URLs before adding them to a playlist prevents broken links and geo-restricted content from reaching end users. The **Free-TV/IPTV** repository implements a robust validation workflow that contributors can replicate locally to ensure their submissions meet quality standards. This guide explains how the automated testing works and how to run the same checks on your local machine.

## Automated CI Validation in Free-TV/IPTV

Every pull request that modifies a `.md` file in the `lists/` directory triggers the **Test IPTV file quality** workflow defined in [`.github/workflows/test_playlist.yml`](https://github.com/Free-TV/IPTV/blob/main/.github/workflows/test_playlist.yml). This CI pipeline performs two distinct validation layers before allowing a merge.

### M3U Syntax Validation

The workflow uses the **`m3u-linter`** tool to parse the generated `playlist.m3u8` file and enforce strict formatting rules. The linter checks for proper header syntax, attribute quoting, and playlist structure according to the project's [`M3u-linter.config.json`](https://github.com/Free-TV/IPTV/blob/main/M3u-linter.config.json) configuration. If the generated playlist contains malformed entries, the CI job fails immediately.

### Stream Availability Testing

The **`iptv-checker`** utility probes each URL using FFmpeg to verify actual stream accessibility. According to lines 47-51 in [`.github/workflows/test_playlist.yml`](https://github.com/Free-TV/IPTV/blob/main/.github/workflows/test_playlist.yml), the checker runs with a concurrency of **100 workers** and a **120-second timeout** per stream:

```bash

# As implemented in the CI workflow

iptv-checker -o output -p 100 -t 120000 playlist.m3u8

```

The tool reports dead streams, measures latency, identifies GeoIP-blocking issues, and writes a detailed JSON summary to the `output/` directory. Line 49 of the same workflow file ensures FFmpeg is installed as a prerequisite for the checker.

## Local Testing Workflow for Contributors

You can replicate the exact CI validation locally before submitting a pull request. This ensures that changes to `lists/*.md` files will pass automated testing.

1. **Clone the repository and generate the playlist:**

   ```bash
   git clone https://github.com/Free-TV/IPTV.git && cd IPTV
   python3 make_playlist.py
   ```

   This script processes the markdown tables in `lists/*.md` and builds `playlist.m3u8`, injecting country codes and filtering only entries marked with `[>]` (as handled in [`make_playlist.py`](https://github.com/Free-TV/IPTV/blob/main/make_playlist.py) lines 53-55).

2. **Validate M3U syntax:**

   ```bash
   npm install -g m3u-linter
   m3u-linter -c M3u-linter.config.json playlist.m3u8
   ```

3. **Install FFmpeg and the stream checker:**

   ```bash
   sudo apt-get install -y ffmpeg  # Required by iptv-checker

   npm install -g iptv-checker
   ```

4. **Test all stream URLs:**

   ```bash
   iptv-checker -o output -p 100 -t 120000 playlist.m3u8
   ```

   This probes every URL with 100 concurrent workers and a 120-second timeout per stream, matching the CI configuration.

5. **Inspect the results:**

   ```bash
   cat output/report.json | jq '.'
   ```

   Look for entries with `"status":"dead"` or `"geoBlocked":true` to identify problematic URLs.

6. **Fix and iterate:**

   Update failing URLs in the appropriate `lists/*.md` file, regenerate the playlist with `python3 make_playlist.py`, and repeat steps 2-5 until the report shows only healthy streams.

## Quick Ad-Hoc Testing for Single URLs

For rapid verification of a single stream without running the full suite, use **FFprobe** to check codec and stream metadata:

```bash
ffprobe -v error -show_entries stream=codec_name,width,height -of default=noprint_wrappers=1:nokey=1 "$URL"

```

If the command returns codec information and exits with status 0, the stream is reachable and playable. A non-zero exit code indicates network errors, 404 responses, or authentication failures.

## Understanding the Test Results

The **[`output/report.json`](https://github.com/Free-TV/IPTV/blob/main/output/report.json)** file generated by `iptv-checker` contains detailed metadata for each tested URL. Healthy streams show `"status":"online"` with low latency values, while failed entries indicate specific failure modes:

- **Dead streams**: URLs that timeout or return connection errors
- **Geo-blocked streams**: URLs that reject connections based on source IP location (marked `"geoBlocked":true`)
- **Slow streams**: URLs exceeding the 120-second threshold

According to the contribution guidelines in [`README.md`](https://github.com/Free-TV/IPTV/blob/main/README.md) lines 174-176, any URL flagged as unreachable or geo-blocked must be resolved before the PR can be merged, maintaining the repository's policy of providing working, freely accessible content.

## Summary

- **Free-TV/IPTV** automatically tests every URL via GitHub Actions in [`.github/workflows/test_playlist.yml`](https://github.com/Free-TV/IPTV/blob/main/.github/workflows/test_playlist.yml) using `m3u-linter` and `iptv-checker`.
- Run `python3 make_playlist.py` locally to generate `playlist.m3u8` from the `lists/*.md` source files before testing.
- Use `iptv-checker -o output -p 100 -t 120000 playlist.m3u8` to replicate CI testing with 100 concurrent workers and 120-second timeouts.
- Check [`output/report.json`](https://github.com/Free-TV/IPTV/blob/main/output/report.json) for `"status":"dead"` or `"geoBlocked":true"` entries to identify problematic streams.
- Use `ffprobe` for quick single-URL validation without installing the full checker suite.

## Frequently Asked Questions

### How long does the stream testing take?

The `iptv-checker` processes URLs concurrently using 100 workers, so a typical playlist of several hundred channels completes in 5-10 minutes depending on network latency. Individual streams timeout after 120 seconds if unresponsive.

### Can I test streams without installing Node.js?

While `m3u-linter` and `iptv-checker` require Node.js, you can validate single URLs using **FFprobe** (which only requires FFmpeg). For full playlist validation, the Node.js tools are necessary to replicate the exact CI environment used by Free-TV/IPTV.

### What does the `[>]` marker mean in the markdown files?

The [`make_playlist.py`](https://github.com/Free-TV/IPTV/blob/main/make_playlist.py) script (lines 53-55) only includes channels marked with `[>]` in the generated `playlist.m3u8`. This marker indicates the stream is confirmed working and should be included in public playlists, while unmarked entries are treated as draft or unverified.

### Why does my stream pass locally but fail in the CI?

The CI environment may use different network routing or IP geolocation that triggers geo-blocking rules not present in your local network. Additionally, some streams block datacenter IPs (common for GitHub Actions runners) while allowing residential connections. Check the `geoBlocked` field in the JSON report to confirm.