PHP Regex to get youtube video ID?

Solution 1:

Use parse_url() and parse_str().

(You can use regexes for just about anything, but they are very easy to make an error in, so if there are PHP functions specifically for what you are trying to accomplish, use those.)

parse_url takes a string and cuts it up into an array that has a bunch of info. You can work with this array, or you can specify the one item you want as a second argument. In this case we're interested in the query, which is PHP_URL_QUERY.

Now we have the query, which is v=C4kxS1ksqtw&feature=relate, but we only want the part after v=. For this we turn to parse_str which basically works like GET on a string. It takes a string and creates the variables specified in the string. In this case $v and $feature is created. We're only interested in $v.

To be safe, you don't want to just store all the variables from the parse_url in your namespace (see mellowsoon's comment). Instead store the variables as elements of an array, so that you have control over what variables you are storing, and you cannot accidentally overwrite an existing variable.

Putting everything together, we have:

<?php
$url = "http://www.youtube.com/watch?v=C4kxS1ksqtw&feature=relate";
parse_str( parse_url( $url, PHP_URL_QUERY ), $my_array_of_vars );
echo $my_array_of_vars['v'];    
  // Output: C4kxS1ksqtw
?> 

Working example


Edit:

hehe - thanks Charles. That made me laugh, I've never seen the Zawinski quote before:

Some people, when confronted with a problem, think ‘I know, I’ll use regular expressions.’ Now they have two problems.Jamie Zawinski

Solution 2:

preg_match("#(?<=v=)[a-zA-Z0-9-]+(?=&)|(?<=v\/)[^&\n]+|(?<=v=)[^&\n]+|(?<=youtu.be/)[^&\n]+#", $url, $matches);

This will account for

youtube.com/v/{vidid}
youtube.com/vi/{vidid}
youtube.com/?v={vidid}
youtube.com/?vi={vidid}
youtube.com/watch?v={vidid}
youtube.com/watch?vi={vidid}
youtu.be/{vidid}

I improved it slightly to support: http://www.youtube.com/v/5xADESocujo?feature=autoshare&version=3&autohide=1&autoplay=1

The line I use now is:

preg_match("#(?<=v=)[a-zA-Z0-9-]+(?=&)|(?<=v\/)[^&\n]+(?=\?)|(?<=v=)[^&\n]+|(?<=youtu.be/)[^&\n]+#", $link, $matches);

Solution 3:

Based on bokor's comment on Anthony's answer:

preg_match("/^(?:http(?:s)?:\/\/)?(?:www\.)?(?:m\.)?(?:youtu\.be\/|youtube\.com\/(?:(?:watch)?\?(?:.*&)?v(?:i)?=|(?:embed|v|vi|user|shorts)\/))([^\?&\"'>]+)/", $url, $matches);

$matches[1] contains the vidid

Matches:

  • youtube.com/v/vidid
  • youtube.com/vi/vidid
  • youtube.com/?v=vidid
  • youtube.com/?vi=vidid
  • youtube.com/watch?v=vidid
  • youtube.com/watch?vi=vidid
  • youtu.be/vidid
  • youtube.com/embed/vidid
  • http://youtube.com/v/vidid
  • http://www.youtube.com/v/vidid
  • https://www.youtube.com/v/vidid
  • youtube.com/watch?v=vidid&wtv=wtv
  • http://www.youtube.com/watch?dev=inprogress&v=vidid&feature=related
  • https://m.youtube.com/watch?v=vidid
  • youtube.com/shorts/vidid

Does not match:

  • www.facebook.com?wtv=youtube.com/v/vidid

Solution 4:

This can be very easily accomplished using parse_str and parse_url and is more reliable in my opinion.

My function supports the following urls:

  • http://youtube.com/v/dQw4w9WgXcQ?feature=youtube_gdata_player
  • http://youtube.com/vi/dQw4w9WgXcQ?feature=youtube_gdata_player
  • http://youtube.com/?v=dQw4w9WgXcQ&feature=youtube_gdata_player
  • http://www.youtube.com/watch?v=dQw4w9WgXcQ&feature=youtube_gdata_player
  • http://youtube.com/?vi=dQw4w9WgXcQ&feature=youtube_gdata_player
  • http://youtube.com/watch?v=dQw4w9WgXcQ&feature=youtube_gdata_player
  • http://youtube.com/watch?vi=dQw4w9WgXcQ&feature=youtube_gdata_player
  • http://youtu.be/dQw4w9WgXcQ?feature=youtube_gdata_player

Also includes the test below the function.

/**
 * Get Youtube video ID from URL
 *
 * @param string $url
 * @return mixed Youtube video ID or FALSE if not found
 */
function getYoutubeIdFromUrl($url) {
    $parts = parse_url($url);
    if(isset($parts['query'])){
        parse_str($parts['query'], $qs);
        if(isset($qs['v'])){
            return $qs['v'];
        }else if(isset($qs['vi'])){
            return $qs['vi'];
        }
    }
    if(isset($parts['path'])){
        $path = explode('/', trim($parts['path'], '/'));
        return $path[count($path)-1];
    }
    return false;
}
// Test
$urls = array(
    'http://youtube.com/v/dQw4w9WgXcQ?feature=youtube_gdata_player',
    'http://youtube.com/vi/dQw4w9WgXcQ?feature=youtube_gdata_player',
    'http://youtube.com/?v=dQw4w9WgXcQ&feature=youtube_gdata_player',
    'http://www.youtube.com/watch?v=dQw4w9WgXcQ&feature=youtube_gdata_player',
    'http://youtube.com/?vi=dQw4w9WgXcQ&feature=youtube_gdata_player',
    'http://youtube.com/watch?v=dQw4w9WgXcQ&feature=youtube_gdata_player',
    'http://youtube.com/watch?vi=dQw4w9WgXcQ&feature=youtube_gdata_player',
    'http://youtu.be/dQw4w9WgXcQ?feature=youtube_gdata_player'
);
foreach($urls as $url){
    echo $url . ' : ' . getYoutubeIdFromUrl($url) . "\n";
}