How to extract Google Drive video URLs for web player integration

I’m trying to build a service that extracts direct video links from Google Drive files so I can embed them in web players like JWPlayer and VideoJS on my website. I want something similar to existing API services but I can’t figure out the right approach.

I found some code on GitHub and modified it for my needs. The extraction part works and I get video URLs, but when I try to play them I get 403 permission errors. The videos won’t load in the player.

I think the issue might be related to IP restrictions or authentication requirements. Do I need to implement OAuth 2.0 or handle IP whitelisting to access Google’s video APIs properly?

Here’s my main class for handling the drive links:

namespace VideoExtractor;

class DriveParser
{
    protected $endpoint;
    protected $filename = '';
    public $videoSources;
    
    protected $qualityTags = [
        37, 22, 59, 18
    ];
    
    protected $formatMap = [
        '18' => '360p',
        '59' => '480p', 
        '22' => '720p',
        '37' => '1080p',
        '82' => '360p_3d',
        '83' => '240p_3d',
        '84' => '720p_3d',
        '85' => '1080p_3d'
    ];
    
    public function setQualityTags(array $tags)
    {
        $this->qualityTags = $tags;
    }
    
    public function setFormatMap(array $formats)
    {
        $this->formatMap = $formats + $this->formatMap;
    }
    
    public function setFilename($name)
    {
        $this->filename = $name;
    }
    
    public function extractUrls($driveUrl)
    {
        $results = [];
        
        if($this->parseFileId($driveUrl)) {
            $response = $this->fetchVideoInfo();
            
            if($response && $this->extractValue($response, 'status=', '&') === 'ok') {
                $streamData = $this->extractValue($response, 'fmt_stream_map=', '&');
                $urlList = explode(',', urldecode($streamData));
                
                foreach($urlList as $urlData) {
                    list($tag, $videoUrl) = explode('|', $urlData);
                    if(in_array($tag, $this->qualityTags)) {
                        $results[$this->formatMap[$tag]] = preg_replace("/[^\/]+\.google\.com/", "redirector.googlevideo.com", $videoUrl);
                    }
                }
            }
        }
        $this->videoSources = $results;
    }
    
    public function getPlayerConfig($playerType = 'jwplayer')
    {
        $config = [];
        $urlKey = ($playerType == 'jwplayer') ? 'src' : 'file';
        
        foreach($this->videoSources as $quality => $url) {
            $config[] = [
                'type' => 'video/mp4',
                'label' => $quality,
                'file' => $url . '&title=' . $quality,
                $urlKey => $url . '&title=' . $this->filename . '-' . $quality
            ];
        }
        return json_encode($config);
    }
    
    private function fetchVideoInfo()
    {
        try {
            $stream = fopen($this->endpoint, "r");
            if(!$stream) {
                throw new \Exception('Failed to open URL.');
            }
            $data = stream_get_contents($stream);
            fclose($stream);
            return $data ?: '';
        } catch(\Exception $e) {
            echo 'Error: ' . $e->getMessage();
        }
    }
    
    private function parseFileId($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, $matches);
        
        if(isset($matches[1])) {
            $this->endpoint = 'https://docs.google.com/get_video_info?docid=' . $matches[1];
            return true;
        }
        return false;
    }
    
    private function extractValue($text, $startMarker, $endMarker)
    {
        $startPos = stripos($text, $startMarker);
        if($startPos === false) return false;
        
        $markerLength = strlen($startMarker);
        $endPos = stripos(substr($text, $startPos + $markerLength), $endMarker);
        
        if($endPos !== false) {
            $result = substr($text, $startPos + $markerLength, $endPos);
        } else {
            $result = substr($text, $startPos + $markerLength);
        }
        
        return $result ?: false;
    }
}

And here’s my player implementation:

<?php
require __DIR__ . 'driveparser.php';
use \VideoExtractor\DriveParser;

$parser = new DriveParser;
$parser->extractUrls('https://drive.google.com/file/d/0B4EeKbDRC_36QzVNd2xnUEJfU28/view');
?>

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Video Player Test</title>
</head>
<body>
    <div id='videoPlayer'></div>
    
    <script src="https://content.jwplatform.com/libraries/cJ0z4Ufh.js"></script>
    <script>
        jwplayer.key='r1br2DJmUxLwrLgpi7D4IjgUHoHsDvGWHw2T7Q==';
        var player = jwplayer('videoPlayer');
        player.setup({
            sources: <?php echo $parser->getPlayerConfig('jwplayer');?>,
            width: '50%',
            height: '50%',
            aspectratio: '16:9',
            fullscreen: true,
            autostart: true
        });
    </script>
    
    <pre><?php print_r($parser->getPlayerConfig('jwplayer')); ?></pre>
</body>
</html>

When I test the extracted URLs directly in browser I get a 403 error saying my client doesn’t have permission to access the videoplayback endpoint. The error mentions IP and expiration parameters in the URL. Is this a common issue with Google Drive video extraction?

Been fighting Google Drive video extraction for years. The IP restrictions and auth tokens make direct URLs a total nightmare. Even when you get them working, they constantly break.

Skip all that headache. I automated this with Latenode and it’s so much cleaner.

Here’s my workflow:

  • Watches Google Drive folder for new videos
  • Auto-copies them to real video hosting (Vimeo, Bunny CDN, whatever)
  • Updates database with new embed URLs
  • Sends webhooks to refresh players

No more Google restrictions. No bandwidth costs from proxying. No broken URLs.

I run this for a client portal with training videos. Non-tech staff upload to Drive, Latenode migrates everything automatically, web players always work.

Runs completely in the background. Zero maintenance after setup.

Takes maybe 30 minutes to configure: https://latenode.com

Those 403 errors are normal - Google’s doing exactly what they designed it to do. Drive video URLs have signed parameters tied to the original IP address and expire in about 6 hours. When your web players try loading these URLs from different client IPs, Google blocks them. I’ve hit this same wall before. That old get_video_info endpoint is basically dead now - Google locked it down around 2019-2020 specifically to stop direct URL extraction like this. The IP binding means even if you extract URLs server-side, they’re useless when users try accessing them from their browsers. Your only real option is setting up a proxy on your server that fetches the video content and streams it to your players, but that’ll cost you big on bandwidth. Otherwise, just use Google Drive’s official embed player or move public videos to YouTube instead.

Been there! Hit the same wall last year building something similar. You’re dealing with Google’s CORS policy plus their referrer checking - even with valid URLs, browsers block cross-origin requests to Google’s video servers unless the referrer’s whitelisted.

Tried everything for weeks. Rotating user agents, session persistence, spoofing referrer headers. Nothing stuck because Google fingerprints requests and has multiple protection layers.

What worked: ditched the direct URL approach entirely. Built a server-side streaming proxy that uses Google Drive API with service accounts, downloads video chunks to memory, then streams to clients. Catch is all video traffic runs through your server, so you need solid bandwidth. Fine for smaller projects but gets expensive with high traffic. Google Drive API docs have solid examples for this setup.

That get_video_info endpoint’s been broken since 2020 when Google locked down their API. Those 403 errors aren’t a bug - Google deliberately blocked direct URL extraction to stop unauthorized embedding.

I wasted months trying to reverse engineer their new streaming protocols after they killed the old endpoints. The URLs now have encrypted signatures that check your IP, user agent, and session tokens. Even if you extract working URLs, they only work for that specific browser session.

OAuth won’t fix this - it’s not an auth issue. Google just doesn’t want you accessing video URLs directly anymore. Your code’s fine, but you’re fighting Google’s intentional blocks, not something you can work around.

Just use Google Drive’s official embed iframe or switch to real video hosting. I gave up and moved everything to Bunny CDN after burning too much time on Drive extraction hacks.

Google killed this years ago - you’re hitting deprecated endpoints. Those 403s are because Drive URLs now use time-limited tokens that expire quickly. I’ve tried this approach myself and it’s a waste of time. Just upload your videos to Cloudflare Stream or Wasabi instead. Costs about $1/TB but actually works, unlike these Drive hacks that break whenever Google updates something.