Skip to main content

iptv-stream-validator

A small Python package for validating IPTV stream endpoints and parsing M3U / M3U8 playlists. It uses only the Python standard library, has no runtime dependencies, and supports Python 3.9+.

What the package does

  • Parses M3U / M3U8 playlists — extended playlists with #EXTINF metadata (title, duration, tvg-id, group-title, and other key="value" attributes) as well as plain URL-only lists.
  • Checks stream endpoints over HTTP(S) — one lightweight request per URL that stops after the response status line and headers, without downloading the media body.
  • Records HTTP status and response time for every check.
  • Applies configurable timeouts so dead endpoints cannot stall a validation run.
  • Reports failures as data — every check returns a ValidationResult, so DNS errors, refused connections, timeouts, and HTTP errors are results, not exceptions.
  • Produces JSON-ready output — results and playlist entries serialize to plain dictionaries, and summarize_results() aggregates a whole run into counts, failed URLs, and median/average response times.

Installation

The distribution name is iptv-stream-validator. Once published on PyPI:

pip install iptv-stream-validator

To install from a checkout of this repository (the package is pure Python, standard library only):

pip install .

There are no runtime dependencies.

Basic Python usage

from iptv_stream_validator import StreamValidator, summarize_results

validator = StreamValidator(timeout=5)

results = validator.validate_many(
    [
        "https://example.com/streams/news.m3u8",
        "http://example.com:8080/live/sports.ts",
    ]
)

for result in results:
    print(result.to_json())

print(summarize_results(results))

StreamValidator sends a GET request by default (many streaming servers reject HEAD) but never reads the response body — the connection is closed as soon as the status line and headers arrive. Pass method="HEAD" if you prefer HEAD requests.

M3U playlist validation example

Parse a playlist and check the syntactic validity of its URLs before doing any network I/O:

from iptv_stream_validator import parse_m3u, is_valid_stream_url

playlist_text = """#EXTM3U
#EXTINF:-1 tvg-id="cnn.us" group-title="News",CNN
https://example.com/streams/cnn.m3u8
#EXTINF:-1 tvg-id="bbc.uk",BBC One
https://example.com/streams/bbc.m3u8
"""

entries = parse_m3u(playlist_text)

for entry in entries:
    print(entry.title, entry.attributes, entry.url)
    print("  URL looks valid:", is_valid_stream_url(entry.url))

Output:

CNN {'tvg-id': 'cnn.us', 'group-title': 'News'} https://example.com/streams/cnn.m3u8
  URL looks valid: True
BBC One {'tvg-id': 'bbc.uk'} https://example.com/streams/bbc.m3u8
  URL looks valid: True

Playlists can also be read straight from a file with parse_m3u_file(path), and extract_urls(text) returns just the URL list. A playlist whose text contains no URL lines raises PlaylistError.

Stream endpoint validation example

Combining the two modules — parse a playlist, then validate every endpoint it contains:

from iptv_stream_validator import StreamValidator, parse_m3u, summarize_results

with open("playlist.m3u", "r", encoding="utf-8") as handle:
    entries = parse_m3u(handle.read())

validator = StreamValidator(timeout=5)
results = validator.validate_many(entry.url for entry in entries)

for entry, result in zip(entries, results):
    state = "OK" if result.ok else "FAIL"
    print(f"{state}  {entry.title or entry.url}  {result.error or result.status}")

summary = summarize_results(results)
print(f"{summary['ok']}/{summary['total']} endpoints responded")
print(f"median response time: {summary['median_response_time']}s")

Timeout and error handling

  • The timeout (default 10 seconds, configurable via StreamValidator(timeout=...)) covers DNS resolution, connection setup, and waiting for the response status line.
  • validate() catches network-level problems (URLError, DNS failures, refused connections, socket timeouts) and HTTP error statuses, and returns them inside the ValidationResult — it does not raise for a broken endpoint.
  • HTTP 4xx/5xx responses are reported as failures with their status code, since the endpoint answered but the URL is not usable as a stream.
  • Redirects are followed by default; if the final URL differs from the requested one it is recorded in result.final_url.
  • Invalid constructor arguments (unknown method, non-numeric timeout, empty user agent) raise ValueError/TypeError immediately.
result = validator.validate("https://example.com/streams/down.m3u8")
if not result.ok:
    print(result.error)  # e.g. "timed out after 5s" or "HTTP 404 Not Found"

Example output

A single result (result.to_json()):

{
  "url": "https://example.com/streams/news.m3u8",
  "ok": true,
  "status": 200,
  "response_time": 0.184371,
  "error": null,
  "final_url": null
}

A failed check:

{
  "url": "https://example.com/streams/down.m3u8",
  "ok": false,
  "status": null,
  "response_time": 5.001293,
  "error": "timed out after 5s",
  "final_url": null
}

A run summary (summarize_results(results)):

{
    "total": 3,
    "ok": 2,
    "failed": 1,
    "failed_urls": ["https://example.com/streams/down.m3u8"],
    "median_response_time": 0.211054,
    "average_response_time": 0.197713,
}

Limitations

  • Checks are sequential; validating thousands of URLs takes correspondingly long. Run multiple processes or threads yourself if you need concurrency.
  • A successful HTTP response does not prove the payload is playable media — the content is not inspected or decoded. Some servers accept any request path with a 200 response; treat results as a first-pass filter, not a guarantee.
  • Endpoints that require specific headers (cookies, referers, unusual user agents) can be configured via user_agent, but anything more elaborate needs custom code on top of this package.
  • is_valid_stream_url() is a syntactic check only (HTTP/HTTPS scheme, non-empty host); it performs no network requests.
  • The parser covers the common #EXTINF-based IPTV playlist layout. Other directives (#EXTVLCOPT, #EXTGRP, #KODIPROP, ...) are ignored rather than interpreted.
  • No M3U variant-specific handling beyond #EXTINF metadata: no XMLTV merging, no EPG lookup, no deduplication of streams.

License

MIT — see LICENSE.

Additional IPTV playlist / player resources

  • IPTV2Live — IPTV playlist and player reference site; this project's homepage and documentation are hosted there.
  • HLS (HTTP Live Streaming), RFC 8216 — the specification behind .m3u8 media playlists.
  • VideoLAN VLC — a widely used player for M3U playlists and network streams.
  • FFmpeg — the standard toolkit for inspecting and re-streaming media (e.g. ffprobe for checking whether a URL yields playable media).
  • iptv-org/iptv — a large, publicly maintained collection of M3U playlists, useful as realistic test input.

Metadata

Release files for iptv-stream-validator 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for iptv-stream-validator 0.1.0
File Size Uploaded Provenance
iptv_stream_validator-0.1.0.tar.gz 16.4 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for iptv-stream-validator 0.1.0
File Interpreter ABI Platform
iptv_stream_validator-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 28.3 kB

Release files / iptv_stream_validator-0.1.0.tar.gz

Download URL iptv_stream_validator-0.1.0.tar.gz
Size 16.4 kB
Tags Source
SHA-256 checksum
How to use checksums
ff57d8e1fbd841c1145451983b8003b59d402e607c8dbb9e21eab0f9145f2f1c
BLAKE2b-256 checksum
How to use checksums
a7687ac834db28fcad0d54dd25247654d9a4170ee2920551a822800f41e9e1ba
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.10

Release files / iptv_stream_validator-0.1.0-py3-none-any.whl

Download URL iptv_stream_validator-0.1.0-py3-none-any.whl
Size 11.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c1eb1316a2c7414db9f25e318f3ae0dc6c76dcbda958fece8aa8dd2d8c5e7112
BLAKE2b-256 checksum
How to use checksums
0fd349d06e130553dae6cf5f69e7bb58816d40681f68b8030ffd70343103648e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.10

Security for iptv-stream-validator 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page