Skip to content

Instantly share code, notes, and snippets.

@milesrichardson
Created July 10, 2024 21:50
Show Gist options
  • Save milesrichardson/4661c311199b98023701f6cecd3b89b0 to your computer and use it in GitHub Desktop.
Save milesrichardson/4661c311199b98023701f6cecd3b89b0 to your computer and use it in GitHub Desktop.
How to use VLC to watch m3u8 playlist at URL with custom HTTP referrer and user agent

Imagine this: it's Sunday afternoon at 1pm, and you want to watch some live content. But you don't have a TV subscription. So you do a little Googling, and eventually you find yourself on a sketchy website where you can watch the content you're looking for. But while the website has a video player, it's surrounded by advertisements, and probably a cryptominer too. You don't want this website eating your CPU for 2 hours while you're watching your favorite Sunday afternoon content.

Wouldn't it be nice if you could watch that video in VLC instead? Then you can close the sketchy website and still watch your content. It's like having your cake and taking a bite of it too!

Here's how you do it:

  1. Capture the m3u8 request in dev tools. Open the site (or just the iframe, if possible) in DevTools and click "play." Search the network tab for m3u8 and grab the first request.

  2. Run VLC with command line flags to set the User Agent and Referrer. From the request body, you need to copy the requested URL, the user agent, and the HTTP referrer

Now, open VLC from the command line. If you're on a Mac, your VLC binary is probably located at /Applications/VLC.app/Contents/MacOS/VLC. You can use the --http-referrer and --http-user-agent flags to pass the values you extracted from DevTools to VLC.

For example:

/Applications/VLC.app/Contents/MacOS/VLC \
  --http-referrer "https://somesketchysisterwebsiteofgivemesketchystream.eu/" \
  --http-user-agent "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/117.0" \
  "https://givemesomesketchystream.website/hls/tsn/playlist.m3u8"

This will open VLC, and ensure that it makes HTTP requests to the m3u8 URL with the Referrer and User-Agent headers set to the values you provided.

99% of the time, this is sufficient to watch the playlist. It will not work on sites that use a dynamic playlist URL where the key changes every few chunks (typically, these sites have a host page that refreshes the key and updates the URL of the video player). If you encounter one of these, just move onto one of the other sketchy sites. You should find one that works eventually.

P.S. Having trouble opening DevTools? Some of these sites use a trick where they put a debug; inside an infinite while loop. If you disable breaking on debug statements, you should be able to avoid getting stuck.

@papodaca
Copy link

you can also save these details into a playlist file that can be simply opened:
playlist.m3u

#EXTM3U
#EXTVLCOPT:http-referrer=https://somesketchysisterwebsiteofgivemesketchystream.eu/
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/117.0
https://givemesomesketchystream.website/hls/tsn/playlist.m3u8

@vitali2y
Copy link

(function (xhr) {
  var XHR = XMLHttpRequest.prototype
  var open = XHR.open
  XHR.open = function (method, url) {
    this._method = method
    this._url = url
    if ((arguments[0] == "GET") && ((arguments[1].indexOf(".mp4") > 0) || (arguments[1].indexOf(".m3u8") > 0)))
      console.log("open: url:", url)
    return open.apply(this, arguments)
  }
})(XMLHttpRequest)

@noman-land
Copy link

noman-land commented Jul 14, 2024

And to tie it all together, here's a bookmarklet that will construct and download a playlist.m3u8 file that can be opened in VLC.

(() => {
  const XHR = XMLHttpRequest.prototype;
  const open = XHR.open;
  let done = false;
  XHR.open = function (...args) {
    const [method, url] = args;
    this._method = method;
    this._url = url;
    if (
      done === false &&
      method === 'GET' &&
      ['.mp4', '.m3u8'].some(type => new URL(url).pathname.endsWith(type))
    ) {
      done = true;
      const playlist = [
        '#EXTM3U',
        `#EXTVLCOPT:http-referrer=${location.toString()}`,
        '#EXTVLCOPT:http-user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/117.0',
        url,
      ].join('\n');
      const link = document.createElement('a');
      link.setAttribute('download', 'playlist.m3u8');
      link.setAttribute('href', `data:application/vnd.apple.mpegurl;base64,${btoa(playlist)}`);
      link.click();
    }
    return open.apply(this, args);
  };
})();

@chapmanjacobd
Copy link

The yt-dlp generic extractor will be able to handle this and more. If you have both yt-dlp and mpv installed then you can often just do mpv $video_page_url

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment