YouTube Video Downloader (ytdl-core)
ytdl-core is a pure JavaScript library designed for downloading YouTube videos directly within Node.js environments, offering a streaming interface for efficient processing. Its current stable version is 4.11.5, with releases typically occurring as needed to address breaking changes from YouTube's API or to introduce minor features and bug fixes. The project shows an active maintenance cycle, frequently releasing patches (e.g., 4.11.2 to 4.11.5 in a few months) to adapt to YouTube's evolving infrastructure, particularly around video parsing and signature deciphering. A key differentiator is its focus on a lean, Node.js-friendly streaming API, allowing developers to pipe video streams directly to file systems or other processing utilities without intermediate storage. It ships with TypeScript types, facilitating its use in modern TypeScript projects.
Common errors
-
Error: Video is unavailable
cause YouTube has made changes to its video embedding or streaming API, or the video itself is geo-restricted/private/deleted.fixEnsure `ytdl-core` is the latest version. Check if the video is genuinely available and not restricted. For geo-restricted or private videos you have access to, consider using proxy or cookie options. -
Error: No video formats found
cause Often linked to YouTube API changes that prevent `ytdl-core` from correctly parsing available formats, or potentially due to age-restriction/account requirements.fixUpdate `ytdl-core` to the latest version to get the newest parsing fixes. If the problem persists, check for existing issues on the GitHub repository or create a new one, providing the video URL. -
TypeError: Cannot read properties of undefined (reading 'pipe') or stream hangs indefinitely
cause Typically caused by throttling from YouTube due to too many requests from a single IP, or outdated signature deciphering logic.fixEnsure `ytdl-core` is updated. Implement IPv6 rotation via the `IPv6Block` option or use a proxy to circumvent throttling. Adjust `dlChunkSize` if large files are being throttled. -
TS2307: Cannot find module 'ytdl-core' or its corresponding type declarations.
cause Incorrect TypeScript configuration or import syntax for a package that might not explicitly define default exports for CommonJS `require` when `esModuleInterop` is off.fixIn `tsconfig.json`, set `"esModuleInterop": true` or `"allowSyntheticDefaultImports": true`. Then use `import ytdl from 'ytdl-core';`. Alternatively, use `import * as ytdl from 'ytdl-core';`.
Warnings
- breaking YouTube frequently updates its website and API, which can lead to `ytdl-core` breaking or requiring updates to continue functioning. Developers should ensure they are using the latest version.
- gotcha The `begin` option for starting a video download at a specific timestamp is known to be unreliable for non-live videos, as documented in issues #129 and #219.
- gotcha Higher quality video formats (1080p and above) are often delivered without an accompanying audio track. Downloading such formats requires separate audio and video streams to be downloaded and then merged, typically with an external tool like FFmpeg.
- deprecated The primary maintainer has paused active development on `fent/node-ytdl-core` since July 14, 2023, with support now community-driven and PRs not currently merged. Users are encouraged to explore forks like `@distube/ytdl-core` for ongoing updates.
Install
-
npm install ytdl-core -
yarn add ytdl-core -
pnpm add ytdl-core
Imports
- ytdl
const ytdl = require('ytdl-core'); // CommonJS is supported, but ESM is preferred for modern Node.js and TypeScript projects.import ytdl from 'ytdl-core';
- getInfo
import { getInfo } from 'ytdl-core'; // getInfo is a method on the default export, not a named export.import ytdl from 'ytdl-core'; await ytdl.getInfo(url);
- getBasicInfo
import { getBasicInfo } from 'ytdl-core'; // getBasicInfo is a method on the default export, not a named export.import ytdl from 'ytdl-core'; await ytdl.getBasicInfo(url);
Quickstart
import * as fs from 'fs';
import ytdl from 'ytdl-core';
const videoUrl = 'http://www.youtube.com/watch?v=aqz-KE-bpKQ'; // Example video ID
const outputFileName = process.env.VIDEO_OUTPUT_PATH ?? 'video.mp4';
console.log(`Downloading video from ${videoUrl} to ${outputFileName}...`);
ytdl(videoUrl, { quality: 'highestaudio' })
.pipe(fs.createWriteStream(outputFileName))
.on('finish', () => {
console.log('Download complete!');
})
.on('error', (err) => {
console.error('Error during download:', err.message);
// Optionally delete partially downloaded file on error
if (fs.existsSync(outputFileName)) {
fs.unlinkSync(outputFileName);
}
});
// Example of fetching video information
// ytdl.getInfo(videoUrl).then(info => {
// console.log('Title:', info.videoDetails.title);
// console.log('Formats:', info.formats.length);
// }).catch(err => console.error('Error fetching info:', err.message));