Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proper usage example #1

Open
Elite opened this issue Oct 11, 2024 · 5 comments
Open

Proper usage example #1

Elite opened this issue Oct 11, 2024 · 5 comments

Comments

@Elite
Copy link

Elite commented Oct 11, 2024

Hi,

I am using this example to test things out but the download is failing with HTTP Error 403, what am I missing here:

// ==UserScript==
// @name         browser-ytdl-core: no proxy
// @description  example: CORS restricts usage to 'youtube.com' domain
// @version      1.0.0
// @require      ../../dist/es2020/ytdl-core.js
// @match        *://youtube.com/watch?v=*
// @match        *://youtube.com/embed/*
// @match        *://*.youtube.com/watch?v=*
// @match        *://*.youtube.com/embed/*
// @icon         https://www.youtube.com/favicon.ico
// @run-at       document_end
// ==/UserScript==

// add support for CSP 'Trusted Type' assignment
(function() {
    'use strict';

    // Add support for CSP 'Trusted Type' assignment
    const addDefaultTrustedTypePolicy = function() {
        if (typeof window.trustedTypes !== 'undefined') {
            try {
                const passthroughPolicy = string => string;
                window.trustedTypes.createPolicy('default', {
                    createHTML: passthroughPolicy,
                    createScript: passthroughPolicy,
                    createScriptURL: passthroughPolicy
                });
            } catch(e) {
                console.error('Failed to create trusted type policy:', e);
            }
        }
    };

    // Main function to handle video download
    async function downloadVideo() {
        addDefaultTrustedTypePolicy();

        if (!window.ytdl) {
            console.error('ytdl-core is not available');
            return;
        }

        try {
            const videoUrl = window.location.href;
            const info = await ytdl.getInfo(videoUrl);
            const format = ytdl.chooseFormat(info.formats, { quality: '18' });

            if (!format) {
                console.error('itag 18 not available for this video');
                return;
            }

            // Create download link
            const downloadLink = document.createElement('a');
            downloadLink.textContent = 'Download (itag 18)';
            downloadLink.style.position = 'fixed';
            downloadLink.style.top = '10px';
            downloadLink.style.right = '10px';
            downloadLink.style.zIndex = '9999';
            downloadLink.style.background = '#065fd4';
            downloadLink.style.color = 'white';
            downloadLink.style.padding = '10px 15px';
            downloadLink.style.textDecoration = 'none';
            downloadLink.style.borderRadius = '3px';
            downloadLink.style.fontWeight = 'bold';

            downloadLink.href = format.url;
            downloadLink.download = `${info.videoDetails.title}.mp4`;

            downloadLink.addEventListener('click', (event) => {
                event.stopPropagation();
            });

            document.body.appendChild(downloadLink);

        } catch (error) {
            console.error('An error occurred:', error.message);
        }
    }

    // Run the main function
    downloadVideo();
})();```
@warren-bank
Copy link
Owner

To be perfectly honest.. I haven't tried to download or watch any of the video URLs included in the response. Getting the library to work was my focus up to this point. Now that it does (appears to), the next thing I had in mind was to update my Youtube userscript.. which obtained its URLs using custom logic and hasn't been updated in a very long time. I figured I'd replace all of the custom logic with this library, which can be downloaded from a CDN. Stay tuned.. I'll probably play with it tonight.. and I'll let you know how it works. Of course, the example userscript taken verbatim just dumps the entire (huge) JSON response to the DOM.. so you could test each of the URLs by hand.. which is probably where I'm going to begin.

@Elite
Copy link
Author

Elite commented Oct 11, 2024

Thanks, do update your findings.

@warren-bank
Copy link
Owner

warren-bank commented Oct 11, 2024

Shoot.. you're right.. all of the URLs return a 403 error. Seems to be related to this issue, which they apparently found a workaround for when running in a Node.js environment.. but my substitution of undici for fetch must've caused a reversion.

I'll need to read the commits that closed this issue to see what solution they found..


aside:

I tested my old Youtube userscript to see if it still works at all.. and it behaves in the exact same way. It's still able to obtain URLs for all of the video resolutions, but they all return a 403 status.


update:

  • no help there.. looks like they just lowered the version of this undici dependency, and called it a fix
  • I'm sure the real culprit is the agent class.. that is passed as a parameter to undici.. and appears to serve as a cookie jar
  • as a 1st attempt, I tried to edit the default fetch options with:
    const fetchOptions = {
      method:      'GET',
      mode:        'cors',
      credentials: 'include',
      redirect:    'follow'
    }
    
    if (window.location.hostname.toLowerCase().includes('youtube')) {
      document.cookie = 'SOCS=CAI'
    }
    • diff:
      • credentials will include cookies with the requests
      • document.cookie sets this cookie for the "youtube.*" domain
        • which is hard coded into the agent class
    • but no joy
    • will need to dig deeper..
  • as a 2nd attempt, I committed a few changes to the mock library used to make network requests
    • now, all requests do succeed and receive a 200 response
    • however, it doesn't fix anything.. all of the video URLs still return a 403
  • I'm not eager to spend very much more time on this..
    • I'm running out of ideas
    • maybe somebody more familiar with how Youtube whitelists IPs.. and the cookies involved.. will someday stumble across this repo/issue and make a helpful suggestion
    • wishful thinking

@Elite
Copy link
Author

Elite commented Oct 12, 2024

Maybe this repo can give you some ideas - https://github.com/ybd-project-ver1/ytdl-core

@warren-bank
Copy link
Owner

warren-bank commented Oct 12, 2024

OK, so lets file this under serendipitous.. PR#111 was opened today, and it fixes the issue!

I just pushed tag v4.14.4-distubejs.4 to npm, which includes this update to ytdl-core that hasn't yet been merged.

To continue your testing, please update your userscript with:

@require https://cdn.jsdelivr.net/npm/@warren-bank/browser-ytdl-core@4.14.4-distubejs.4/dist/es2020/ytdl-core.js

or, optionally:

@require https://cdn.jsdelivr.net/npm/@warren-bank/browser-ytdl-core@latest/dist/es2020/ytdl-core.js

PS: I just tested your userscript, and it works great 😃

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants