• Stars
    star
    4,507
  • Rank 9,474 (Top 0.2 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created over 10 years ago
  • Updated 3 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

YouTube video downloader in javascript.

node-ytdl-core

Depfu codecov Discord

Yet another YouTube downloading module. Written with only Javascript and a node-friendly streaming interface.

Support

You can contact us for support on our chat server

Usage

const fs = require('fs');
const ytdl = require('ytdl-core');
// TypeScript: import ytdl from 'ytdl-core'; with --esModuleInterop
// TypeScript: import * as ytdl from 'ytdl-core'; with --allowSyntheticDefaultImports
// TypeScript: import ytdl = require('ytdl-core'); with neither of the above

ytdl('http://www.youtube.com/watch?v=aqz-KE-bpKQ')
  .pipe(fs.createWriteStream('video.mp4'));

API

ytdl(url, [options])

Attempts to download a video from the given url. Returns a readable stream. options can have the following, in addition to any getInfo() option and chooseFormat() option.

  • range - A byte range in the form {start: INT, end: INT} that specifies part of the file to download, ie {start: 10355705, end: 12452856}. Not supported on segmented (DASH MPD, m3u8) formats.
    • This downloads a portion of the file, and not a separately spliced video.
  • begin - What time in the video to begin. Supports formats 00:00:00.000, 0ms, 0s, 0m, 0h, or number of milliseconds. Example: 1:30, 05:10.123, 10m30s.
    • For live videos, this also accepts a unix timestamp or Date object, and defaults to Date.now().
    • This option is not very reliable for non-live videos, see #129 and #219.
  • liveBuffer - How much time buffer to use for live videos in milliseconds. Default is 20000.
  • highWaterMark - How much of the video download to buffer into memory. See node's docs for more. Defaults to 512KB.
  • dlChunkSize - When the chosen format is video only or audio only, the download is separated into multiple chunks to avoid throttling. This option specifies the size of each chunk in bytes. Setting it to 0 disables chunking. Defaults to 10MB.
  • IPv6Block - IPv6 block to rotate through, an alternative to using a proxy. Read more. Defaults to undefined.

Event: info

Emitted when the video's info is fetched, along with the chosen format to download.

Event: progress

  • number - Chunk length in bytes or segment number.
  • number - Total bytes or segments downloaded.
  • number - Total bytes or segments.

Emitted whenever a new chunk is received. Passes values describing the download progress.

miniget events

All miniget events are forwarded and can be listened to from the returned stream.

Stream#destroy()

Call to abort and stop downloading a video.

async ytdl.getBasicInfo(url, [options])

Use this if you only want to get metainfo from a video.

async ytdl.getInfo(url, [options])

Gets metainfo from a video. Includes additional formats, and ready to download deciphered URL. This is what the ytdl() function uses internally.

options can have the following

  • requestOptions - Anything to merge into the request options which miniget is called with, such as headers.
  • requestCallback - Provide a callback function that receives miniget request stream objects used while fetching metainfo.
  • lang - The 2 character symbol of a language. Default is en.

ytdl.downloadFromInfo(info, options)

Once you have received metadata from a video with the ytdl.getInfo function, you may pass that information along with other options to this function.

ytdl.chooseFormat(formats, options)

Can be used if you'd like to choose a format yourself. Throws an Error if it fails to find any matching format.

options can have the following

  • quality - Video quality to download. Can be an itag value, a list of itag values, or one of these strings: highest/lowest/highestaudio/lowestaudio/highestvideo/lowestvideo. highestaudio/lowestaudio try to minimize video bitrate for equally good audio formats while highestvideo/lowestvideo try to minimize audio respectively. Defaults to highest, which prefers formats with both video and audio.

    A typical video's formats will be sorted in the following way using quality: 'highest'

    itag container quality codecs                 bitrate  audio bitrate
    18   mp4       360p    avc1.42001E, mp4a.40.2 696.66KB 96KB
    137  mp4       1080p   avc1.640028            4.53MB
    248  webm      1080p   vp9                    2.52MB
    136  mp4       720p    avc1.4d4016            2.2MB
    247  webm      720p    vp9                    1.44MB
    135  mp4       480p    avc1.4d4014            1.1MB
    134  mp4       360p    avc1.4d401e            593.26KB
    140  mp4               mp4a.40.2                       128KB
    

    format 18 at 360p will be chosen first since it's the highest quality format with both video and audio. If you'd like a higher quality format with both video and audio, see the section on handling separate streams.

  • filter - Used to filter the list of formats to choose from. Can be audioandvideo or videoandaudio to filter formats that contain both video and audio, video to filter for formats that contain video, or videoonly for formats that contain video and no additional audio track. Can also be audio or audioonly. You can give a filtering function that gets called with each format available. This function is given the format object as its first argument, and should return true if the format is preferable.

    // Example with custom function.
    ytdl(url, { filter: format => format.container === 'mp4' })
  • format - Primarily used to download specific video or audio streams. This can be a specific format object returned from getInfo.

    • Supplying this option will ignore the filter and quality options since the format is explicitly provided.
// Example of choosing a video format.
let info = await ytdl.getInfo(videoID);
let format = ytdl.chooseFormat(info.formats, { quality: '134' });
console.log('Format found!', format);

ytdl.filterFormats(formats, filter)

If you'd like to work with only some formats, you can use the filter option above.

// Example of filtering the formats to audio only.
let info = await ytdl.getInfo(videoID);
let audioFormats = ytdl.filterFormats(info.formats, 'audioonly');
console.log('Formats with only audio: ' + audioFormats.length);

ytdl.validateID(id)

Returns true if the given string satisfies YouTube's ID format.

ytdl.validateURL(url)

Returns true if able to parse out a valid video ID.

ytdl.getURLVideoID(url)

Returns a video ID from a YouTube URL. Throws an Error if it fails to parse an ID.

ytdl.getVideoID(str)

Same as the above ytdl.getURLVideoID(), but can be called with the video ID directly, in which case it returns it. This is what ytdl uses internally. Throws an Error if it fails to parse an ID.

ytdl.version

The version string taken directly from the package.json.

Limitations

ytdl cannot download videos that fall into the following

  • Regionally restricted (requires a proxy)
  • Private (if you have access, requires cookies)
  • Rentals (if you have access, requires cookies)
  • YouTube Premium content (if you have access, requires cookies)
  • Only HLS Livestreams are currently supported. Other formats will get filtered out in ytdl.chooseFormats

Generated download links are valid for 6 hours, and may only be downloadable from the same IP address.

Ratelimits

When doing to many requests YouTube might block. This will result in your requests getting denied with HTTP-StatusCode 429. The following Steps might help you:

  • Update ytdl-core to the latest version
  • Use proxies (you can find an example here)
  • Extend on the Proxy Idea by rotating (IPv6-)Addresses
    • read this for more information about this
  • Use cookies (you can find an example here)
    • for this to take effect you have to FIRST wait for the current ratelimit to expire
  • Wait it out (it usually goes away within a few days)

How does using an IPv6 block help?

For request-intensive tasks it might be useful to spread your requests across multiple source IP-Addresses. Changing the source IP that you use is similar to using a proxy, except without bypassing restrictions such as a region lock. More IP-Addresses result in less requests per IP and therefor increase your ratelimit. Since IPv4 Addresses are a limited Resource we advise to use IPv6.

Using an IPv6 block is essentially having millions of IPv6 addresses at your request. In a /64 IPv6 block (which is usually the Block given to a single Household), there are 18,446,744,073,709,551,616 unique IPv6 addresses. This would allow you to make each request with a different IPv6 address.

Even though using an IP-Block does help against ratelimits it requires you to setup your host system to accept http traffic from every message in an IP-Block. We can not help you with the setup for any specific host / hosting provider but searching the internet most likely can.

Handling Separate Streams

Typically 1080p or better videos do not have audio encoded with it. The audio must be downloaded separately and merged via an encoding library. ffmpeg is the most widely used tool, with many Node.js modules available. Use the format objects returned from ytdl.getInfo to download specific streams to combine to fit your needs. Look at example/ffmpeg.js for an example on doing this.

What if it stops working?

YouTube updates their website all the time, it's not that rare for this to stop working. If it doesn't work for you and you're using the latest version, feel free to open up an issue. Make sure to check if there isn't one already with the same error.

Run the tests at test/irl-test.js to make sure this is really an issue with ytdl-core.

npm run test:irl

These tests are not mocked, they try to start downloading a few videos. If these fail, then it's time to debug. If the error you're getting is signature deciphering, check lib/sig.js. Otherwise, the error is likely within lib/info.js.

Install

npm install ytdl-core@latest

Or for Yarn users:

yarn add ytdl-core@latest

Make sure you're installing the latest version of ytdl-core to keep up with the latest fixes.

If you're using a bot or app that uses ytdl-core such as ytdl-core-discord or discord-player, it may be dependent on an older version. To update its ytdl-core version, that library has to update its package.json file, you can't simply change the version on your project's package.json, the app will still use its own older version of ytdl-core.

Look in their repo to see if they already have an active pull request that updates ytdl-core. If they don't, open an issue asking them to update ytdl-core, or better yet, fork the project and submit a pull request with the updated version.

While you wait for the pull reques to merge, you can point to its branch in your package.json

  "ytdl-core-discord": "amishshah/ytdl-core-discord#dependabot/npm_and_yarn/ytdl-core-2.0.1"

Update Checks

The issue of using an outdated version of ytdl-core became so prevalent, that ytdl-core now checks for updates at run time, and every 12 hours. If it finds an update, it will print a warning to the console advising you to update. Due to the nature of this library, it is important to always use the latest version as YouTube continues to update.

If you'd like to disable this update check, you can do so by providing the YTDL_NO_UPDATE env variable.

env YTDL_NO_UPDATE=1 node myapp.js

Related Projects

  • ytdl - A cli wrapper of this.
  • pully - Another cli wrapper of this aimed at high quality formats.
  • ytsr - YouTube video search results.
  • ytpl - YouTube playlist and channel resolver.

Tests

Tests are written with mocha

npm test

More Repositories

1

randexp.js

Create random strings that match a given regular expression.
JavaScript
1,779
star
2

node-ytdl

Command line youtube video downloader.
JavaScript
1,188
star
3

node-m3u8stream

Concatenates segments from a m3u8/dash-mpd playlist into a consumable stream.
TypeScript
213
star
4

node-feedsub

Subscribes to RSS/Atom/JSON feeds and notifies on new items.
TypeScript
196
star
5

timequeue.js

A queue with custom concurrency and time limit.
TypeScript
191
star
6

node-torrent

Torrent reader, writer, and hash checker for node.
JavaScript
190
star
7

feedme.js

RSS/Atom/JSON feed parser
TypeScript
155
star
8

clusterhub

Sync data in your cluster applications.
JavaScript
131
star
9

ret.js

Tokenizes a string that represents a regular expression.
JavaScript
90
star
10

socket.io-clusterhub

socket.io storage powered by clusterhub for multi process applications.
JavaScript
70
star
11

chrome-options

Options page for Chrome extensions
JavaScript
64
star
12

node-muk

Mock object methods and dependencies.
JavaScript
57
star
13

node-miniget

A small http(s) GET library.
TypeScript
52
star
14

node-streamify

Streamify helps you easily provide a streaming interface for your code.
JavaScript
51
star
15

pauseable.js

Create event emitters, intervals, and timeouts that can be paused and resumed.
JavaScript
47
star
16

node-streamspeed

A simple way to keep track of the speed of your node streams.
TypeScript
38
star
17

irc-colors.js

Color and formatting for irc bots made easy. Inspired by colors.js and cli-color.
JavaScript
35
star
18

node-kat

File and stream concatenation the right way.
JavaScript
25
star
19

node-stream-equal

Test that two readable streams are equal to each other.
TypeScript
24
star
20

node-streamin

Provide a better streaming api in your app.
JavaScript
20
star
21

npm-updates

Emits update events from the npm repository.
JavaScript
16
star
22

node-jstream

Continuously reads in JSON and outputs Javascript objects.
JavaScript
16
star
23

muk-prop.js

Mock object methods and properties
JavaScript
12
star
24

hook.io-feedsub

hook.io bindings for RSS/Atom/JSON feeds
JavaScript
11
star
25

node-eventyoshi

Allows several event emitters to be listened and emitted through a single one.
JavaScript
11
star
26

node-torrent-cli

CLI for reading, writing, and hash checking torrents
JavaScript
10
star
27

chrome-veefeed

Follow YouTube and Twitch channels, get notifications, categorize videos
JavaScript
9
star
28

pokecry

guess pokemon through their cries
JavaScript
8
star
29

node-newsemitter

An event emitter that emits only new events.
TypeScript
7
star
30

clusterchat

A simple multi process chat demo using socket.io-clusterhub
JavaScript
7
star
31

ordered-queue.js

Queue with concurrency that starts tasks in order and runs them in parallel.
JavaScript
7
star
32

node-module-boilerplate

My personal boilerplate that I use to create node modules.
JavaScript
6
star
33

vim-relative-indent

Hide leading indent
Vim Script
5
star
34

hook.io-npm

Hook that emits on npm module updates.
JavaScript
5
star
35

jps

A scraper for the jpopsuki tracker.
JavaScript
5
star
36

nickserv

Communicates with the NickServ IRC service
JavaScript
5
star
37

node-streamit

JavaScript
4
star
38

ann

IRC bot made to announce and for convenience.
CoffeeScript
4
star
39

vim-frozen

colorscheme for vim
Vim Script
3
star
40

twi

really basic twitter cli client
JavaScript
3
star
41

node-writestreamp

A writable file stream that creates directories as needed.
JavaScript
3
star
42

gifchat

gifphy bot for hipchat
JavaScript
2
star
43

queue2.js

A unordered queue and ordered queue working together.
JavaScript
2
star
44

pokenum

A way to remember numbers using Pokemon.
JavaScript
1
star
45

node-muk-require

Mock dependencies
JavaScript
1
star
46

nickie

Nickserv irc bot.
JavaScript
1
star
47

node-callme

Hey I just met you, and this is crazy, but here's my callback.
JavaScript
1
star
48

jquery.rubber.js

jQuery plugin that stretches text fields to fit their content.
JavaScript
1
star