Funergy
By:
Funergy

Google get video fmt stream map

December 16, 2016 17k views
API PHP CentOS

TL:DR How would I go about to replicate a script like this http://api.getlinkdrive.com/ for Google Drive videos.

Google video playback request links are bound by ip and token.
I can get those links by using drive.google.com/getvideoinfo?docid=FILEID
But needs to be executed on the clients browser
if you get the fmt stream map from the Digital Ocean droplet you get links personalised to the droplets ip.

If you get it from the clients ip you get a link for the users ip, which is what I want as result.

But unfortunately CrossDomain ajax requests won't work for that.

Some API I have seen does what I want to make:
http://api.getlinkdrive.com/

You enter a shared link and get the redirector.googlevideo.com/playback? link for each resolution.

I have seen from the link that they registered themselves as an Google drive app.
Would that have anything to do with it?

Can I use the Google drive SDK for it?
I have looked into the google drive SDK but a GET request to the api on FULL doesnt return any video related data except length and resolution.

-Thanks for helping

1 comment
  • None of the currently mentioned solutions still work; even the projects at:

    https://github.com/quocnguyen/dt-api
    https://github.com/quocnguyen/dt-worker

    Fail with 403 error because of Google's new security measure of checking for the DRIVE_STREAM cookie when you hit the generated redirector video links.

    However, despite none of the mentioned solutions working -- there is still at least one exploit to get a special brand of redirector links that do not enforce DRIVE_STREAM cookie checking. The proof is sites like kissanime, 9anime, etc still are able to operate by using these special redirector links.

15 Answers

@tony1020
@Jenmy

<?php
/**
 * Created by PhpStorm.
 * User: Funergy
 * Date: 12/11/2016
 * Time: 6:10 PM
 */
$_SERVER['REMOTE_ADDR'] = isset($_SERVER['HTTP_CF_CONNECTING_IP']) ? $_SERVER['HTTP_CF_CONNECTING_IP'] : $_SERVER['REMOTE_ADDR'];

/**
 * Google Drive library
 *
 * @author Marxvn
 * @copyright (c) 2016, Marxvn
 * @license https://spdx.org/licenses/BSD-3-Clause.html BSD-3-Clause
 */

/**
 * Changes made to src
 *
 * - Line 59 Vidcode to numbers only
 *
 * - Line 155 Force ipv4 to fopen
 *
 * - Line 136-143 Add more key/values to array
 *
 */
class gdrive
{
    /**
     *
     * @var url
     */
    protected $url;
    /**
     *
     * @var title
     */
    protected $title = '';
    /**
     *
     * @var sources
     */
    public $sources;
    /**
     *
     * @var itag
     */
    protected $itag = [
        37,
        22,
        59,
        18
    ];
    /**
     *
     * @var vidcode
     */
    protected $vidcode = [
        //2D Non-DASH
        '18'    => 360,
        '59'    => 480,
        '22'    => 720,
        '37'    => 1080,
        //3D Non-DASH
        '82'    => 360,
        '83'    => 240,
        '84'    => 720,
        '85'    => 1080
    ];
    /**
     *
     * @param  array    $itags
     * @return void
     */
    public function setItag(array $itag)
    {
        $this->itag = $itag;
    }
    /**
     *
     * @param  array    $vidcode
     * @return void
     */

    public function setVidcode(array $vidcode)
    {
        $this->vidcode = $vidcode + $this->vidcode;
    }
    /**
     *
     * @param  array    $title
     * @return void
     */

    public function setTitle($title)
    {
        $this->title = $title;
    }
    /**
     *
     * @param  string   $gurl
     * @return array
     */

    public function getLink($gurl)
    {
        $source = [];
        if( $this->getDriveId($gurl) ) {
            $body = $this->getByfopen();
            if($body && $this->getStr($body,'status=', '&') === 'ok') {
                $fmt = $this->getStr($body, 'fmt_stream_map=','&');
                $urls = explode(',', urldecode($fmt));

                foreach ($urls as $url) {
                    list($itag,$link) = explode('|', $url);
                    if(in_array($itag, $this->itag)){
                        $source[$this->vidcode[$itag]] = preg_replace("/[^\/]+\.googlevideo\.com/", "redirector.googlevideo.com",$link);
                    }
                }
            }
        }
        $this->sources = $source;
    }
    /**
     *
     * @param  string   $type
     * @return json
     */

    public function getSources($type = 'videojs')
    {
        $s = [];
        $url_tag = ($type == 'videojs') ? 'src' : 'file';
        foreach ($this->sources as $itag => $link) {
            $s[] = [
                'type'  => 'video/mp4',
                'label' => $itag."p",
                'res' => $itag,
                'src'   => $link.'&tile='.$itag,
                $url_tag => $link.'&tile='.$this->title.'-'.$itag,
                'default' => ($itag == '1080') ? "true" : "false",
            ];
        }
        return json_encode($s);
    }
    /**
     *
     * @param  string   $url
     * @return string
     */
    public function getByfopen()
    {
        try {
            $handle = fopen($this->url, "r",false, stream_context_create(['socket' => ['bindto' => '0:0']]));
            if ( !$handle ) {
                throw new \Exception('Url open failed.');
            }
            $contents = stream_get_contents($handle);
            fclose($handle);
            return $contents ? $contents : '';
        } catch( \Exception $e) {
            echo 'Message: ' .$e->getMessage();
        }
    }
    /**
     *
     * @param  string   $url
     * @return mixed
     */

    private function getDriveId($url)
    {
        preg_match('/(?:https?:\/\/)?(?:[\w\-]+\.)*(?:drive|docs)\.google\.com\/(?:(?:folderview|open|uc)\?(?:[\w\-\%]+=[\w\-\%]*&)*id=|(?:folder|file|document|presentation)\/d\/|spreadsheet\/ccc\?(?:[\w\-\%]+=[\w\-\%]*&)*key=)([\w\-]{28,})/i', $url , $match);
        if(isset($match[1])) {
            $this->url = 'https://docs.google.com/get_video_info?docid='.$match[1];
            return true;
        }
        return false;
    }
    /**
     *
     * @param  string   $string
     * @param  string   $find_start
     * @param  string   $find_end
     * @return mixed
     */
    private function getStr($string, $find_start, $find_end)
    {
        $start = stripos($string, $find_start);
        if($start === false) return false;
        $length = strlen($find_start);
        $end = stripos(substr($string, $start+$length), $find_end);
        if($end !== false) {
            $rs = substr($string, $start+$length, $end);
        } else {
            $rs = substr($string, $start+$length);
        }
        return $rs ? $rs : false;
    }
}


  • Thank you for share but i run it on my server and get this link

    {"type":"video/mp4","label":"720p","res":720,default: "true","src":"https://redirector.googlevideo.com/videoplayback?requiressl=yes&id=de7ef43f45cebd4d&itag=22&source=webdrive&ttl=transient&app=explorer&ip=45.32.xxx.xxx&ipbits=24&expire=1482246739&sparams=requiressl,id,itag,source,ttl,ip,ipbits,expire&signature=35E648FC8871D74CB01A8095102A6F955523B526.4D8904D3AB2A68D4BE14A339D285B5619CB39BC3&key=ck2&mm=31&mn=sn-n4v7sn7z&ms=au&mt=1482232032&mv=m&nh=IgpwZjAyLnNqYzA3Kgs3Ny42Ny43MS40NQ&pl=22&safm=0&tile=720","file":"https://redirector.googlevideo.com/videoplayback?requiressl=yes&id=de7ef43f45cebd4d&itag=22&source=webdrive&ttl=transient&app=explorer&ip=45.32.xxx.xxx&ipbits=24&expire=1482246739&sparams=requiressl,id,itag,source,ttl,ip,ipbits,expire&signature=35E648FC8871D74CB01A8095102A6F955523B526.4D8904D3AB2A68D4BE14A339D285B5619CB39BC3&key=ck2&mm=31&mn=sn-n4v7sn7z&ms=au&mt=1482232032&mv=m&nh=IgpwZjAyLnNqYzA3Kgs3Ny42Ny43MS40NQ&pl=22&safm=0&tile=-720","default":"false"},
    

    look good but when it access link

    https://redirector.googlevideo.com/videoplayback?requiressl=yes&id=de7ef43f45cebd4d&itag=22&source=webdrive&ttl=transient&app=explorer&ip=45.32.xxx.xxx&ipbits=24&expire=1482246739&sparams=requiressl,id,itag,source,ttl,ip,ipbits,expire&signature=35E648FC8871D74CB01A8095102A6F955523B526.4D8904D3AB2A68D4BE14A339D285B5619CB39BC3&key=ck2&mm=31&mn=sn-n4v7sn7z&ms=au&mt=1482232032&mv=m&nh=IgpwZjAyLnNqYzA3Kgs3Ny42Ny43MS40NQ&pl=22&safm=0&tile=720
    

    it got error 403. Did you encounter that problem?

    and ipbits=24 . I see on api.getlinkdrive.com ipbits=0 and it run good . I think the problem is ipbits .

  • Hi @Funergy, first of all thank you so much for your script! I have a question about it and hope you can help me again if it's not much trouble. The redirectors links I got with the script are still bound by ip and token. When I print the $SERVER['REMOTEADDR'] it shows the correct client ip, but it seems that streamcontextcreate(['socket' => ['bindto' => '0:0']]) still use the server ip and not the client ip. Is there something I am missing? Thanks again for your help.

    • Its perfectly normal. The script needs to get the script via the server hosts ip.
      The streamcontextcreate is to force the request to use my servers ipv4 adress and not ipv6.

      I dont get it myself why but Google doesnt track the ipv4 urls for some reason.
      So when redirected the ip changes to the ipv6 of the client maybe because the server cant find a correct connection to the ipv6f from the host and the client since most routers now support ipv4 and ipv6.
      And so they have 2ips assigned. This is a way I could interpret it but hey I'm not google ;)

      If I request an Video url in ipv4 and then
      request the actual video with ipv6 so its a fiftyfifty to let it through or not. Since they dont have any idea if its the same client.
      It could be since I last said you can have a ipv4 and an ipv6.
      And I guess google chose for always serve the content to the client.
      So its 60% Accept and 40% Deny

      I hope I explained it good enough since I'm not really excellent at it.

      EDIT: If someone else knows more about this or can prove me wrong. Feel free to do it Im not particularly specialised in this kind of networking stuff

  • @Funergy
    after i upload the php scrit on my web server
    how can i call this php script function on my browser??
    i use link just this in my browser www.mydomainname.com/getlink/?url=https://drive.google.com/file/d/<fileid>/view
    but not work...

    thanks

  • Thanks so much for the code, but I can't seem to reproduce this on my server. The URL is IP-locked and I've tried both IPv4 and v6.

    This might be your server's network configuration that allow this to work. Can you share what your server's network settings are? DNS, network interfaces, IPv4 and v6 settings?

    I think there might be something on Google with URL generation with dual-stack clients.

    • I use google IPv6 DNS servers so I think thats important
      Respond if this fixed it. I'll add it to the OP

      • I tried switching to using only Google IPv6 DNS, it didn't work on my server.

        What region are your servers hosted at?
        Do you have a live-running code somewhere?
        How is your consistency of having this working on client's browser?

        During my fiddling session, I found out that the working stream URL does not change when you reissue a second API request to like getlinkdrive, but when I refresh my own API, everytime the expires and signature parameters change. Maybe it's caching but I don't think it is.
        Do these parameters on your working server change on refresh?

        I also found out that, with the right IP, you can replace the parameter app=* with anything you want. It doesn't cause the 403 error. The parameters which are not defined in the sparams list shouldn't be bounded to the signature, that's probably the reason why you see app=api.getlinkdrive.com.

        • For me it works 100%. I'll be hosting an aplha version for my website and then see if its the same for other people.

          URL's change everytime I request the data.
          I do have live-running code right now but since its still development I cannot share anything yet.

          I use DigitalOcean for my hosting. And its located in Amsterdam.

  • This exploit has been patched by Google and is not working anymore as of this post.

  • Hello! Please can you send me the working source code which doesn't give 403 error when accessed from other IP.
    I know that somehow client's IP is passed to the request from the server. But dont know how to pass the client ip from server to request.

Okay found it already and its a shocker just force ipv4 and its fixed.
reply if you want source code.

I have the solution to 403 error.

Anyone interested just leave a email. (not free)

Why don't you contact the author of the script? He's selling this code.

Above code is returning urls with 403 error, If any one has working solution please mail me at pvtlyf(at)gmail.com
@Funergy @mami

  • Its working for me so idk why it isnt for you

    • I'm using it from VPS, Its not working for me, will you tell me whats your Internet setting, or anything else

      • The only difference I have with stock CentOS settings is Im using google ipv6 dns. I havent tweaked any other network setting

        • Its my VPS Connection Setting
          IPv6 Only
          nameserver 2001:4860:4860:0:0:0:0:6464
          nameserver 2001:4860:4860:0:0:0:0:64
          But I'm getting error
          fopen(): phpnetworkgetaddresses: getaddrinfo failed: Temporary failure in name resolution in

          • Must be your configuration. try pinging other website via terminal/cmd if it doesnt work try looking into your dns settings. Check if you have made the right changes. I cannot see right now what you have done. but it means it doesnt resolve its ip of fopen. Which means in browser talk cannot resolve host name.

        • Please email me at pvtlyf(at)gmail.com, I'll pay for help, Its urgent

        • Hi Funergy,

          I am interested in a working version of the script with example and I wanna make a deal with you.

          Please drop me a line at bunthoeun1990[at]gmail[dot]com

          Thanks

    • And please contact me at email

@mami @IbrahimCh @Funergy

We are still looking for an in-house solution for generating redirector URLs for YouTube. Please email us your quotation at darren.antwan@gmail.com.

We have relied on http://api.getlinkdrive.com/ which not only is slow af, but the URLs seem to expire so caching is out of option.

Hi everyone,

Checkout https://duongtang.clgt.vn

i want to buy this script pls email me thanks

shaniax90 @ gmail.com

I have a solution to take permalink directly from google drive.
Contact me: akunid.indah@gmail.com

I have another solution, but need lots of gsuite accounts.. Its working for now.. contact me for more info.. jchen75@gmail.com

If i am wrong please correct me. Is this last code in firt post or still need to be improved?
If it is plase send to me last shape of code tiklitirtil[at]gmail.com

Okay nevermind,

As I understand there are many different vision on this solution but google close every one of hole one by one. Still there are web sites which using googl drive for their movie it is excellent because it is free space and free cdn but all these sites (which is still active) using someting different then everybody talking online it is app=storage.

Is there anyone who can talk about it, solution with app=storage

  • example of site using app=storage ?
    actually you can remove "app=xxxx" or change to "app=whatever" without affecting the link. the link will still work.

    • 720pizle.com and many others.
      Yes maybe link will be working in fact many other method working too but it is not reliable, sometimes it starts to not work in a few hours sometimes in days but usually it has problem. What I can see that who has app=storage in their link they do not have problem any time anywhere with any browser it just works. I think it is someting how they produce these links.

I use script with localhost (I setup composer) I get error on DOM (chrome).
"Uncaught SyntaxError: Unexpected token"

IS there anybody that can help to me?
Thanks in advance
ps. Still I couldn't get where shoul I neter my original link. I think it is about this.

Well "403 (Forbidden)" is the destiny of project as I understand

Have another answer? Share your knowledge.