Introduction

Currently there are many chrome extensions available on Chrome to download videos from YouTube. But there are not any articles on how to make your own simple chrome extension to download from YouTube. This article will help readers understand the process and code involved.

In this post, we will see how we can download videos from Youtube by making our own simple chrome extension. This extension will have the following capabilities:

  • A drop-down list for video quality
  • A drop-down list for video format

We will take the help of node libraries ytdl-core and express to run a local node server. The entire code can be referenced at Github.

For those who are new to chrome extension development, please follow this blog to understand development of a simple Chrome Extension.

Glossary

  • ytdl-core: A node-package for Youtube downloading
  • ReadStream: A readable stream is an abstraction for a source from which data can be consumed
  • WriteStream: Streams to which data can be written

Steps:

First, create a project directory. There are two parts of this project: running a node server and creating the extension. We will first understand how to setup the node server.

Setup a local node server to facilitate Youtube Video Downloads

To setup a local node server, we first need to have node-js installed on our system. After installing node-js, cd into the project directory and run npm init. This will create a package.json file in the project directory.

Next, we need express module and ytdl-core module for our purpose. Therefore, run npm install ytdl-core express. This will download and load the required node_modules into the project directory. Now, we need to create a index.js file. Put the following code in index.js:

var express = require('express');
var app = express();
var ytdl = require('ytdl-core');

app.listen('4000', function(){
	console.log("listening on 4000");
});

app.get('/download', function(req, res) {
	var link = req.query.url;
	var format = req.query.format;
	var quality = req.query.quality;

	video = ytdl(link,{
		format:format,
		quality:quality,
	});
	video.pipe(res);
});

In the above code, we first load the required node modules and then we make out app listen on port 4000. Next, we handle a GET request from the extension which will be more clear in the following section.

Writing the Chrome Extension for YouTube Downloads

Once we have setup a node-server locally, it is time to start building the extension.

Create a src/ folder inside the project directory. This src folder will contain the extension code. Then, create a manifest.json file inside the src folder.

{
    "name": "YouTube Downloader",
    "version": "1.0",
    "manifest_version": 2,

    "description": "Download from YouTube",
    "page_action": {
        "default_title": "Download from YouTube",
        "default_popup": "popup.html"
    },
    "permissions": [
        "downloads",
        "activeTab",
        "declarativeContent"
    ],
    "background" : {
        "scripts" : ["background.js"],
        "persistent" : false
    }
}

Since, we want our extension to run only on YouTube, we will make it a Page-Action extension rather than Browser-Action.

Next step is to create the extension html. For this, create a popup.html file inside the src folder.

<!DOCTYPE html>
<html>
<head>
	<title>Chrome Extension for Youtube Downloading</title>
	http://main.js
	<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
	<h1>Youtube Downloader</h1>
	<label for="quality">Quality</label>
	<select id="quality">
		 <option value="highest">highest</option>
		 <option value="lowest">lowest</option>
		 <option value="highestaudio">highestaudio</option>
		 <option value="lowestaudio">lowestaudio</option>
		 <option value="highestvideo">highestvideo</option>
		 <option value="lowestvideo">lowestvideo</option>
	</select>
	<label for="filename">SaveAs</label>
	<input id="filename" placeholder="<filename>">
	<label for="format">Format</label>
	<select id="format">
		 <option value="mp4">mp4</option>
		 <option value="wmv">wmv</option>
		 <option value="flv">flv</option>
		 <option value="avi">avi</option>
		 <option value="mp3">mp3</option>
		 <option value="mpg">mpg</option>
	</select>
	<button id="download">Download</button>

	
</body>
</html>

This adds a drop-down for selecting video quality and video format and an input element for the filename of the downloaded video. Finally, there’s a download button.

Next, we will create a javascript file: main.js inside the src folder.

window.onload = function() {
	var quality = document.getElementById('quality');
	var filename = document.getElementById('filename');
	var format = document.getElementById('format');
	var dButton = document.getElementById('download');
	
	dButton.onclick = function(){
		console.log("button  clicked");
		chrome.tabs.query({'active': true, 'lastFocusedWindow': true}, function (tabs) {
	    	var url = tabs[0].url;
	    	var message  = {
	    		'url' : url,
	    		'quality': quality.value,
	    		'filename': filename.value,
	    		'format': format.value
	    	};
	    	chrome.runtime.sendMessage(message);
		});
	};
}

Here, we are using the chrome.tabs API to fetch the current video url. After that, we create a json message containing video URL, video Quality, video Format and filename, i.e. all the parameters that we took input from user.

Next step is to write background.js which is more of an event page for the extension. Create a file background.js inside src folder.

chrome.runtime.onInstalled.addListener(function() {
	chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {
		chrome.declarativeContent.onPageChanged.addRules([{
			conditions: [
				new chrome.declarativeContent.PageStateMatcher({
					pageUrl: { hostContains: 'youtube'}
				})
			],
			actions: [ new chrome.declarativeContent.ShowPageAction() ]
		}]);
	});
});

chrome.runtime.onMessage.addListener(function(message) {
	var url = 'http://localhost:4000/download?';
	var queryString = Object.keys(message).map(key => key + '=' + message[key]).join('&');
	url += queryString;
	console.log(url);
	chrome.downloads.download({url:url,
		filename: "YoutubeDownloader/" + message.filename +'.' + message.format}, function(downID) {
			chrome.downloads.show(downID);
	});
});

In this script, we first create a query to send to the server running locally at localhost:4000. In the request query, we add all required params. Then, we use chrome.downloads API to send the GET request to server. Now, if we go back to index.js, we have handled a get request of action ‘download’. When the server receives this GET request, we use ytdl-core module to generate a readable stream and then we write it to a writable stream, in our case, response. The response is then received back into the extension and a video file gets downloaded within a folder “YoutubeDownloader” with the filename and format specified by the user in the defaults downloaded directory.

Learning Tools

  • Developer.chrome.com/extensions/devguide is a good place to start if you already have knowledge of javascript.
  • Chrome offers many APIs, to develop chrome extensions and apps. Understanding their use is a big plus.
  • I have used ytdl-core npm module for this project. ytdl-core, itself provide a lot of functionalities to play around with youTube videos.
  • There are many other libraries in node to play around with YouTube videos such as ytdl, youtube-node, youtube-api etc.

Learning Strategy

Initially, I thought of doing this project without the use of running a server locally. I thought so because there are many modules in node which can be used within the web browser using a module called browserify. Therefore, I tried to use ytdl-core module inside my extension using browserify. Now, since ytdl-core constructor returns a readable stream, it can be only used in extension if one can have file-system access to create read and writable streams. But, the Chrome file-system API cannot be used in chrome extensions, therefore, I could not figure out a way for doing this project without running a local server. So, I got to read a lot about file-system usage and readable and writable streams in doing this project.

Reflective Analysis

We know that there many extensions available on chrome for downloading youtube videos. In this article, we have tried to build our own simple extension to download from YouTube. We have understood, how we can make use of node-modules to setup a local server. We have also understood how to make http requests to the server for downloading videos.

Conclusion and Future directions

In this article, we have understood how we can make our own simple chrome extension to download videos from YouTube without any hassle. We have added options for format and quality. Moving forward, we can also implement downloading a specific part of video by taking the start time and end time as user input.

So, That’s it! Thanks for reading. Complete source code is on Github.