# How to Add New Channels to the IPTV Database: A Step-by-Step Guide

> Learn how to add new channels to the IPTV database with this step-by-step guide. Submit stream URLs via GitHub issues or pull requests for validation and playlist generation.

- Repository: [iptv-org/iptv](https://github.com/iptv-org/iptv)
- Tags: how-to-guide
- Published: 2026-02-25

---

**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`](https://github.com/iptv-org/iptv/blob/main/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](https://github.com/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:

1. Open a new issue in the `iptv-org/database` repository.
2. Select the **"Add channel"** template.
3. Provide the required fields: ID, name, country, categories, and languages.
4. 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`](https://github.com/iptv-org/iptv/blob/main/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:

1. 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/main/.github/ISSUE_TEMPLATE/1_streams_add.yml)](https://github.com/iptv-org/iptv/blob/master/.github/ISSUE_TEMPLATE/1_streams_add.yml).
2. 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.
3. Optional fields include quality (e.g., `1080p`), label (e.g., `Geo-blocked`), HTTP User-Agent, and HTTP Referrer.
4. 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`](https://github.com/iptv-org/iptv/blob/main/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:

1. Locate the country playlist under the `streams/` directory (e.g., `streams/us.m3u`).
2. Append a new entry following the **Stream Description Scheme**:

   ```text
   #EXTINF:-1 tvg-id="CHANNEL_ID",CHANNEL NAME (QUALITY) [LABEL]
   https://example.com/stream.m3u8
   ```

3. The `Stream.fromPlaylistItem` method (lines 34‑73 in [`scripts/models/stream.ts`](https://github.com/iptv-org/iptv/blob/main/scripts/models/stream.ts)) parses this format to extract `tvg-id`, title, quality, and label when the repository regenerates.
4. Commit the change and open a pull request. The CI workflow runs the same validation scripts to ensure the `tvg-id` exists 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`](https://github.com/iptv-org/iptv/blob/main/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`](https://github.com/iptv-org/iptv/blob/main/update.ts)). The `Stream` class (defined in [`scripts/models/stream.ts`](https://github.com/iptv-org/iptv/blob/main/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`](https://github.com/iptv-org/iptv/blob/main/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:

```typescript
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`](https://github.com/iptv-org/iptv/blob/main/scripts/commands/playlist/update.ts) and the enrichment methods at lines 94‑115 of [`scripts/models/stream.ts`](https://github.com/iptv-org/iptv/blob/main/scripts/models/stream.ts).

## Summary

- **Database First**: Verify or create the channel in `iptv-org/database` before submitting stream URLs; the `addStreams` function ignores unknown channel IDs (lines 49‑51).
- **Issue Form**: Use the template at [`.github/ISSUE_TEMPLATE/1_streams_add.yml`](https://github.com/iptv-org/iptv/blob/main/.github/ISSUE_TEMPLATE/1_streams_add.yml) and obtain the `approved` label to trigger automation.
- **Direct Edit**: Manually append `#EXTINF` entries to files in `streams/` following the format parsed by `Stream.fromPlaylistItem` (lines 34‑73).
- **Validation**: The `playlist:update` script validates against `apiData.channelsKeyById` and enriches entries via the `Stream` class methods.
- **Persistence**: Processed streams are saved to country-specific `.m3u` files via `streamsStorage.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`](https://github.com/iptv-org/iptv/blob/main/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`](https://github.com/iptv-org/iptv/blob/main/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`](https://github.com/iptv-org/iptv/blob/main/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.