iptv-org/iptv
Collection of publicly available IPTV channels from all over the world
Healthy across the board
- ✓Last commit 1d ago
- ✓5 active contributors
- ✓Distributed ownership (top contributor 49%)
- ✓Unlicense licensed
- ✓CI configured
- ✓Tests present
- ⚠Small team — 5 top contributors
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Embed this verdict
[](https://repopilot.app/r/iptv-org/iptv)Paste into your README — the badge live-updates from the latest cached analysis.
Onboarding doc
Onboarding: iptv-org/iptv
Generated by RepoPilot · 2026-05-04 · Source
Verdict
GO — Healthy across the board
- Last commit 1d ago
- 5 active contributors
- Distributed ownership (top contributor 49%)
- Unlicense licensed
- CI configured
- Tests present
- ⚠ Small team — 5 top contributors
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
TL;DR
A curated collection of publicly available IPTV (Internet Protocol Television) stream URLs, organized into M3U playlists filterable by country, language, and category. The repo uses TypeScript scripts under scripts/commands/ to automate playlist generation, validation, formatting, stream testing, and README updates — it's not a video server but a structured, CI-maintained index of stream links pulled from the iptv-org/database and iptv-org/api companion repos. All automation lives under scripts/: scripts/commands/ contains individual CLI entry points (playlist/generate.ts, playlist/validate.ts, playlist/test.ts, etc.) that import shared utilities from scripts/core/ (playlistParser.ts, streamTester.ts, dataSet.ts, etc.) and constants from scripts/constants.ts. The actual M3U playlist files are not stored in the repo root but generated and published to GitHub Pages; scripts/api.ts handles loading remote channel data from the iptv-org/api.
Who it's for
Cord-cutters and IPTV enthusiasts who want ready-made M3U playlists for video players like VLC or Kodi, and open-source contributors who submit/maintain stream URLs via GitHub Issues and PRs. DevOps-minded contributors also work on the TypeScript automation scripts that validate, test, and regenerate the playlists.
Maturity & risk
The repo has an active CI pipeline with three GitHub Actions workflows (.github/workflows/check.yml, format.yml, update.yml), Jest tests, ESLint config, and a structured contribution process via CONTRIBUTING.md and typed issue templates. It is production-ready in the sense that millions of users rely on the hosted playlists at iptv-org.github.io/iptv/index.m3u, but stream URLs are inherently volatile and require constant community maintenance.
Heavy dependency on two external sibling repos (iptv-org/database and iptv-org/api) means breakage there can silently corrupt playlist generation; the postinstall hook runs api:load automatically which can fail in network-restricted environments. Stream URLs are user-submitted and can go dead or become geo-restricted at any time, creating a high ongoing maintenance burden. Single-org ownership (iptv-org) with multiple maintainers reduces bus-factor risk, but the legal landscape around publicly re-linking streams is inherently risky depending on jurisdiction.
Active areas of work
Based on the file structure, active work includes the playlist edit/export commands (scripts/commands/playlist/edit.ts and export.ts) which appear to be newer workflow additions, and ongoing maintenance of the stream-testing pipeline (scripts/commands/playlist/test.ts using scripts/core/streamTester.ts). The update workflow (.github/workflows/update.yml) runs on a schedule to continuously regenerate playlists.
Get running
git clone https://github.com/iptv-org/iptv.git cd iptv npm install
postinstall automatically runs: npm run api:load
To generate all playlists:
npm run playlist:generate
To validate playlists:
npm run playlist:validate
To run tests:
npm test
Daily commands: npm run playlist:generate # regenerate all M3U playlists from API data npm run playlist:validate # validate playlist structure and channel IDs npm run playlist:format # auto-format M3U files npm run playlist:test # live-test stream URLs for availability npm run playlist:lint # run m3u-linter (config: m3u-linter.json) npm run readme:update # regenerate README/PLAYLISTS.md stats npm run report:create # create GitHub issue report for dead streams
Map of the codebase
scripts/constants.ts— Defines all shared constants (paths, URLs, file patterns) used across every script — changing anything here affects the entire pipeline.scripts/core/playlistParser.ts— Central parser that reads and structures .m3u stream files into typed objects; all generators and validators depend on this abstraction.scripts/models/stream.ts— Defines the Stream data model/schema that every command, generator, and table builds on — the canonical shape of a channel entry.scripts/commands/playlist/generate.ts— Entry point for the playlist generation pipeline that produces all output .m3u files consumed by end users.scripts/generators/generator.ts— Base generator class/interface that all specific generators extend — understanding this is required before adding any new playlist type.scripts/commands/playlist/validate.ts— Runs all validation rules against stream files; contributes must pass this before any PR is merged..github/workflows/update.yml— Orchestrates the full automated update pipeline (load API data, format, generate, test, commit) — understanding this shows how all scripts connect in CI.
How to make changes
Add a new country stream file
- Create a new M3U file named with the ISO 3166-1 alpha-2 country code following existing file conventions (EXTINF tags with tvg-id, tvg-logo, group-title, tvg-language, tvg-country). (
streams/xx.m3u) - Run the format command to ensure the new file conforms to canonical style before committing. (
scripts/commands/playlist/format.ts) - Run validate to confirm all stream entries pass schema and business rule checks. (
scripts/commands/playlist/validate.ts) - Run generate to produce updated output playlists that include the new country's channels. (
scripts/commands/playlist/generate.ts)
Add a new playlist generator (e.g., by subdivision/region)
- Create a new generator class extending the base Generator, implementing the generate() method to filter/group streams by the new dimension. (
scripts/generators/subdivisionsGenerator.ts) - Register the new generator in the generators index so it is picked up by the generate command. (
scripts/generators/index.ts) - Add any new path constants needed for output file locations. (
scripts/constants.ts) - Update the generate command entry point if orchestration logic needs to change. (
scripts/commands/playlist/generate.ts)
Add a new documentation table (e.g., regions breakdown)
- Create a new table module extending the base table pattern, implementing render logic for the new data dimension. (
scripts/tables/regionsTable.ts) - Register the new table in the tables index for import convenience. (
scripts/tables/index.ts) - Integrate the new table output into the README update command. (
scripts/commands/readme/update.ts) - Add placeholder markers in the README template where the new table should be injected. (
.readme/template.md)
Add a new stream validation rule
- Identify the Stream model fields that the new rule targets and confirm the property exists. (
scripts/models/stream.ts) - Add the validation logic inside the validate command, following the pattern of existing rule checks. (
scripts/commands/playlist/validate.ts) - If the rule requires new shared utility functions, add them here. (
scripts/utils.ts) - Update m3u-linter config if the rule overlaps with linter-level checks to avoid duplication. (
m3u-linter.json)
Why these technologies
- TypeScript (tsx) — Provides type safety for complex stream/playlist data models without a compile step, using tsx for direct execution — ideal for a script-heavy repo with no web server.
- M3U playlist format — Industry-standard format for IPTV that is natively supported by virtually all media players; no custom format avoids friction for end users.
Traps & gotchas
- npm install runs postinstall which calls api:load — this makes an outbound HTTP request to iptv-org's API; it will fail silently or loudly in offline/CI environments without network access. 2) playlist:test does live HTTP requests to potentially hundreds of stream URLs — it is slow, rate-sensitive, and should not be run carelessly locally. 3) The GITHUB_TOKEN env var is required for report:create (uses @octokit/core to open GitHub issues). 4) tsx is used to run TypeScript directly (no build step), so Node.js version compatibility with tsx matters — check package.json engines if added. 5) The actual M3U files served at iptv-org.github.io are on the gh-pages branch, not main — you won't see them in the working tree.
Architecture
Concepts to learn
- M3U / M3U8 playlist format — All output of this repo is M3U files; understanding the #EXTINF tag attributes (tvg-id, tvg-logo, group-title) is essential for reading playlistParser.ts and the linter config.
- HLS (HTTP Live Streaming) — Most stream URLs in the playlists are .m3u8 HLS streams; understanding how HLS manifests work explains why streamTester.ts checks HTTP headers rather than downloading full video.
- EPG (Electronic Program Guide) — The tvg-id attribute in M3U entries maps channels to EPG data; understanding this linkage explains why channel IDs must exactly match the iptv-org/database schema.
- GitHub Actions scheduled workflows — The update.yml workflow runs on a cron schedule to continuously regenerate and commit playlists; understanding workflow_dispatch and schedule triggers is needed to modify the CI pipeline.
- tsx (TypeScript execute) — All scripts run via tsx rather than compiling first with tsc; this means there's no build step but also no type-checked output — errors surface only at runtime unless you run tsc manually.
- XMLTV format — EPG data consumed alongside these playlists uses the XMLTV XML schema; understanding it clarifies why tvg-id values in M3U files must match XMLTV channel IDs exactly.
Related repos
iptv-org/database— The canonical source of all channel metadata (names, logos, categories, countries) that this repo's generate/validate scripts consume via the API.iptv-org/api— The REST API layer over iptv-org/database; loaded at postinstall time via scripts/commands/api/load.ts to provide structured channel data.iptv-org/epg— Companion repo providing Electronic Program Guide data for channels listed in these playlists, referenced directly in the README.Free-TV/FreeTVorg-data— Alternative curated free/public TV stream collection solving the same problem in a similar community-maintained format.iptv-org/awesome-iptv— Ecosystem repo listing IPTV player apps, tools, and resources that consumers of these playlists would use.
PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add unit tests for scripts/core/playlistParser.ts and scripts/core/proxyParser.ts
The scripts/core directory contains critical parsing logic (playlistParser.ts, proxyParser.ts, logParser.ts, numberParser.ts) that feeds into playlist generation, validation, and stream testing. The jest config in package.json already targets tests/ directory, but there are no visible test files for these core utilities. A bug in playlistParser.ts could silently corrupt generated playlists for millions of users. Adding focused unit tests here would be the highest-leverage contribution a new developer could make.
- [ ] Create tests/core/playlistParser.test.ts — write tests covering valid M3U entry parsing, missing EXTINF attributes, malformed URLs, and multi-line entries
- [ ] Create tests/core/proxyParser.test.ts — write tests covering valid proxy strings, invalid formats, and edge cases like empty input
- [ ] Create tests/core/logParser.test.ts — write tests that cover success/failure log line parsing since it feeds into scripts/commands/report/create.ts
- [ ] Create tests/core/numberParser.test.ts — write tests for integer and float parsing including locale edge cases
- [ ] Run
npm testto confirm all new tests pass and check coverage withjest --coverage
Add unit tests for each generator in scripts/generators/ (e.g. countriesGenerator.ts, languagesGenerator.ts)
The generators directory contains 10+ generator classes (countriesGenerator.ts, languagesGenerator.ts, regionsGenerator.ts, subdivisionsGenerator.ts, etc.) that produce the actual playlist files consumed by end users. There is no evidence of test coverage for these generators in the file structure. A regression in any generator silently produces broken or empty playlist files. Each generator has a clear interface defined by generator.ts (the base class), making them straightforward to unit test with mock data from the @iptv-org/sdk dependency.
- [ ] Review scripts/generators/generator.ts to understand the base interface all generators implement
- [ ] Create tests/generators/countriesGenerator.test.ts — mock the API data (countries, streams) and assert the correct M3U output is generated per country code
- [ ] Create tests/generators/languagesGenerator.test.ts — assert channels are correctly bucketed by language tag, including channels with multiple languages
- [ ] Create tests/generators/indexGenerator.test.ts — assert the master index playlist includes all channels without duplicates
- [ ] Create tests/generators/rawGenerator.test.ts — assert raw output strips all IPTV-org metadata extensions correctly
- [ ] Use jest mocking to stub scripts/api.ts data so tests are deterministic and offline
Refactor scripts/commands/playlist/validate.ts to extract and independently test each validation rule
validate.ts is a command-level script that almost certainly contains multiple distinct validation rules (URL format, channel ID existence, duplicate detection, blocked streams, etc.) bundled together procedurally. As a single command file it cannot be unit tested at the rule level — only end-to-end. Extracting individual validator functions into scripts/core/validators/ (e.g. urlValidator.ts, duplicateValidator.ts, channelIdValidator.ts) mirrors the existing pattern in scripts/core/ and makes each rule independently testable. This directly improves maintainability when new stream validation rules need to be added or modified.
- [ ] Read scripts/commands/playlist/validate.ts in full and enumerate every distinct validation check it performs
- [ ] Create scripts/core/validators/ directory and extract each check into its own named function/module (e.g. urlValidator.ts, channelIdValidator.ts, duplicateDetector.ts)
- [ ] Refactor validate.ts to import and call the extracted validators, keeping the CLI entry point thin
- [ ] Create tests/core/validators/urlValidator.test.ts — cover http/https schemes, missing scheme, localhost, and known-blocked domains
- [ ] Create tests/core/validators/duplicateDetector.test.ts
Good first issues
- Add unit tests for scripts/core/logParser.ts and scripts/core/numberParser.ts — these utility files appear to have no corresponding test files visible in the structure. 2) Add JSDoc/inline documentation to scripts/core/streamTester.ts — it's the most complex core module and has no visible documentation, making it hard for new contributors to understand timeout/retry logic. 3) Add a scripts/core/proxyParser.ts test file — proxy handling is a non-trivial feature that affects stream testing reliability and appears untested based on the file listing.
Top contributors
- @iptv-bot[bot] — 44 commits
- @freearhey — 28 commits
- @JulioCesarXY — 8 commits
- @Pecaquito — 5 commits
- @brokenstream — 4 commits
Recent commits
18c2ef8— [Bot] Update PLAYLISTS.md (iptv-bot[bot])366f1b5— [Bot] Update /streams (iptv-bot[bot])dff7431— Merge pull request #37469 from JulioCesarXY/patch-2 (StrangeDrVN)458aca0— Merge pull request #37465 from JulioCesarXY/master (StrangeDrVN)6e891f4— Fix channel name in Brazil Region (JulioCesarXY)f0bc1f2— Add Trace Brazuca Stream br.samsung.m3u (JulioCesarXY)b11ffd7— Add tvg-id on Trace UK uk.samsung.m3u (JulioCesarXY)00ca270— [Bot] Update PLAYLISTS.md (iptv-bot[bot])e70dfb8— [Bot] Update /streams (iptv-bot[bot])d76046b— Merge pull request #37347 from renanbazinin/add/il-now14-stream (Pecaquito)
Security observations
- Medium · Unverified External Stream URLs in M3U Playlists —
streams/*.m3u. The repository aggregates publicly available IPTV stream URLs from all over the world (e.g., streams/ad.m3u, streams/ae.m3u, etc.). These URLs point to external, third-party servers that are not controlled by the repository maintainers. Users who load these playlists into video players may be redirected to malicious servers, exposed to tracking, or have their IP addresses harvested by hostile stream providers. There is no integrity verification (e.g., hash checking) of stream endpoints. Fix: Add documentation warnings to users about the risks of loading untrusted stream URLs. Consider implementing periodic automated checks to detect and flag potentially malicious or redirecting URLs. Warn users to use a VPN or sandbox environment when consuming untrusted streams. - Medium · postinstall Script Executes Network Call Automatically —
package.json (postinstall hook), scripts/commands/api/load.ts. The package.json defines a 'postinstall' script that runs 'npm run api:load' (which executes 'tsx scripts/commands/api/load.ts') automatically after every 'npm install'. This means any developer or CI system that runs 'npm install' will automatically trigger a network request to an external API without explicit user consent or awareness. If the external API (iptv-org SDK or related) is compromised or returns malicious data, it could affect the local environment or CI pipeline during installation. Fix: Remove the postinstall hook or make it opt-in (e.g., documented as a manual step). If it must remain, validate and sanitize all data returned from the API before use, and pin the API endpoint. Consider using 'npm ci' in CI environments and auditing what the api:load script fetches and writes to disk. - Medium · Dependency on Multiple Third-Party GitHub/Octokit Packages Without Subresource Integrity —
package.json, package-lock.json. The project uses several @octokit packages (@octokit/core, @octokit/plugin-paginate-graphql, @octokit/plugin-paginate-rest, @octokit/plugin-rest-endpoint-methods, @octokit/types) to interact with the GitHub API. If any of these packages are compromised via a supply chain attack (e.g., typosquatting, maintainer account takeover), sensitive GitHub tokens used in CI workflows could be exfiltrated. The package-lock.json should be reviewed to ensure integrity hashes are present. Fix: Regularly audit dependencies with 'npm audit'. Pin exact dependency versions in package.json. Use 'npm ci' in CI to enforce package-lock.json. Enable GitHub's Dependabot for automated vulnerability alerts. Review package-lock.json to confirm all packages have integrity hashes (sha512). - Medium · GitHub Actions Workflows May Use Unpinned Action Versions —
.github/workflows/check.yml, .github/workflows/format.yml, .github/workflows/update.yml. The GitHub Actions workflow files (.github/workflows/check.yml, format.yml, update.yml) are present but their contents were not fully provided. If these workflows reference third-party actions using mutable tags (e.g., uses: actions/checkout@v3) rather than pinned SHA commits, a compromised action could execute arbitrary code within the CI environment, potentially exposing repository secrets (e.g., GITHUB_TOKEN, API keys). Fix: Pin all GitHub Actions to specific commit SHAs rather than mutable version tags (e.g., uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11). Use tools like 'actionlint' or 'Dependabot' for Actions to enforce this. Apply the principle of least privilege to GITHUB_TOKEN permissions using 'permissions:' blocks. - Medium · Potential for Malicious Content Injection via External Issue/Discussion Templates —
.github/ISSUE_TEMPLATE/, .github/DISCUSSION_TEMPLATE/, scripts. The issue templates (.github/ISSUE_TEMPLATE/.yml) and discussion templates (.github/DISCUSSION_TEMPLATE/.yml) accept user-supplied stream URLs and channel metadata. If any workflow automation (e.g., report:create, playlist:edit) processes these inputs without sanitization, there is a risk of injection into generated M3U files or markdown reports. M3U files with crafted URIs (e.g., javascript: URIs or file:// paths) could potentially be exploited depending on the player used. Fix: undefined
LLM-derived; treat as a starting point, not a security audit.
Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.