How to Add New Channels to the IPTV Database: A Step-by-Step Guide
To add new channels to the IPTV database, you must first ensure the channel metadata exists in the iptv-org/database project, then submit a working stream URL through the "Add stream" GitHub issue form or a direct pull request, which triggers automated scripts to validate and generate the proper playlist entries.
The iptv-org/iptv repository aggregates publicly available IPTV streams into curated .m3u playlists. To maintain data integrity, the project enforces a strict two-step workflow that separates channel metadata from stream URLs, using TypeScript automation scripts that validate every submission against the central database API.
Prerequisites: Verify the Channel in the Central Database
Before submitting a stream URL, you must confirm the channel metadata exists in the iptv-org/database repository. The addStreams routine in scripts/commands/playlist/update.ts validates every request against apiData.channelsKeyById, and if the ID is absent, the stream will be ignored (lines 49‑51).
Check for Existing Channel IDs
Search the iptv-org/database repository for your channel. If it exists, note its exact channel ID (e.g., bbcnews). This ID is required for the submission form.
Submit a Database Request for Missing Channels
If the channel is missing from the database:
- Open a new issue in the
iptv-org/databaserepository. - Select the "Add channel" template.
- Provide the required fields: ID, name, country, categories, and languages.
- Wait for the maintainers to merge the entry.
Once merged, the channel ID becomes available to the IPTV scripts via the API data loaded in scripts/api.ts (lines 45‑55), which indexes channels by ID using data.channelsKeyById = channels.keyBy(c => c.id) (line 53).
Methods to Submit New Stream URLs
Once the channel ID is active in the database, add a live stream URL using one of two methods.
Option 1: Use the "Add Stream" Issue Form (Recommended)
The repository automates playlist generation by reading approved GitHub issues. To submit via the form:
- Open a new issue using the Add stream template located at [
.github/ISSUE_TEMPLATE/1_streams_add.yml](https://github.com/iptv-org/iptv/blob/master/.github/ISSUE_TEMPLATE/1_streams_add.yml). - Fill in the required fields:
- Stream ID:
<channel_id>or<channel_id>@<feed_id>(feed ID is optional). - Stream URL: A working HTTP(S) link pointing directly to the stream.
- Stream ID:
- Optional fields include quality (e.g.,
1080p), label (e.g.,Geo-blocked), HTTP User-Agent, and HTTP Referrer. - Submit the issue.
A maintainer will add the approved label (or automation will apply it). When the issue carries both streams:add and approved labels (checked at lines 36‑38 of update.ts), the nightly playlist:update workflow executes the addStreams function. This routine validates the stream_id against the API channel list (lines 49‑51), builds a new Stream object with the supplied data (lines 57‑65), and inserts it into the proper country-specific playlist (e.g., us.m3u).
Option 2: Direct Pull Request to Playlist Files
If you prefer manual contribution, edit the playlist files directly:
-
Locate the country playlist under the
streams/directory (e.g.,streams/us.m3u). -
Append a new entry following the Stream Description Scheme:
#EXTINF:-1 tvg-id="CHANNEL_ID",CHANNEL NAME (QUALITY) [LABEL] https://example.com/stream.m3u8 -
The
Stream.fromPlaylistItemmethod (lines 34‑73 inscripts/models/stream.ts) parses this format to extracttvg-id, title, quality, and label when the repository regenerates. -
Commit the change and open a pull request. The CI workflow runs the same validation scripts to ensure the
tvg-idexists in the central database.
How the Automation Processes Your Request
The playlist:update command orchestrates the transformation of approved issues into playlist entries through three distinct phases.
Validation Against the Central API
The script loads the full database into memory via loadData() in scripts/api.ts (lines 45‑55), creating a lookup table keyed by channel ID. The addStreams function checks that the submitted stream_id exists in this dataset before proceeding (lines 49‑51). If validation fails, the entry is skipped.
Stream Object Creation and Enrichment
For valid requests, the script instantiates a new Stream({...}) object (lines 57‑65 of update.ts). The Stream class (defined in scripts/models/stream.ts) enriches the object through:
updateTvgId(): Normalizes the channel identifier.updateTitle(): Generates a human-readable title from the database metadata.updateFilepath(): Determines the target playlist file (e.g.,streams/us.m3u) based on the channel’s country (lines 94‑115).
Playlist File Generation
After processing all modifications, the updated Stream collection is serialized and written to the appropriate file. The key persistence logic occurs at line 52 of update.ts: await streamsStorage.save(filepath, playlist.toString()), which saves the formatted #EXTINF entries to streams/<country>.m3u.
Manual Implementation: Adding Streams Programmatically
The following TypeScript example reproduces the internal logic of the addStreams function, demonstrating how to create and persist a stream entry manually:
import { Stream } from './scripts/models/stream'
import { Collection } from '@freearhey/core'
import { loadData } from './scripts/api'
import { Storage } from '@freearhey/storage-js'
import { STREAMS_DIR } from './scripts/constants'
import { Playlist } from './scripts/models/playlist'
async function addNewStream() {
// Load central database into memory
const apiData = await loadData()
const channelId = 'bbcnews' // Must exist in iptv-org/database
const feedId = '' // Optional
const streamUrl = 'https://example.com/stream.m3u8'
const quality = '1080p'
const label = 'Geo-blocked'
// Build Stream object matching the script's implementation
const newStream = new Stream({
channel: channelId,
feed: feedId || undefined,
title: 'BBC News', // Will be overwritten by updateTitle()
url: streamUrl,
user_agent: undefined,
referrer: undefined,
quality
})
newStream.label = label
newStream
.updateTitle()
.updateFilepath()
// Add to collection
const streams = new Collection<Stream>()
streams.add(newStream)
// Persist to country-specific playlist
const storage = new Storage(STREAMS_DIR)
await storage.save('us.m3u', new Playlist(streams, { public: false }).toString())
}
addNewStream()
This snippet mirrors the object construction logic found at lines 57‑71 of scripts/commands/playlist/update.ts and the enrichment methods at lines 94‑115 of scripts/models/stream.ts.
Summary
- Database First: Verify or create the channel in
iptv-org/databasebefore submitting stream URLs; theaddStreamsfunction ignores unknown channel IDs (lines 49‑51). - Issue Form: Use the template at
.github/ISSUE_TEMPLATE/1_streams_add.ymland obtain theapprovedlabel to trigger automation. - Direct Edit: Manually append
#EXTINFentries to files instreams/following the format parsed byStream.fromPlaylistItem(lines 34‑73). - Validation: The
playlist:updatescript validates againstapiData.channelsKeyByIdand enriches entries via theStreamclass methods. - Persistence: Processed streams are saved to country-specific
.m3ufiles viastreamsStorage.save()(line 52).
Frequently Asked Questions
What is the difference between the database and the iptv repository?
The iptv-org/database repository stores static channel metadata (names, countries, categories, IDs), while iptv-org/iptv stores dynamic stream URLs (the actual video links). You cannot add a stream to the iptv repository unless the channel ID first exists in the database, as enforced by the validation logic in scripts/commands/playlist/update.ts (lines 49‑51).
Why was my stream request ignored by the automation?
The addStreams function requires two specific labels on your issue: streams:add and approved (checked at lines 36‑38). Additionally, the stream_id you provided must exactly match a channel ID in the central database lookup table (apiData.channelsKeyById). If either condition fails, the script skips the request without modifying playlists.
Can I add a stream without using the GitHub issue form?
Yes. You can submit a direct pull request editing the appropriate file in the streams/ directory (e.g., streams/us.m3u). Append an #EXTINF line followed by the URL, matching the format parsed by Stream.fromPlaylistItem in scripts/models/stream.ts (lines 34‑73). The CI pipeline will validate that the tvg-id exists in the database before merging.
How long does it take for an approved stream to appear in the playlist?
Approved issues are processed by the nightly playlist:update workflow, which runs the update.ts script to regenerate all .m3u files. Streams typically appear within 24 hours of receiving the approved label, though direct pull requests may merge faster if they pass immediate CI checks.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →