npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

hlsdownloader

v6.1.1

Published

Downloads HLS Playlist file and TS chunks

Readme

HLSDownloader

NPM Version Node.js Version TypeScript License: MIT CI Coverage Status Documentation Maintenance Semver: Badge Downloads: HLSDownloader Min Bundle Size: HLSDownloader Known Vulnerabilities

⚠️ This package is native ESM and no longer provides a CommonJS export. If your project uses CommonJS, you will have to convert to ESM. Please don't open issues for questions regarding CommonJS / ESM.

⚠️ HLSDownloader v2.x.x is no longer maintained and we will not accept any backport requests.


Features

  • Event Based: Event based API
  • Modern ESM: Optimized for Node.js 20+ environments using native modules.
  • TypeScript Native: Built with strong typing for mission-critical applications.
  • Resilient Networking and Retryable: Built-in resilience that automatically retries with exponential backoff of failed segment requests to ensure download completion.
  • Promise Based: Fully asynchronous API designed for seamless integration with async/await and modern control flows.
  • Support for HTTP/2: Leverages multiplexing to download multiple segments over a single connection for reduced overhead.
  • Overwrite Protection: Safeguards your local data by preventing accidental overwriting of existing files unless explicitly enabled.
  • Support for Custom HTTP Headers: Allows injection of custom headers for handling authentication, user-agents, or session tokens.
  • Concurrent Downloads: Maximizes bandwidth by fetching multiple HLS segments simultaneously through parallel HTTP connections.
  • Proxy and NoProxy Support: Proxy support and No Proxy support (undici integration).
  • Professional Docs: Integrated JSDoc-to-HTML pipeline using TypeDoc and the Fresh theme.

Installation

npm install hlsdownloader

Note: This library requires undici as a peer dependency for proxy support.

Examples

Example 1: Basic Download with Event Monitoring

This is the standard implementation for saving a remote HLS stream to a local directory.

import { HLSDownloader } from 'hlsdownloader';

async function downloadStream() {
  const downloader = new HLSDownloader({
    playlistURL: 'https://example.com/video/master.m3u8',
    destination: './downloads/my-video',
    overwrite: true,
    concurrency: 5, // Process 5 segments simultaneously
    retry: { limit: 3, delay: 1000 },
    timeout: 15000,
  });

  downloader.on('start', ({ total }) => console.log(`start downloading assets...`));

  // Listen to progress updates
  downloader.on('progress', data => {
    const percent = ((data.total / data.total) * 100).toFixed(2); // Simple logic for example
    console.log(`[Progress] Downloaded: ${data.url}`);
  });

  // Handle errors for specific segments
  downloader.on('error', err => {
    console.error(`[Segment Error] Failed to fetch ${err.url}: ${err.message}`);
  });

  // Final summary
  const summary = await downloader.startDownload();
  console.log(`Finished! Total items: ${summary.total}. Errors: ${summary.errors.length}`);
}

downloadStream();

Example 2: "Dry-Run" / CDN Priming (No File Writing)

If the destination is omitted, the library fetches streams but doesn't write to disk. This is excellent for CDN Priming or validating manifest health.

import { HLSDownloader } from 'hlsdownloader';

async function primeCDN() {
  const downloader = new HLSDownloader({
    playlistURL: 'https://cdn.provider.com/live/stream.m3u8',
    // destination is omitted -> results in memory-only stream fetch
    concurrency: 10,
    headers: {
      Authorization: 'Bearer internal-token-123',
      'X-Custom-Source': 'Prewarm-Service',
    },
  });

  downloader.on('start', ({ total }) => console.log(`Priming ${total} assets...`));

  const result = await downloader.startDownload();

  if (result.errors.length === 0) {
    console.log('CDN Cache successfully warmed.');
  } else {
    console.error('Priming failed for some chunks', result.errors);
  }
}

primeCDN();

Example 3: Corporate Proxy & Advanced Networking

If you are using behind corporate proxy, pass the proxy and no proxy configuration as follows

import { HLSDownloader } from 'hlsdownloader';

const downloader = new HLSDownloader({
  playlistURL: 'https://secure-stream.corp.internal/index.m3u8',
  destination: '/mnt/storage/archive',
  proxy: 'http://proxy.corporate.net:8080',
  noProxy: '.internal.com,localhost', // Bypass proxy for internal domains
  headers: {
    Cookie: 'session_id=abc123',
    'User-Agent': 'MediaArchiver/1.0',
  },
});

downloader.on('start', ({ total }) => console.log(`Priming ${total} assets...`));

// Listen to progress updates
downloader.on('progress', data => {
  const percent = ((data.total / data.total) * 100).toFixed(2); // Simple logic for example
  console.log(`[Progress] Downloaded: ${data.url}`);
});

// Handle errors for specific segments
downloader.on('error', err => {
  console.error(`[Segment Error] Failed to fetch ${err.url}: ${err.message}`);
});

const summary = await downloader.startDownload();

Example 4: Simple progress bar

This example demostrate a simple download progressbar. You can bring your own progress bar implementation

import { HLSDownloader } from 'hlsdownloader';

const downloader = new HLSDownloader({
  playlistURL: 'https://stream.example.com/playlist/master.m3u8',
  concurrency: 5,
  retry: { limit: 3, delay: 1000 },
  headers: { 'User-Agent': 'MyHeader' },
  timeout: 15000,
});

downloader.on('start', ({ total }) => {
  console.log(`Starting download of ${total} segments...`);
});

downloader.on('progress', ({ processed, total, url }) => {
  const percentage = Math.round((processed / total) * 100);
  const progressBar = '='.repeat(Math.floor(percentage / 5)).padEnd(20, ' ');
  process.stdout.clearLine(0);
  process.stdout.cursorTo(0);
  process.stdout.write(`[${progressBar}] ${percentage}% | Processing: ${processed}/${total}`);
});

downloader.on('end', () => {
  process.stdout.write('\nDownload Complete!\n');
});

await downloader.startDownload();

API Documentation

The library is organized under the HLSDownloader module. For full interactive documentation, visit our Documentation site.

HLSDownloader (Class)

The main service orchestrator for fetching HLS content.

| Method | Returns | Description | | --------------- | -------------------------- | ------------------------------------- | | startDownload() | Promise<DownloadSummary> | Begins parsing and fetching segments. |

DownloaderOptions (Interface)

| Option | Type | Default | Description | | ----------- | --------- | ------------------------ | ------------------------------------------------------------------------------------------ | | playlistURL | string | Required | The source .m3u8 URL. | | destination | string | undefined | Local path to save files. Omit for "dry-run" mode. | | concurrency | number | os.cpus().length | Simultaneous segment downloads. | | overwrite | boolean | false | Overwrite existing files in the destination. | | headers | object | {} | Custom headers to pass | | timeout | number | 10000 | Network request timeout in ms. | | retry | object | { limit: 1, delay: 500 } | Exponential backoff settings. | | proxy | string | undefined | Corporate proxy URL. Also reads URLs for HTTP_PROXY, HTTPS_PROXY environment variables | | noProxy | string | undefined | Corporate No Proxy Urls. Also reads urls from NO_PROXY environment vriable |

DownloaderEvents (Interface)

| Event Name | Description | | ---------- | -------------------------------------------- | | start | emits when download started | | progress | emits for each segement downloded | | error | emits when a segement downlod error occurred | | end | emits when download ended |

DownloadSummary (Interface)

| Property | Type | Description | | -------- | ----------------- | ------------------------------------- | | total | number | Count of successfully saved segments. | | message | string | User friendly message. | | errors | DownloadError[] | Array of detailed failure objects. |

SegmentDownloadedData (Interface) - emits on progress events

| Property | Type | Description | | --------- | -------- | -------------------------------------------------------------------------- | | url | string | Original segment URL as referenced in the HLS playlist (.m3u8). | | path | string | Local file system path where the segment was saved. Empty if not provided. | | processed | number | Total number of segments downloaded so far. | | total | number | Total number of segments downloaded to download, including this one. |


SegmentDownloadErrorData (Interface) - emits on error events

| Property | Type | Description | | -------- | -------- | ---------------------------------------------------------- | | url | string | Original segment URL that failed to download. | | name | string | Error name or type (e.g., NetworkError, TimeoutError). | | message | string | Human-readable error description. |

Development & Contributing

Contributions are welcome! This project enforces strict quality standards to maintain 100% coverage.

Prerequisites

Workflow

Fork & Clone: Get the repo locally.

  • Install: npm install
  • Test: npm run test (Must pass without warnings)
  • Lint: npm run lint (Must pass without warnings)
  • Build: npm run build (Generates ./dist and bundled types)
  • Docs: npm run docs (Generates TypeDoc HTML)
  • Test with Coverage Report: npm run test:coverage (Must maintain 100% coverage)

Guidelines

  • Follow the JSDoc hierarchy: Use @module HLSDownloader and @category Services/Types.
  • All new features must include unit tests.
  • Maintain ESM compatibility (always use file extensions in imports).

Contributions, issues and feature requests are welcome!Feel free to check issues page. You can also take a look at the contributing guide.

Show your support

Give a ⭐️ if this project helped you!. I will be grateful if you all help me to improve this package by giving your suggestions, feature request and pull requests. I am all ears!!

License

Copyright © 2026 Nur Rony.