47

I want to validate youtube video ids sbumitted in the URL to one of my sites before accessing the Youtube API, but I don't know what the allowed characters are in such an id. I see people on the net guessing it can contain numbers and characters, but I haven't yet seen an official specification of these video ids.

Is there one?

Tom
  • 7,515
  • 7
  • 38
  • 54
  • I can call some function like `yTPlayer.duration { duration, error -> if duration > 0 { this is valid id! } }`. – 蘇哲聖 Jan 23 '21 at 06:06

10 Answers10

61

See this thread for official info.

you can hit this: http://gdata.youtube.com/feeds/api/videos/VIDEO_ID (Page now returns: "No longer available".)

and determine if the video is valid based on response

There's no way you can check the validity of the ID with RegEx, since not all alpha-numeric values are valid ID's.

p.s. i'm pretty sure i saw "dashes" in video ID's

p.p.s. "underscore" is a valid character also: http://www.youtube.com/watch?v=nrGk0AuFd_9

[a-zA-Z0-9_-]{11} is the regex (source), but there's no guarantee that the video will be there even if regex is valid

Brock Adams
  • 90,639
  • 22
  • 233
  • 295
roman m
  • 26,012
  • 31
  • 101
  • 133
  • If you wan to check if url is live, here an example in ruby: http://www.igvita.com/2006/09/07/validating-url-in-ruby-on-rails/ – borisrorsvort Jan 06 '12 at 10:16
  • 3
    This no longer appears to work. http://gdata.youtube.com/feeds/api/videos/NOT_A_VIDEO_ID returns 200 OK. – nornagon Jun 02 '15 at 22:59
  • See my answer further down which covers a solution for V3 of the API – richwol Aug 17 '15 at 13:40
  • 7
    The url included in this answer is no longer valid. See further options on this page or at this similar question... http://stackoverflow.com/questions/29166402/verify-if-video-exist-with-youtube-api-v3/31100389 – Harry B Sep 07 '15 at 08:06
17

With v3 of the YouTube API I achieved this by calling:

GET https://www.googleapis.com/youtube/v3/videos?part=id&id=Tr5WcGSDqDg&key={YOUR_API_KEY}

This returns something like:

{
  "kind": "youtube#videoListResponse",
  "etag": "\"dc9DtKVuP_z_ZIF9BZmHcN8kvWQ/P2cGwKgbH6EYZAGxiKCZSH8R1KY\"",
  "pageInfo": {
    "totalResults": 1,
    "resultsPerPage": 1
  },
  "items": [{
    "kind": "youtube#video",
    "etag": "\"dc9DtKVuP_z_ZIF9BZmHcN8kvWQ/Rgd0_ApwigPcJHVX1Z2SIQ5FJtU\"",
    "id": "Tr5WcGSDqDg"
  }]
}

So you can just do a check:

if(json.hasOwnProperty('pageInfo') && json.pageInfo.totalResults === 1) {
   if(items[0].kind==='youtube#video') {
      //valid video ID
   }
}
Federico Grandi
  • 6,785
  • 5
  • 30
  • 50
richwol
  • 1,065
  • 2
  • 11
  • 24
  • 3
    This is now necessary as v2 of the api is no longer working. I've been looking everywhere for this, thankyou. – Adam Aug 08 '15 at 01:09
12

If you are looking for a quicker and more scalable solution I would say to use REGEX with some logging/fallback for errors to be pro-active if YouTube changes their ID in the future.

I've been working with the YouTube API for a while now, dealing with millions of videos. Looping through them, I found this to be the most ideal:

/^[A-Za-z0-9_-]{11}$/

A more detailed example say in PHP:

public static function validId($id) {
    return preg_match('/^[a-zA-Z0-9_-]{11}$/', $id) > 0;
}
Michael
  • 8,362
  • 6
  • 61
  • 88
acidjazz
  • 1,244
  • 12
  • 14
6

I solved this issue in the same way Roman recommended. In my helper:

Be sure to include your requires at the top of the file:

require "net/http"
require "uri"

Then:

def validate_id(youtube_id)
  uri = URI.parse("http://gdata.youtube.com/feeds/api/videos/#{ youtube_id }")
  http = Net::HTTP.new(uri.host, uri.port)
  request = Net::HTTP::Get.new(uri.request_uri)
  response = http.request(request)
  %Q{ #{response.code} }
end

Be sure there is no white space between the brackets in "#{response.code}"

Lastly, compare it to the desired response:

def youtube_data(youtube_id) 
  if validate_id(youtube_id) == "200"
    #video is good code
  else %Q{ Video is no longer valid }
  end
end
Sorry-Im-a-N00b
  • 1,151
  • 2
  • 12
  • 20
6

Here is a simple implementation in JavaScript:

async function validVideoId(id) {
  const url = "http://img.youtube.com/vi/" + id + "/mqdefault.jpg";
  const { status } = await fetch(url);
  if (status === 404) return false;
  return true;
}

console.log(validVideoId('60ItHLz5WEA'));
  • +1 This [url] trick was perfect for my needs (check videoId is live/available)! (though OP sounds like they just wanted basic input validation to then call the Youtube API?) – Adam Smooch Jun 08 '21 at 19:35
1

I just look to see if it is alphanumeric with possible dash or not. You might want to look into oEmbed, you can query YouTube to see if the ID is a valid video or not.

NeuroScr
  • 322
  • 1
  • 7
0

Here is a simple implementation of Roman's approach in PHP:

function validYoutube($id){
    $id = trim($id);
    if (strlen($id) === 11){
        $file = @file_get_contents('http://gdata.youtube.com/feeds/api/videos/'.$id);
        return !!$file;
    }
    return false;
}

And here are the tests:

echo validYoutube('Nv7U6_WhqvQ');
echo validYoutube('Nv7U6_Whqvf');
echo validYoutube('Nv7U6_Whqzz');
Salvador Dali
  • 214,103
  • 147
  • 703
  • 753
0

I think this works for checking if the video exists or not. Other validation can be done using REGEX as mentioned above. (Implemented using PHP)

public function verifyVideoID($videoID) {
    parse_str(file_get_contents("http://youtube.com/get_video_info?el=detailpage&video_id=".$videoID), $info);
    if (isset($info['errorcode'])) {
        $response = ['response' => false];
        return response()->json($response);
    } else {
        $response = ['response' => true];
        return response()->json($response);
    }
}
0

Here's one I came up with from combining info from other answers here and elsewhere:

function validId($id) {
    return preg_match('/^[a-zA-Z0-9_-]{11}$/', $id) > 0;
}

function isvalYtube($url) {
    $purl = str_ireplace('www.', '', parse_url($url, PHP_URL_HOST));    
    if (!strpos($url, 'youtu.be/') && ($purl != 'youtu.be')) {
        if (strpos($url, 'watch') && ($purl = 'youtube.com')) {
                parse_str(parse_url($url, PHP_URL_QUERY), $id);             
                if (!empty($id['v'])) { return(validId($id['v']) ? true : false); } else { return false; }                 
        }     
    } else {        
        if (!empty(basename($url))) { return(validId(basename($url)) ? true : false); } else { return false; }    
    }  
}

echo isvalYtube($url) ? 'valid link' : 'invalid link';

First function checks if we're dealing with a valid Youtube video ID.

Second function simply checks if it's a valid youtube VIDEO LINK or VIDEO from PLAYLIST LINK, excluding channel links.

Note: It doesn't determine if it's an active video nor does it check if it exists or not. These functions act merely as Youtube video-link syntax checkers and should be treated as such.

Usage examples:

$url = 'http://www.youtube.com/watch?v=o_QBk4VwnIA';
echo isvalYtube($url) ? 'valid link' : 'invalid link';
//returns 'valid link'

$url = 'http://youtu.be/o_QBk4VwnIA';
echo isvalYtube($url) ? 'valid link' : 'invalid link';
//returns 'valid link'

$url = 'http://www.youtube.com/watch?v=o_QBk4VwnIA&feature=youtu.be';
echo isvalYtube($url) ? 'valid link' : 'invalid link';
//returns 'valid link'

$url = 'https://www.youtube.com/watch?v=Sq3eLdixvCc&list=OLAK5uy_nvaYLo9AG_rZyqkXzYlkJfLjBuZS84bIU';
echo isvalYtube($url) ? 'valid link' : 'invalid link';
//returns 'valid link'

$url = 'https://www.youtube.com/channel/UCMPQY9gW0hQ9e_-IdQUKEAw';
echo isvalYtube($url) ? 'valid link' : 'invalid link';
//returns 'invalid link'
Ivan
  • 1,274
  • 16
  • 22
-2

Simple use this code:

 public class HelloWorld{

   public static void main(String []args){

     String expression = "^.*((youtu.be"+ "\\/)" + "|(v\\/)|(\\/u\\/w\\/)|(embed\\/)|(watch\\?))\\??v?=?([^#\\&\\?]*).*"; // var regExp = /^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#\&\?]*).*/;

     String video_url = "https://www.youtube.com/watch?v=as3tGTN2u98";

     if (video_url.matches(expression)) {
      System.out.println("It's valid");
     }


 }

}