Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

android youtube download url 403 forbidden

there are some videos that can't download.

I got download url by using this

http://www.youtube.com/get_video_info?video_id=itGNQbJwRSk

Is there anyone why below url is not available to download?

total url:

http://r1---sn-a5m7lnek.googlevideo.com/videoplayback?expire=1391267516&ms=au&source=youtube&sver=3&upn=OzZzFV_-2o4&id=8ad18d41b2704529&itag=22&mt=1391243224&ipbits=0&ratebypass=yes&fexp=935622%2C914924%2C926515%2C916623%2C936910%2C936913&sparams=gcr%2Cid%2Cip%2Cipbits%2Citag%2Cratebypass%2Csource%2Cupn%2Cexpire&mv=m&ip=183.101.166.55&key=yt5&gcr=kr&signature=F303D0C863C27A6A46124A09E40F308BB67181E013.3FA3E17460DDF6ECA004D9E48B1356849534EBFFFF

separated url with each params:

http://r1---sn-a5m7lnek.googlevideo.com/videoplayback?

expire=1391267516&

ms=au&

source=youtube&

sver=3&

upn=OzZzFV_-2o4&

id=8ad18d41b2704529&

itag=22&

mt=1391243224&

ipbits=0&

ratebypass=yes&

fexp=935622%2C914924%2C926515%2C916623%2C936910%2C936913&

sparams=gcr%2Cid%2Cip%2Cipbits%2Citag%2Cratebypass%2Csource%2Cupn%2Cexpire&

mv=m&

ip=183.101.166.55&

key=yt5&

gcr=kr&

signature=F303D0C863C27A6A46124A09E40F308BB67181E013.3FA3E17460DDF6ECA004D9E48B1356849534EBFFFF

and I used below codes in open stream

    u = new URL(url);
    HttpURLConnection huc = (HttpURLConnection)u.openConnection();//to know the size of video
    huc.setRequestProperty("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.102 Safari/537.36");
    huc.setRequestProperty("Accept","*/*");
    huc.setRequestMethod("GET");
    huc.setDoOutput(false);
    int size = huc.getContentLength();      
    int status = huc.getResponseCode();
    Log.e("download", status+ huc.getResponseMessage());
    is = new BufferedInputStream(huc.getInputStream());

but it returns status = 403, size = -1. I couldn't find anything to help yet.

Is there anyone have a idea?

like image 231
yountae.kang Avatar asked Feb 01 '14 09:02

yountae.kang


1 Answers

In short: https://github.com/lure/YoutubeGrabber

Long story: Every youtube video page contains a js block which initialise html5 player. Of course, there is aa flash player, too, but JS one is more easily to understand.

Streams located in two params: url_encoded_fmt_stream_map for video+audio combined and adaptive_fmts for video or audio separate streams. Each link is made up from two let's call it parts:

  1. everything what is going before url=https: and
  2. everything from this point till the , (comma) which separates streams.

What you should know about initialising block is: some params may appear twice and you have to keep only one copy in your request. You can't predict which params may be dropped out so try to include everything you've found in a "raw" link. Special part of all of this is a signature that is required by backends. Beware, that signature may appear in a first or second part of link.

There is 3 types of signatures in a current time:

  • signature - this one is plain and need no decipher, requires no handling.
  • sig - ciphered
  • s - ciphered

Having this blocks, player should prepare each link and request backend for stream chosen. It's done by concatenating all existing params excluding duplicates and append prepared signature.

While you can carefully find all possible player version this likely is not the best solution. It seems better to download player from your application and extract the exact decoding function from it. This approach will work with ANY youtube video page.

Despite of your decision, you still need the function. Most of the time this function may be found with this RegEx

set\("signature",\s*(?:([^(]*).*)\);

Use any formatting tool to read it source. You'll find that the main function uses one addition so you should extract it too. After that it's quite easy to implement the function in java or (which I prefer better) to extract decipher function and keep it around.

Steps in short: 1. extract url_encoded_fmt_stream_map and adaptive_fmts 2. split by , 3. find decipher function in player and reimplement it in language of your choice or extract and eval.

for example, here is a function extracted from http://s.ytimg.com/yts/jsbin/html5player-new-en_US-vflhlPTtB/html5player-new.js

var fs = {
    Q2: function (a, b) {
        a.splice(0, b)
    }, cK: function (a) {
        a.reverse()
    }, yy: function (a, b) {
        var c = a[0];
        a[0] = a[b % a.length];
        a[b] = c
    }
};
function gs(a) {
    a = a.split("");
    fs.yy(a, 40);
    fs.Q2(a, 3);
    fs.yy(a, 53);
    fs.yy(a, 11);
    fs.Q2(a, 3);
    fs.cK(a, 8);
    fs.Q2(a, 3);
    fs.yy(a, 16);
    fs.cK(a, 75);
    return a.join("")
};
like image 156
Observer Avatar answered Oct 03 '22 00:10

Observer