YouTube Media Converter PHP Script Documentation

Getting Started

What is YouTube Media Converter?

YouTube Media Converter is a very fast, high-quality YouTube to MP3 Converter and Video Downloader.


  • Linux Server (All Linux distributions supported)
  • Works with any hosting plan (Shared*, Dedicated, VPS, etc.)
  • Apache or Nginx
  • PHP 5.3 or later
  • PHP GD extension
  • cURL and PHP cURL extension
  • FFmpeg and libmp3lame codec
  • Apache's mod_rewrite (Nginx rewriting instructions)
  • YouTube API Key (free)
  • 50 MB Disk Space on Server

* Note: If you are a using a shared hosting plan, please ensure that FFmpeg and cURL are installed.


  • Converts YouTube video to MP3 in milliseconds, at qualities up to 320kbps
  • Leverages the power of FFmpeg to create crisp, clean, quality, video-to-MP3 conversions
  • Downloads YouTube videos directly to MP4, 3GP, FLV, and WEBM
  • Supports the download of HD and Ultra HD video (2k and 4k), if available
  • Allows users to download all but MP3 formats directly from YouTube, bypassing your server and saving bandwidth
  • Downloads/Converts encrypted YouTube (e.g., Vevo channel) videos
  • Enables video preview as well as audio playback (via Integrated Music Player) prior to download/conversion
  • Integrates YouTube Search (accepts search term, video page URL, or playlist URL)
  • Displays Top Videos (filterable by Country)
  • Fully optimized for SEO, featuring dynamic Meta and Open Graph tags, dynamic image shares, automatic generation of robots.txt and XML sitemaps, video search URLs/links, and progressive enhancement to facilitate search bot crawling
  • Includes a JSON RESTful API and Button/Iframe API to facilitate software integration in a variety of use-case scenarios
  • Enables multi-language support via easy-to-add (and easy-to-edit!) translation files
  • Requires very little disk space because downloaded/converted files are not stored on server!
  • Effortlessly configure a multitude of software options via an easy-to-read Config file
  • Includes a "config check" utility to facilitate the software's installation and help resolve any issues with the server configuration
  • Facilitates the addition of more pages via common header, footer, and CSS files
  • Optionally rotates between multiple outgoing IPs to prevent temporary IP bans and/or CAPTCHAs imposed by YouTube
  • Optionally rotates between multiple YouTube API keys to effectively extend API usage limits
  • Features a completely "responsive" default design (leveraging the Bootstrap framework) to provide optimal viewing for ALL device types and sizes!
  • Programmed entirely in easy-to-read PHP OOP (Object Oriented Programming), JavaScript/jQuery, and CSS
  • Enables effortless editing/customization of code
  • Leverages MVC coding principles to enable templating and clear separation of presentation and business logic

Server Configuration

When in doubt, have a pro admin or hosting provider install the required dependency packages for you. Alternatively, we can also perform the server setup for an additional cost.

For the "Do-It-Yourselfers", general command-line instructions (for installing ALL required software dependencies) are available for the following, popular Linux distributions:

(Note: These instructions are provided as a convenience and courtesy to you. They are not a substitute for a professional server configuration. Generally, it is not my responsibility to teach you how to install and configure packages on, or administer and maintain, a Linux system.)

Debian 7 (Wheezy) and Debian 8 (Jessie)

Update Sources

apt-get update

Install Apache Webserver and PHP 5

apt-get install apache2 php5

Create your Domain Directory

mkdir /var/www/YOURDOMAIN.COM

Change Domain Directory Owner

chown www-data:www-data /var/www/YOURDOMAIN.COM

Install text editor "nano"

apt-get install nano

Create Apache vHost

nano /etc/apache2/sites-enabled/YOURDOMAIN.COM.conf

Add the following to the file (via nano), then Press Ctrl + O to save the file and Ctrl + X to close the nano editor:

<VirtualHost *:80>

DocumentRoot "/var/www/YOURDOMAIN.COM"


Enable Apache's "mod_rewrite"

a2enmod rewrite
/etc/init.d/apache2 restart

Install GD PHP Extension

apt-get install php5-gd

Install cURL and cURL PHP Extension

apt-get install curl php5-curl

Add Debian Multimedia Repo Sources List for FFmpeg and Codecs

nano /etc/apt/sources.list.d/

Add the following to the file (via nano):

  • For Debian 7 (Wheezy)
    • # Debian Multimedia Repository 
      deb wheezy main non-free
      deb wheezy-backports main
  • For Debian 8 (Jessie)
    • # Debian Multimedia Repository 
      deb jessie main non-free
      deb jessie-backports main
  • Press Ctrl + O to save the file
  • Press Ctrl + X to close the nano Editor

Update Sources

apt-get update

Install "deb-multimedia-keyring"

apt-get install deb-multimedia-keyring

Update Sources

apt-get update

Install FFmpeg

apt-get install ffmpeg

Ubuntu 12.04, Ubuntu 14.04, and Ubuntu 16.04

Update Sources

sudo apt-get update

Install Apache Webserver and PHP

  • For Ubuntu 12.04 and 14.04
    • sudo apt-get install apache2 php5
  • For Ubuntu 16.04
    • sudo apt-get install apache2 php7.0

Create your Domain Directory

sudo mkdir /var/www/YOURDOMAIN.COM

Change Domain Directory Owner

sudo chown www-data:www-data /var/www/YOURDOMAIN.COM

Install text editor "nano"

sudo apt-get install nano

Create Apache vHost

sudo nano /etc/apache2/sites-enabled/YOURDOMAIN.COM.conf

Add the following to the file (via nano), then Press Ctrl + O to save the file and Ctrl + X to close the nano editor:

<VirtualHost *:80>

DocumentRoot "/var/www/YOURDOMAIN.COM"


Enable Apache's "mod_rewrite"

sudo a2enmod rewrite
sudo /etc/init.d/apache2 restart

Install GD PHP Extension

  • For Ubuntu 12.04 and 14.04
    • sudo apt-get install php5-gd
  • For Ubuntu 16.04
    • sudo apt-get install php7.0-gd

Install cURL and cURL PHP Extension

  • For Ubuntu 16.04
    • sudo apt-get install curl php7.0-curl
  • For Ubuntu 12.04 and 14.04
    • sudo apt-get install curl php5-curl
  • For Ubuntu 12.04
    • Open '/etc/php5/apache2/php.ini' and add this line
    • Restart Apache

      sudo /etc/init.d/apache2 restart

Install FFmpeg

  • For Ubuntu 12.04 and 16.04
    • sudo apt-get install ffmpeg
  • For Ubuntu 14.04
    • Add FFmpeg Repo

      sudo add-apt-repository ppa:kirillshkrogalev/ffmpeg-next
    • Update Sources

      sudo apt-get update
    • Install FFmpeg

      sudo apt-get install ffmpeg

Install on CentOS 6.x and CentOS 7.x

Install Apache

yum install httpd

Install wget & gcc

yum install wget gcc

Install epel repo

  • For CentOS 6.x
    • wget 
      rpm -Uvh epel-release-6-8.noarch.rpm
  • For CentOS 7.x
    • wget 
      rpm -Uvh epel-release-7-11.noarch.rpm

Install PHP and the cURL and GD PHP extensions

yum install php php-devel php-gd php-common

Start Apache

/etc/init.d/httpd start

Install FFmpeg

  • Download a precompiled version of FFmpeg
    • If you want a precompiled version of FFmpeg + codecs for your CentOS server, then you can download a recent static build of FFmpeg here.
    • Use the x86_64 build for 64-bit servers and the x86 build for 32-bit servers.
    • Decompress the corresponding tar.xz distribution, and locate the 'ffmpeg' binary file.
    • To install this build, simply upload the 'ffmpeg' binary file to your "/usr/bin" directory and change permissions of the file to chmod 0755 or higher. And, presto, you have a fully-functioning CentOS build of FFmpeg + codecs, compatibile with my software, that you did not have to compile yourself!
  • OR, Compile FFmpeg from source
    • Get the dependencies

      yum install autoconf automake gcc-c++ libtool make nasm pkgconfig zlib-devel git
    • Make a directory in “/root/” to put all of the source code into:

      cd /root 
      mkdir ~/ffmpeg_sources
    • Build/Install FFmpeg and codecs as follows

      • Yasm

        cd ~/ffmpeg_sources 
        curl -O
        tar xzvf yasm-1.2.0.tar.gz
        cd yasm-1.2.0
        ./configure --prefix="$HOME/ffmpeg_build" --bindir="$HOME/bin"
        make install
        make distclean
        export "PATH=$PATH:$HOME/bin"
      • libmp3lame

        MP3 audio encoder.
        Requires FFmpeg to be configured with --enable-libmp3lame

        cd ~/ffmpeg_sources 
        curl -L -O
        tar xzvf lame-3.99.5.tar.gz
        cd lame-3.99.5
        ./configure --prefix="$HOME/ffmpeg_build" --bindir="$HOME/bin" --disable-shared --enable-nasm
        make install
        make distclean
      • FFmpeg

        cd ~/ffmpeg_sources 
        git clone --depth 1 git://
        cd ffmpeg
        export PKG_CONFIG_PATH
        ./configure --prefix="$HOME/ffmpeg_build" --extra-cflags="-I$HOME/ffmpeg_build/include" --extra-ldflags="-L$HOME/ffmpeg_build/lib" --bindir="$HOME/bin" --extra-libs=-ldl --enable-gpl --enable-nonfree --enable-libmp3lame
        make install
        make distclean
        hash -r
        . ~/.bash_profile
      • After all of this, FFmpeg will be compiled into "/root/bin/ffmpeg".

      • Move the FFmpeg binary file from “/root/bin/ffmpeg” to “/usr/bin/ffmpeg”. Then set permissions of “/usr/bin/ffmpeg” to chmod 0777.

        mv /root/bin/ffmpeg /usr/bin/ffmpeg
        chmod 0777 /usr/bin/ffmpeg

Software Installation

Get YouTube API Key

1. Navigate to the Google Developers Console and click "Create Project".

2. Enter a Project Name and click the "Create" button.

3. Click on the "YouTube Data API" link.

4. Click the "Enable" button.

5. Click the "Go to Credentials" button.

6. Select "Web server" from the "Where will you be calling the API from?" menu, select "Public data" for "What data will you be accessing?", and then click the "What credentials do I need?" button.

7. Copy and save your API key to a safe place, and then click the "Restrict key" link.

8. For "Key restriction", choose "None", and then click the Save button. (Note: It may take up to 5 minutes for the API key settings to take effect. So, please wait at least 5 minutes before running the software's "config check" utility, to ensure that the "YouTube API Keys" test passes!)

Using Multiple API Keys

You may use one or more YouTube API keys with this software. The use of multiple keys enables you to effectively extend the daily API quota/limit and is recommended for sites with moderate-to-heavy traffic. In fact, as a general precaution, we recommend that you have 1 key for every 1,000 daily website visitors.

A new, separate Google account should be created for each new API key that you use with this software. For each Google account, please follow the provided instructions for generating a YouTube API key.

Your API key(s) must be inserted into the $_youtubeApiKeys array in "lib/Config.php". If you supply multiple keys, then one key is randomly selected from this array per request.

Configure Settings

Unpack/Unzip the distribution file, open "lib/Config.php", and edit:

Required Settings

Set the FFmpeg path

// FFmpeg Server Path - usually "/usr/bin/ffmpeg" or "/usr/local/bin/ffmpeg"
const _FFMPEG_PATH = "/usr/bin/ffmpeg";

Set the cURL path

// cURL Server Path
const _CURL_PATH = "/usr/bin/curl";

Set your YouTube API Key or Keys

// YouTube API Keys (Get API Keys from and/or review '/docs/#youtubeAPI' and '/docs/#youtubeAPIMultiple').
// You may have one or more API keys. If you have multiple keys, then one is randomly selected from the array per request.
// The use of multiple keys enables you to effectively extend the daily API quota/limit and is recommended for sites with moderate-to-heavy traffic.
public static $_youtubeApiKeys = array(

Set the App Root directory

// The root directory and location of the application, relative to the web root.
const _APPROOT = '/'; // Directory names must be preceded and followed by a '/'. A value of '/' indicates the web root directory.

Advanced Settings

Website Name (appears in navbar)

// Website Name (appears in navbar)
const _WEBSITE_NAME = "MyConverterSite";

Website Domain (appears in footer and downloaded/converted file name branding)

// Website Domain (appears in footer and downloaded/converted file name branding)
const _WEBSITE_DOMAIN = "";

Default "Country Group", e.g., "Americas", "Europe", or Add Your Own (Required for Charts feature!)

// Default "Country Group"
// Value can be a continent name or any name that you choose to categorize a group of countries in the Config::$_countries array.
// The default available values are "Africa", "Asia", "Americas", "Europe", and "Oceania".
const _DEFAULT_COUNTRY_GROUP = "Americas";

Default Country (Must be within the Default "Country Group"!)

// Default Country
// Must be a valid, lowercase, ISO 3166-1 alpha-2 country code
// Scroll down to $_countries array to see default list of available countries.
const _DEFAULT_COUNTRY = "us";

Default Language (Must be included in "app/Languages/index.php"!)

// Default Website Language
const _DEFAULT_LANGUAGE = "en"; // You MUST choose from available languages in "app/Languages/index.php"

Social Network settings

const ENABLE_FACEBOOK_LIKE_BOX = true; // Enable or disable Facebook Like Box in Sidebar

Facebook Page URL Name (e.g.,

const FACEBOOK_PAGE_NAME = "facebook";  // E.g.,{Facebook page name}

Active Site Template ("default" and "xeon" templates available)

// Template Folder Name
const _TEMPLATE_NAME = "default"; // "default" and "xeon" templates available

Video Results per Page (number of initial results and results returned by "Load more videos" button)

// Number of additional video results returned when the "Load more videos" button is clicked
// Maximum number is 50 !!
const _RESULTS_PER_PAGE = 5;

Enable YouTube Direct download (download directly from YouTube servers)

// Enable YouTube Direct download (true = enabled, false = disabled)

Enable/Disable Website Interface (e.g., if you only need API interface)

// Access Control for website
// Also see Config::$_apiAllowedDomains, below, to regulate and whitelist API access
const _WEBSITE_ENABLED = true;  // Enable/Disable website interface

Enable/Disable JSON and/or Button/Iframe APIs

// List of domains and/or IP addresses, separated by commas, that are allowed access to the JSON and Button APIs.
// In general, for both APIs, add IP address for PHP consumption and domain for AJAX/HTML consumption.
// If a domain/IP needs access to both APIs, then it must be included in BOTH the 'json' AND 'button' subarrays!
// If the 'json' or 'button' subarray is empty, then this enables unrestricted, public access to the corresponding API.
// Do NOT prepend domains/IPs with 'http://' or 'https://'!!
// Do NOT prepend domains with 'www' or any other subdomain!!
public static $_apiAllowedDomains = array(
	'json' => array(
		// These are examples. Replace as needed.
	'button' => array(
		// These are examples. Replace as needed.

Now upload all files to your web server

Follow the prompts in the "config check" utility, to help resolve any remaining issues with the server or software configuration.

Don't forget to set "store" folder permissions to chmod 0777!


I opened index.php and see a blank page. What should I do?
  • Enable debug mode in "lib/Config.php", like so:
  • // Debug Mode shows errors
    const _DEBUG_MODE = true;
  • This will enable the output of PHP errors to the browser.
  • Also, check your Apache error log for PHP errors and warnings.
  • If you see a PHP error or warning that you don't understand, please copy and paste the error into Google and behold the plethora of other people who have experienced -- and overcome -- similar errors. Leverage Google to your advantage in this case, and benefit from the experiences of others who have had the same problem.
I opened index.php, but I see no YouTube video results in the page body. What should I do?
  • Ensure that you have generated a valid YouTube API key or keys and that you have configured the corresponding software setting correctly.
  • Ensure that "url rewriting" is enabled on your web server and that your rewrite rules correspond to your specific web server software (e.g., Apache or Nginx).
  • Finally, ensure that the PHP "allow_url_fopen" directive is set to "On" or "1".
  • On cPanel servers (or servers that support a custom php.ini file), you can create a new file and add the following content:
  • allow_url_fopen = On
  • ...then save this file as "php.ini" and upload it to your web root directory.
I opened index.php and see something like: "Parse error: syntax error, unexpected T_FUNCTION in /var/www/html/index.php on line...". What should I do?
  • This is generally an indication that you do not have at least PHP 5.3 installed. Anonymous functions usually cause this error, and they were not introduced until PHP 5.3. You need to install PHP 5.3+ to eliminate this error.
When I run the "config check" utility prior to software installation, I see the error "DNS is OK?: No". What is wrong with my DNS? What should I do?
  • An improperly configured DNS can cause HTTP requests (made from your server to your server's domain) to fail. To test this possibility, save the following code to a file, and then load the file in a web browser:
  • <?php
    // create a new cURL resource
    $ch = curl_init();
    // set URL and other appropriate options
    curl_setopt($ch, CURLOPT_URL, "");
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    // grab URL and pass it to the browser
    // print out any cURL errors as well as HTTP response information
    echo 'Curl error: (' . curl_errno($ch) . ') ' . curl_error($ch) . '<br>';
    // close cURL resource, and free up system resources
  • Now repeat the process, substituting "" with "" (or any other domain name other than your site's domain name!) this time.
  • If the above code consistently fails for any reason, in any way, when CURLOPT_URL is set to "", but consistently works when CURLOPT_URL is set to "" (or any other domain name other than your site's domain name!), then you likely have an issue with your DNS. Evidently, HTTP requests made from your server are able to correctly resolve the DNS of all sites except your own -- indicating an issue with your own DNS configuration. Possible fixes include using another DNS provider, changing nameservers, and/or having a professional configure your DNS for you.
When I click the MP3 and/or MP4 buttons for a given video, I get an error message and the download links don't appear. Why is this?
  • Verify that software.xml exists in the "store" directory, and that the file is chmod to 0777 permissions. Also, ensure that "store" directory permissions allow programmatic modification of software.xml. If software.xml exists, try deleting the file and allowing it to automatically regenerate.
  • Try executing a simple PHP cURL request to the corresponding video page URL, and return the contents of the page to the screen. For example, place the following code in a new file, replacing the "vidID" URL query string parameter value with a valid YouTube video ID:
  • <?php
    // create a new cURL resource
    $ch = curl_init();
    // set URL and other appropriate options
    curl_setopt($ch, CURLOPT_URL, "");
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    // grab URL and pass it to the browser
    // print out any cURL errors as well as HTTP response information
    echo 'Curl error: (' . curl_errno($ch) . ') ' . curl_error($ch) . '<br>';
    // close cURL resource, and free up system resources
  • (Note: You can retrieve the video page URL and corresponding ID for any given video by clicking the "Preview Video" button underneath the video thumbnail image!)
  • Save the file, upload it to your server, and open it in a browser. Do you see the HTML page located at that URL? If the video is blocked in your server's country, then this will be indicated in the screen's output. A blank page or CAPTCHA screen could indicate that your IP has either been temporarily banned or flagged (via the CAPTCHA) for exceeding video pull quota limits. It could also mean that your server is having networking issues.
When I click a MP3 or Video download link, 1) nothing happens, 2) the page reloads and nothing happens, 3) a bunch of strange characters are printed to the screen, or 4) I see an error message. What should I do?
  • First, check that the _FFMPEG_PATH and _CURL_PATH constant values in "lib/Config.php" point to the correct locations of the corresponding binary files on your server. On Linux, you can locate FFmpeg and cURL via the command line interface as follows, e.g.:
  • [email protected]:~# type ffmpeg
    ffmpeg is /usr/bin/ffmpeg
  • [email protected]:~# which ffmpeg
  • [email protected]:~# type curl
    curl is /usr/bin/curl
  • [email protected]:~# which curl
  • Does FFmpeg work from the command console? Try running a FFmpeg command directly in the command line interface. Preferably, run a command that is executed by my software during conversions.
  • Are you running the most recent version of FFmpeg? (Check your version of FFmpeg by typing "ffmpeg" in the command console. If the dates shown in the resulting output are more than 1-2 years old, then you may have an outdated version of FFmpeg.) Also, the software may not work as expected with FFmpeg builds downloaded from the apt-get repository on Debian and Ubuntu. Instead, for these Linux distributions, try downloading a recent, static build of FFmpeg. To install the static build, simply upload the downloaded FFmpeg binary file to your "/usr/bin" directory.
  • You may need to set permissions of the FFmpeg binary to chmod 0777, or lower -- if possible, so that my software has permission to access FFmpeg. This especially holds true for people using a static build of FFmpeg.
  • If Debug Mode is enabled in the software, then try disabling it in "lib/Config.php":
  • // Debug Mode shows errors
    const _DEBUG_MODE = false;
  • Debug Mode prints PHP errors to the screen, and, if you have any such errors during a file's download, then the error message output will conflict with the subsequent downloaded file headers.
  • If you are using CloudFlare SSL and you have created a "Page Rule" that forwards all http:// requests to https://, then you must disable or delete this Page Rule. Instead, you can enable automatic forwarding to https:// via the provided .htaccess file:
  •     #Uncomment the following lines as instructed to redirect all http:// requests to https://
        #If using Cloudflare SSL, uncomment this line
        	#RewriteCond %{HTTP:CF-Visitor} {"scheme":"http"}
        #If NOT using Cloudflare SSL, uncomment this line
        	#RewriteCond %{HTTPS} off
        #Always uncomment these lines
        	#RewriteCond %{REQUEST_URI} !(.mp3|.m4a|.mp4|.webm|.flv|.3gp)$
        	#RewriteCond %{QUERY_STRING} !(.mp3|.m4a|.mp4|.webm|.flv|.3gp)$
        	#RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
  • Also ensure that:
  • On cPanel servers (or servers that support a custom php.ini file), you can create a new file and add the following content:
  • output_buffering = On
    memory_limit = 128M
  • ...then save this file as "php.ini" and upload it to your web root directory.
How and where do I edit the default template and design?
  • This software employs many principles of the MVC paradigm, so all "presentation logic" is located in the "/app/Templates/default" and "/app/Views" directories.
  • In terms of customization, most of your efforts should focus on editing the "default" template in the "/app/Templates/default" directory. Here you will find common header and footer files as well as all CSS, JavaScript, images, and other related dependencies. You can create an entirely different look for the software by editing only the files in this directory and its subdirectories.
  • If you want to create your own, brand-new template, then you can copy the "/app/Templates/default" folder to a new folder named, e.g., "/app/Templates/mytemplate". Then you must change the following constant value in "/lib/Config.php" to (per the example):
  • // Template Folder Name
    const _TEMPLATE_NAME = "mytemplate";
  • Additional presentation-related code is located in the "/app/Views" directory and its subdirectories. But take care when editing code here because some of this code is vital for the display of crucial software functionality.
  • Subdirectories of "/app/Views" that are worth noting:
    1. "/app/Views/pages":
      • Files in this folder effectively embody new "pages" in the software. Pages can either be served synchronously or asynchronously (via AJAX), but they are all pages nonetheless. Each page file corresponds to a function (of the same name) in the "/app/Controllers/PagesController.php" file, and these functions perform "pre-presentation" logic before passing resulting PHP variable values to the pages.
      • For example, the faq() function in "/app/Controllers/PagesController.php":
      • function faq()
        	$this->SetVars(array('uppercase' => true));
        	return $this->render(dirname(__DIR__) . "/" . self::_VIEWS_PATH . "/" . self::_PAGES_DIR, __FUNCTION__, TEMPLATE_NAME);
      • ...creates an $uppercase PHP variable (with boolean value 'true') that can be used anywhere in "/app/Views/pages/faq.php". And "return $this->render()" is what renders and ultimately displays the "faq.php" page.
      • To add a new page to the software, you can add a similar, new function to "/app/Controllers/PagesController.php" and then create a corresponding page file (with the same name!) in "/app/Views/pages".
    2. "/app/Views/elements":
      • "Elements" are small chunks of (often reusable) markup (or presentation code) that can be inserted inside page files in "/app/Views/pages" and inside template header/footer files (e.g., in "/app/Templates/default").
      • For example, the default template consumes a "navbar_links" element in "/app/Templates/default/header.php" like so:
      • <?php echo $this->element('navbar_links'); ?>
      • This code automatically includes and renders the file "/app/Views/elements/navbar_links.php" inside "header.php".
      • To add a new element to the software, create a new file in "/app/Views/elements", insert your custom markup/code, and then render it inside a page or header/footer file via "echo $this->element('element_name')". (Ensure that 'element_name', per the preceding example, is the same name as the new, corresponding file in "/app/Views/elements"!)
Are downloaded/converted files saved on the server?
  • No! You need very little hard disk space because nothing is stored on the server. A mere 50 MB (minimum) of disk space is required.
I think YouTube is blocking or banning my IP address, and/or I am experiencing a CAPTCHA page when trying to connect to a YouTube video page. What can I do?
  • First of all, bans are usually temporary. In my experience, YouTube only blocks/bans your IP for a finite period of time. The amount of time will vary -- generally, anywhere from a few minutes to a few days.
  • If you are frequently getting blocked by YouTube, OR you are experiencing a CAPTCHA page, then you can rotate between multiple outgoing IPs for HTTP requests made to YouTube's servers. My software facilitates this process for you.
  • First, you need to purchase some additional IP (IPv4) addresses from your hosting provider. (Often your hosting provider will include additional IPs for free with your hosting plan!) Extra IP addresses generally only cost a couple of dollars apiece, and it's reasonable to "start" with 4-5 IPs for the purpose of IP rotation. You can always buy more IPs later and add them to the rotation as needed. That said, the more IPs you have, the better off you will be. In general, the number of additional IPs required for your site is directly proportional to the amount of traffic to your site.
  • (Note: Do NOT use "proxy" IPs purchased from a dedicated, 3rd-party proxy provider! The intent of IP rotation is not to hide or obscure your server's identity, but merely to change the outgoing IP address seen by YouTube. Also, dedicated proxy IPs are much slower than IPs used as outgoing network interfaces, so you will see a marked decrease in speed and performance if you use proxies.)
  • Next, you need to configure these additional IP addresses so that they can be used as "outgoing network interfaces". Simply put, your server needs to be configured so that it can "bind" to these extra IPs for HTTP requests. The easiest way to accomplish this is to have your hosting provider do this for you. If you must do this yourself, then you can refer to OVH's guide for setting up "Network IP Aliasing" for a number of different Linux distributions (and Windows):
  • Once your additional IPs are set up, then you can configure the corresponding constant values in "lib/Config.php" in preparation for IP rotation. This file is well-documented, and all constants related to IP rotation and the database are throroughly explained in the associated comment sections.
  • Finally, you must use the SQL provided in "docs/ips.sql" to create the required database table that will hold your IPs. Ensure that you replace the IPs in the SQL INSERT command with your own IP addresses "before" executing the SQL! Additional IP addresses can be added to the INSERT command by copying the format and adding lines to the command. In the future, whenever you want to add another IP address to the rotation, then you simply add the new IP or IPs to this database table.
  • If you find that, with IP rotation enabled, you are still experiencing IP bans and/or CAPTCHAs, then that is generally a sign that you need to add more IP addresses to the rotation (to the corresponding database table). You must keep adding IPs until YouTube downloads/conversions start working normally.
  • If you suspect that there is a problem with the IPs themselves, or the IP configuration on your server, then you should first test each additional IP using the following, simple PHP cURL code:
  • <?php
    	// create a new cURL resource
    	$ch = curl_init();
    	// set URL and other appropriate options
    	curl_setopt($ch, CURLOPT_URL, "");
    	curl_setopt($ch, CURLOPT_HEADER, 0);
    	curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    	curl_setopt($ch, CURLOPT_REFERER, '');
    	curl_setopt($ch, CURLOPT_INTERFACE, '');  // Your extra IP goes here!
    	curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    	curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
    	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    	// grab URL and pass it to the browser
    	// print out any cURL errors as well as HTTP response information
    	echo 'Curl error: (' . curl_errno($ch) . ') ' . curl_error($ch) . '<br>';
    	// close cURL resource, and free up system resources
  • Ensure that you change the CURLOPT_INTERFACE value to your IP address. Then save the code to a .php file and run it on your server. If you see a video but it won't play, you don't see a video, or you get a cURL error and/or curious HTTP response, then there is something wrong with the IP or its configuration as an outgoing network interface on your server.
  • To address this issue, on some servers, you can try commenting out this line of code, like so:
  • //curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);  
  • If all else fails, you can try completely disabling IPv6 on your server. Please consult with your hosting company or server admin to do this.
I think a video or group of videos is blocked in my server's country. What can I do?
  • All countries have some blocked videos. All of them. The only way that you could "unblock" all of these videos is to leverage a global proxy network like Tor. In fact, Tor is the only global proxy network that I am aware of at this time, and it is notoriously known for its slow connection speeds.
  • A more practical approach is to unblock as many videos as you can without spending a lot of extra money, making a lot of extra work for youself, and generally inducing massive, debilitating headaches.
  • The easiest way to avoid blocked videos is to choose a web server in a country that, generally, has few blocked videos. In my experience, the USA, Canada, and France have the least number of blocked videos. You would do yourself a favor to choose a datacenter located in one of these countries.
  • Another way to thwart blocked videos is to use dedicated proxy IPs in your HTTP and download requests. In this case, you can buy one or more proxy IPs from a dedicated, 3rd-party proxy service like InstantProxies. Again, perferably, the proxies should be located in the USA, Canada, or France. Integrate proxy IPs into your PHP cURL requests like so, i.e.:
  • curl_setopt($ch, CURLOPT_PROXY, '');
    curl_setopt($ch, CURLOPT_USERAGENT, '');
    curl_setopt($ch, CURLOPT_REFERER, '');
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
  • When using proxies, you should test for a blocked video first by scraping the content of the video (or video info) page and checking for text that indicates the video is blocked. If the test indicates that a given video is in fact blocked, then you should use a proxy IP. If not, then don't use a proxy IP. The goal is to only use proxy IPs when you need to because, like Tor, using proxies will always be slower than not using proxies.
  • When choosing proxies, ideally you'll want to do the following:
    1. Choose proxies that are geographically very near to your web server. Ideally, the proxy server would be sitting right next to the web server in the same data center.
    2. You are the only person using the proxy server, and you are not using it for anything more than proxy requests.
    3. Your proxy server is not a virtual server running on a physical server that is hosting other virtual proxy instances (that you don't operate).
    4. Spread out your requests to multiple, numerous proxies instead of only having a couple of proxies, for example.
    5. The proxy server(s) should be running with modest CPU load averages and comparable network bandwidth and connection speeds (to your web server).
  • Do NOT use free proxy IPs. You are sharing those proxies with the rest of the world, and they get banned quickly by popular sites (like YouTube).
  • I have not yet implemented proxy integration with my software. That said, it is on my "To-Do" list, among other things!
How can I convert the URL rewriting rules in the included .htaccess file to Nginx rewriting rules?
  • Place the following rewrite rules and code in the respective Nginx vhost file (in "/etc/nginx/sites-available"):
  • if ($http_cf_visitor ~ '{"scheme":"https"}'){
    	set $rule_0 1$rule_0;
    if ($uri ~ "(.mp3|.m4a|.mp4|.webm|.flv|.3gp)$"){
    	set $rule_0 2$rule_0;
    if ($rule_0 = "21"){
    	rewrite /(.*) http://$http_host$uri permanent;
    if (!-d $request_filename){
    	set $rule_1 1$rule_1;
    if (!-f $request_filename){
    	set $rule_1 2$rule_1;
    if ($rule_1 = "21"){
    	rewrite ^/(robots.txt)$ /store/$1 last;
    if (!-d $request_filename){
    	set $rule_2 1$rule_2;
    if (!-f $request_filename){
    	set $rule_2 2$rule_2;
    if ($rule_2 = "21"){
    	rewrite /(test-url-rewriting)$ /inc/version.php last;
    if (!-d $request_filename){
    	set $rule_3 1$rule_3;
    if (!-f $request_filename){
    	set $rule_3 2$rule_3;
    if ($rule_3 = "21"){
    	rewrite ^/(.*)$ /index.php?req=$1&$args last;
How do I add/edit language translations?
  • There are 2 primary components of the software's language translation engine:
    1. "app/Languages/index.php":
      • This file lists all available languages in a PHP array. Each array key is the corresponding ISO 639-1 language code, and each array value is another array containing additional information about the language.
    2. "app/Languages/{language code}.php":
      • These files are named using the corresponding ISO 639-1 language code (e.g., "en.php" or "de.php"). Each file contains a PHP array of translations for a given language. Array keys are used to display translations in other parts of the software (e.g., $translations['website_title'] will return the 'website_title' translation).
  • To add a new language: Add the language to "app/Languages/index.php" (via a new array element), open "app/Languages/en.php" and replace all translations with the new language's translations, and then save the file as {language code}.php. For example, to add the French language:
    • "app/Languages/index.php"
    • return array(
          'en' => array(
              'language' => 'English(US)',
              'country_code' => 'us',
              'lang_code' => 'en',
              'country_name' => 'United States',
              'direction' => 'ltr'
          'de' => array(
              'language' => 'Deutsch',
              'country_code' => 'de',
              'lang_code' => 'de',
              'country_name' => 'Deutschland',
              'direction' => 'ltr'
          'fr' => array(
              'language' => 'Français',
              'country_code' => 'fr',
              'lang_code' => 'fr',
              'country_name' => 'France',
              'direction' => 'ltr'
    • "app/Languages/fr.php"
    • return array(
          // Meta Data - (app/Views/helpers)
          'website_title' => 'french translation',
          'website_description' => 'french translation',
          'website_keywords' => 'french translation',
          'search_description' => 'french translation',
          // Navbar - (app/Views/elements)
          'navbar_home' => 'french translation',
          'navbar_faq' => 'french translation',
          'navbar_contact' => 'french translation',
          // More Translations, etc., here
  • To edit a language: Open "app/Languages/{language code}.php" and add and/or modify translations as needed.
  • To remove a language: Open "app/Languages/index.php" and remove the array element that corresponds to a given language.
  • (Note: Languages that read right-to-left are not yet supported.)
How do I enable the JSON REST API and/or the Button/Iframe API?
  • The software comes with 2 ready-to-consume APIs: A JSON RESTful API and a Button/Iframe API.
  • The APIs are effectively disabled by default (and only accessible to 'localhost'). To enable either API, you must edit the $_apiAllowedDomains array in 'lib/Config.php' per the instructions provided in the corresponding code comments.
  • You can whitelist (restrict) access to either API by adding specific domains and/or IPs to the $_apiAllowedDomains 'json' or 'button' subarray. If either subarray is left empty, then this enables unrestricted, public access to the corresponding API. When an API is made public in this way, an 'API' menu link and page is automatically added to your site. This page provides your website users with detailed instructions for consuming all available public APIs.
  • For further information related to the consumption of each API, please review a preview of the 'API' page here.


Software Support

Stuff you might like to know about software support:

  1. 100% Free support for life!
    • Ask me a question, and I'll answer it!
    • Working directly on your server is not free.
  2. Regular updates/fixes to the software are Free!
  3. See The FAQ for ways to troubleshoot common issues.
  4. Human support for this script is provided via:


Regular License

The Regular License permits the installation of this software on one website.

If you require greater freedom or flexibility, then please purchase an Extended License.

Extended License

If you plan to load this software on multiple websites and/or repackage all or some of the software code in your own application that is redistributed and/or sold for profit, then you MUST buy an extended license.

An extended license costs $449.50 (the cost of 10 individual licenses). There are no exceptions to this rule, and violators will be prosecuted. Please contact me at [email protected] to arrange the purchase of an extended license.


Software Changelog

Version 1.33 (02.26.2018)

  • Omitted "Content-Length" HTTP header for MP3 downloads IF the user agent is Firefox (desktop version), resolving intermittent MP3 download failures in Firefox. (Other browsers/platforms are not affected.)

Version 1.32 (02.11.2018)

  • Switched to "non-DASH" video formats for MP3 conversion to avoid slow conversions caused by YouTube-imposed throttling of "DASH" audio downloads
  • Modified all download URLs to use the "" subdomain, to generally improve download availability and performance
  • Implemented various, minor fixes and refactoring of code

Version 1.31 (05.05.2017)

  • Fixed bug preventing audio playback in Integrated Music Player

Version 1.3 (04.25.2017)

  • Added JSON REST API and Button/Iframe API, API instructions page, and corresponding documentation
  • Added ability to download all but MP3 formats directly from YouTube, completely bypassing server
  • Added ability to download/convert age-restricted YouTube videos
  • Added search suggestions and auto-complete to front page search form
  • Added "layouts" folder to templates, enabling multiple header/footer files for the same template
  • Added ability to disable regular website interface (e.g., if only API is needed)
  • YouTube API requests are retried upon failure, using a new API key when multiple API keys are present
  • Fixed bug that prevented MP3 downloads when Cloudflare SSL is active
  • Implemented various, minor fixes and refactoring of code

Version 1.2 (02.03.2017)

  • Added dynamic Meta and Open Graph tags for video searches
  • Added dynamic "share images" for video searches
  • Automated generation of robots.txt file
  • Automated generation of XML sitemap index file and associated XML sitemaps
  • Added hreflang values to static pages and sitemap URLs
  • Added multi-language support and translation engine
  • Automated language and country detection for translations and "Top Music Videos", respectively
  • Moved the majority of URL rewriting rules from .htaccess to "app/Core/Router.php"
  • Enabled search URLs with the following formats:
    •{Keyword or Keywords}
    •{Video Id}
    •{Video Id}
    •{YouTube Video URL}
  • Added search URL link to each video title in search results
  • Facilitated search bot crawling of code if JavaScript is "not" enabled
  • Implemented various, minor fixes and refactoring of code

Version 1.11 (01.20.2017)

  • Fixed the mechanism used to detect encrypted YouTube videos

Version 1.1 (09.30.2016)

  • Added support for multiple YouTube API keys, to extend API usage quota limits
  • Added "xeon" template to collection of available template designs
  • Video preview button now opens the corresponding video in a FancyBox modal window instead of a new tab
  • Added protection against content scraping of AJAX URLs
  • Added support for more countries in the Top Videos lists
  • Fixed downloaded/converted file incompatibility issue with third-party video/audio editors
  • Fixed bug that prevented the passing of arguments to "element" files
  • Added ability to pass template-specific variable values to generic "page" and "element" files
  • Added "url rewriting" test and support for testing multiple YouTube API keys in "config check" utility
  • Updated the Server Configuration, Software Installation, FAQ, and Changelog sections of these docs

Version 1.01 (07.16.2016)

  • Fixed Error 404 page styles, in some cases
  • Provided option to forward all http:// requests to https:// via .htaccess
  • Fixed bug affecting the video duration format displayed on thumbnail images
  • Updated the Server Configuration, FAQ, and Changelog sections of these docs
  • Fixed url encoding issue that prevented download of some videos
  • Fixed url encoding issue that adversely affected searching with certain keywords