Create Youtube Video Downloader with NodeJS

Programmer101N
May 10 · 4 min read

What we need for this tutorial

  • NodeJS and NPM
  • Express (For creating Web Server)
  • ytdl-core (npm module to get info of youtube video)
  • ejs (templating engine)

Setup our Project

Create a directory named yt_downloader and initialize a node project in that folder with npm init. Now Open Visual Studio Code or any other editor in that folder. Install all the modules needed with npm install ytdl-core express ejs

Now that we have our project setup, Let’s write some code.

Setting up our Server

Create file named index.js in that folder and write code.

const express = require("express");
const app = express();
const ytdl = require("ytdl-core");
app.set("view engine", "ejs");// OUR ROUTES WILL GO HERE
app.listen(3000, () => {
console.log("Server is running on http://localhost:3000");
});

You can run this server by typing nodemon . in your terminal.

Creating Simple GUI with EJS

Create a folder named views and inside it create a file named index.ejs and Create your GUI by writing simple HTML.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Youtube Downloader</title>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css"
integrity="sha384-B0vP5xmATw1+K9KRQjQERJvTumQW0nPEzvF6L/Z6nronJ3oUOFUFpCjEUQouq2+l"
crossorigin="anonymous"
/>
</head>
<body>
<div class="container my-5">
<h1><strong>Youtube Downloader</strong></h1>
<form method="GET" action='/download' class="my-5">
<div class="form-group">
<label for="videoURL"
>Video Link from Youtube</label
>
<input
type="text"
class="form-control"
placeholder="Enter Video URL"
name="url"
/>
</div>
<button type="submit" class="btn btn-primary">Download</button>
</form>
</div>
</body>
</html>

Here our form will make GET request with parameter of url to \download.

I used Bootstrap but you can use css, Just remember you have to serve the static files.

Create a new route \ to serve this index.ejs in your index.js

app.get("/", (req, res) => {
return res.render("index");
});

Creating \download Route.

Create a route that will pass the parameter url to download view.

app.get('\download' , (req, res) => {
const v_id = req.query.url.split('v=')[1];
return res.render('download', {
url: "https://www.youtube.com/embed/" + v_id,
});
});

In above code, I am getting the video id and passing custom embed to the url. (Youtube denies it’s embed to non-trusted websites)

Create new file download.ejs in your views directory.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Download Options for the link</title>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css"
integrity="sha384-B0vP5xmATw1+K9KRQjQERJvTumQW0nPEzvF6L/Z6nronJ3oUOFUFpCjEUQouq2+l"
crossorigin="anonymous"
/>
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css"
integrity="sha512-iBBXm8fW90+nuLcSKlbmrPcLa0OT92xO1BIsZ+ywDWZCvqsWgccV3gFoRBv0z+8dLJgyAHIhR35VZc2oM/gI1w=="
crossorigin="anonymous"
/>
<script
src="https://code.jquery.com/jquery-3.2.1.slim.min.js"
integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
crossorigin="anonymous"
></script>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
crossorigin="anonymous"
></script>
<script
src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
crossorigin="anonymous"
></script>
</head>
<body>
<div class="container">
<iframe class="d-flex" width="640" height="480" src="<%= url %>">
</iframe>
</div>
<div class="container">

</div>
</body>
</html>

Now let’s get our video info with ytdl-core module in our route. Since our ytdl-core library is async, we will create our route to async. I’m sorting my formats of the video by their mime types like video/webm and video/mp4.

app.get("/download", async (req, res) => {
const v_id = req.query.url.split('v=')[1];
const info = await ytdl.getInfo(req.query.url);
return res.render("download", {
url: "https://www.youtube.com/embed/" + v_id,
info: info.formats.sort((a, b) => {
return a.mimeType < b.mimeType;
}),
});
});

Now displaying the download button with EJS in our download.ejs file.

...
</iframe>
</div>
<div class="container">
<div class="btn-group">
<button
type="button"
class="btn btn-success dropdown-toggle"
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false"
>
Download
</button>
<div class="dropdown-menu">
<% info.forEach((format) => { %>
<a class="dropdown-item" href="<%= format.url %>">
<%= format.mimeType.split(";")[0] %> <%= format.hasVideo
? format.height + "p" : "" %> <% if(!format.hasAudio) {
%>
<i class="fas fa-volume-mute text-danger"></i>
<% } %>
</a>
<% }); %>
</div>
</div>
</div>
</body>
</html>

Now our video downloader is complete, if you click on download button, you can select which video to download.

You can download this project from my Github.

Visit this Project on Github

Also Check out my blog, Here is the Link.

Geek Culture

Proud to geek out. Follow to join our +500K monthly readers.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store