Blog Desire

How to create a YouTube video downloader using PHP?

Are you tired of trying different youtube downloaders and with all their limitations? Or you might be tired of seeing all the tutorials that are using the “https://youtube.com/get_video_info” parameter which doesn’t work anymore? Well, not anymore, let’s break the ice and build our own youtube video downloader today. So, without further talking, let’s get started!

YouTube Video downloader

Here is a quick overview of what we need in order to download a video.

Before we get started, we need to get info about the video we want to download from youtube. This method has been updated recently. That’s why most of the old tutorials about youtube video downloaders are broken. So, let’s take a look at the new method. Please save this function in a file called function.php

<?php
function getVideoInfo($video_id){

    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL, 'https://www.youtube.com/youtubei/v1/player?key=AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, '{  "context": {    "client": {      "hl": "en",      "clientName": "WEB",      "clientVersion": "2.20210721.00.00",      "clientFormFactor": "UNKNOWN_FORM_FACTOR",   "clientScreen": "WATCH",      "mainAppWebInfo": {        "graftUrl": "/watch?v='.$video_id.'",           }    },    "user": {      "lockedSafetyMode": false    },    "request": {      "useSsl": true,      "internalExperimentFlags": [],      "consistencyTokenJars": []    }  },  "videoId": "'.$video_id.'",  "playbackContext": {    "contentPlaybackContext": {        "vis": 0,      "splay": false,      "autoCaptionsDefaultOn": false,      "autonavState": "STATE_NONE",      "html5Preference": "HTML5_PREF_WANTS",      "lactMilliseconds": "-1"    }  },  "racyCheckOk": false,  "contentCheckOk": false}');
    curl_setopt($ch, CURLOPT_ENCODING, 'gzip, deflate');

    $headers = array();
    $headers[] = 'Content-Type: application/json';
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

    $result = curl_exec($ch);
    if (curl_errno($ch)) {
        echo 'Error:' . curl_error($ch);
    }
    curl_close($ch);
    return $result;

}

In the code above, we created a PHP function called getVideoInfo. If you call the function with a youtube video id as a parameter, it will return all the information about the video in object format. Now that we have the code to get all information about a video, let’s build a youtube video downloader form right away.

YouTube Video Downloader Form

To provide users a nice interface to put a video URL, we should create an HTML form first. Create a file called index.php in the same folder you created the function.php before. Now, write the code below in your index.php file.

Note: You can download a form generator provided by blog desire for free from here.

<?php require './function.php'; $error = "";?>
<html lang="en" class="h-100">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>Download YouTube video</title>
    <!-- Font-->
    <link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400&display=swap" rel="stylesheet">
    <!-- Bootstrap core CSS -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@4.3.1/dist/css/bootstrap.css" rel="stylesheet">
    <style>
        body {
            font-family: 'Montserrat', sans-serif;
        }
        .formSmall {
            width: 700px;
            margin: 20px auto 20px auto;
        }
    </style>

</head>
<body>
    <div class="container">
        <form method="post" action="" class="formSmall">
            <div class="row">
                <div class="col-lg-12">
                    <h7 class="text-align"> Download YouTube Video</h7>
                </div>
                <div class="col-lg-12">
                    <div class="input-group">
                        <input type="text" class="form-control" name="video_link" placeholder="Paste link.. e.g. https://www.youtube.com/watch?v=5cpIZ8zHHXw" <?php if(isset($_POST['video_link'])) echo "value='".$_POST['video_link']."'"; ?>>
                        <span class="input-group-btn">
                        <button type="submit" name="submit" id="submit" class="btn btn-primary">Go!</button>
                      </span>
                    </div><!-- /input-group -->
                </div>
            </div><!-- .row -->
        </form>

       <!-- Place Your Video Downloader Code Here -->
    </div>
</body>
</html>

You might have noticed that we have used a couple of PHP codes in the form. That’s because we want to keep track of user input in the input field. Now that we have an HTML form for user input and a function that returns any video information, we may proceed furthermore.

Generate a download link

We have a function that can return any video info and a form that accepts user input. Now, it’s our task to combine them both and get info about any video that a user may provide using our form. And after that, we should provide them a download button as well. Once again, here is what we need to do in order to achieve this.

To do so, we need to place some code in our index.php file and here they are

<?php if(isset($_POST['submit'])): ?>


    <?php 
    $video_link = $_POST['video_link'];
    preg_match('%(?:youtube(?:-nocookie)?\.com/(?:[^/]+/.+/|(?:v|e(?:mbed)?)/|.*[?&]v=)|youtu\.be/)([^"&?/ ]{11})%i', $video_link, $match);
    $video_id =  $match[1];
    $video = json_decode(getVideoInfo($video_id));
    $formats = $video->streamingData->formats;
    $adaptiveFormats = $video->streamingData->adaptiveFormats;
    $thumbnails = $video->videoDetails->thumbnail->thumbnails;
    $title = $video->videoDetails->title;
    $short_description = $video->videoDetails->shortDescription;
    $thumbnail = end($thumbnails)->url;
    ?>
    
    
    <div class="row formSmall">
        <div class="col-lg-3">
            <img src="<?php echo $thumbnail; ?>" style="max-width:100%">
        </div>
        <div class="col-lg-9">
            <h2><?php echo $title; ?> </h2>
            <p><?php echo str_split($short_description, 100)[0]; ?></p>
        </div>
    </div>
    
    <?php if(!empty($formats)): ?>
    
    
        <?php if(@$formats[0]->url == ""): ?>
        <div class="card formSmall">
            <div class="card-header">
                <strong>This video is currently not supported by our downloader!</strong>
                <small><?php 
                $signature = "https://example.com?".$formats[0]->signatureCipher;
                            parse_str( parse_url( $signature, PHP_URL_QUERY ), $parse_signature );
                            $url = $parse_signature['url']."&sig=".$parse_signature['s'];
                       ?>
                </small>
            </div>
        </div>
        <?php 
        die();
        endif;
        ?>
        
        <div class="card formSmall">
            <div class="card-header">
                <strong>With Video & Sound</strong>
            </div>
            
            <div class="card-body">
                <table class="table ">
                    <tr>
                        <td>URL</td>
                        <td>Type</td>
                        <td>Quality</td>
                        <td>Download</td>
                    </tr>
                    <?php foreach($formats as $format): ?>
                        <?php
                        
                        if(@$format->url == ""){
                            $signature = "https://example.com?".$format->signatureCipher;
                            parse_str( parse_url( $signature, PHP_URL_QUERY ), $parse_signature );
                            $url = $parse_signature['url']."&sig=".$parse_signature['s'];
                        }else{
                            $url = $format->url;
                        }
                        
                            
                        
                        
                        ?>
                        <tr>
                            <td><a href="<?php echo $url; ?>">Test</a></td>
                            <td>
                                <?php if($format->mimeType) echo explode(";",explode("/",$format->mimeType)[1])[0]; else echo "Unknown";?>
                            </td>
                            <td>
                                <?php if($format->qualityLabel) echo $format->qualityLabel; else echo "Unknown"; ?>
                            </td>
                            <td>
                                <a 
                                    href="downloader.php?link=<?php echo urlencode($url)?>&title=<?php echo urlencode($title)?>&type=<?php if($format->mimeType) echo explode(";",explode("/",$format->mimeType)[1])[0]; else echo "mp4";?>"
                                >
                                    Download
                                </a> 
                            </td>
                        </tr>
                    <?php endforeach; ?>
                </table>
            </div>
        </div>
        
        <!-- Your code here for additional formats -->
        
    <?php endif; ?>


<?php endif; ?>

Please replace the <!– Place Your Video Downloader Code Here –> part with the code snippet above. At this point, users can provide any video URL and they will get a download link for that particular video. Pretty cool right? But wait, this is not the end. We still need to create a downloader file.

Create the downloader file

You might be wondering why we’re going to create another downloader file when we already have the stream URL. Well, this file is to download the video from the Stream URL. This is the last file we will be creating for this tutorial. So, let’s just create another file called downloader.php in the same directory. Done? Now save the code below in your downloader.php file.

<?php
$downloadURL = urldecode($_GET['link']);
$type = urldecode($_GET['type']);
$title = urldecode($_GET['title']);
$fileName = $title.'.'.$type;


if (!empty($downloadURL) && substr($downloadURL, 0, 8) === 'https://') {
    header("Cache-Control: public");
    header("Content-Description: File Transfer");
    header("Content-Disposition: attachment;filename=\"$fileName\"");
    header("Content-Transfer-Encoding: binary");

    readfile($downloadURL);

}

and boom, you are good to go with your own youtube video downloader!

Bonus!

You can replace the <!– Your code here for additional formats –> in your index.php with the code below to provide users all additional formats of the video to download!

<div class="card formSmall">
    <div class="card-header">
        <strong>Videos video only/ Audios audio only</strong>
    </div>
    <div class="card-body">
        <table class="table ">
            <tr>
                <td>Type</td>
                <td>Quality</td>
                <td>Download</td>
            </tr>
            <?php foreach ($adaptiveFormats as $video) :?>
                <?php
                try{
                    $url = $video->url;
                }catch(Exception $e){
                    $signature = $video->signatureCipher;
                    parse_str( parse_url( $signature, PHP_URL_QUERY ), $parse_signature );
                    $url = $parse_signature['url'];
                }
                
                ?>
                <tr>
                    <td><?php if(@$video->mimeType) echo explode(";",explode("/",$video->mimeType)[1])[0]; else echo "Unknown";?></td>
                    <td><?php if(@$video->qualityLabel) echo $video->qualityLabel; else echo "Unknown"; ?></td>
                    <td><a href="downloader.php?link=<?php print urlencode($url)?>&title=<?php print urlencode($title)?>&type=<?php if($video->mimeType) echo explode(";",explode("/",$video->mimeType)[1])[0]; else echo "mp4";?>">Download</a> </td>
                </tr>
            <?php endforeach;?>
        </table>
    </div>
</div>

Demo and Source Code

You can check a demo version of the YouTube Video Downloader from here. Or you can download the source code from here

Please Note: Some video doesn’t return a Stream URL, the script currently doesn’t support such videos. But I’m working on it and will update the tutorial as soon as I can find a solution for such videos.

I hope you found this article helpful. If so, a share from you will make my day. If you face any problems, please let me know in the comment section. Stay safe, have a great day.

Update:

For anyone, who wants to accept a youtube short link like “https://youtu.be/5cpIZ8zHHXw”, should update your downloaded index.php file with the code given for this file in this article. Because this article has been updated but the source code is still old.

Hope this helps. If you still need further assistance, you can let me know via email or a comment. Thanks

Exit mobile version