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

What could it be 'InnertubeError: Streaming data not available' only in remote server but working locally? #748

Closed
4 tasks done
rogerpadilla opened this issue Sep 11, 2024 · 12 comments
Labels
question Further information is requested

Comments

@rogerpadilla
Copy link
Contributor

rogerpadilla commented Sep 11, 2024

Question

Hello, what could it be that my exact code works fine locally but when deploy it in remote servers I got this weird error:

InnertubeError: Streaming data not available
    at Module.chooseFormat (/opt/src/node_modules/youtubei.js/src/utils/FormatUtils.ts:135:11)
    at VideoInfo.chooseFormat (/opt/src/node_modules/youtubei.js/src/core/mixins/MediaInfo.ts:150:24)
    at chooseFormat (/opt/src/server/helpers/yti.helper.ts:59:15)

My current related code is as following (compacted):

  /* I change this every half an hour automatically */
  let _yt: Innertube & { myCreatedAt?: Date };

  async function getYt() {
    const randomMilliseconds = getRandomMilliseconds();
    const thresholdDate = new Date(Date.now() - randomMilliseconds);

    if (thresholdDate <= _yt?.myCreatedAt) {
      return _yt;
    }

    const { poToken, visitorData } = await scrapeYtSession();

    _yt = await Innertube.create({
      po_token: poToken,
      visitor_data: visitorData,
      generate_session_locally: true,
      cache: new UniversalCache(false),
    });

    _yt.myCreatedAt = new Date();

    return _yt;
  }

  async function getDownloadUrl(url: string) {
    const id = getVideoId(url);
    const yt = await getYt();
    const info = await yt.getBasicInfo(id);
    const format = chooseFormat(info);
    const decipheredUrl = format.decipher(yt.session.player);
    // logger.debug('** decipheredUrl', decipheredUrl);
    return decipheredUrl;
  }

  function chooseFormat(info: VideoInfo) {
    return info.chooseFormat?.({ type: 'video+audio', quality: 'bestefficiency' }) ?? info.streaming_data?.formats[0];
  }

thanks in advance.

Other details

No response

Checklist

  • I am running the latest version.
  • I checked the documentation and found no answer.
  • I have searched the existing issues and made sure this is not a duplicate.
  • I have provided sufficient information.
@rogerpadilla rogerpadilla added the question Further information is requested label Sep 11, 2024
@whiskeycola
Copy link

whiskeycola commented Sep 11, 2024

check info.playability_status maybe you are detected as bot

@iamDonkey
Copy link

Same situation
Without bearer token: sign in to confirm you are not bot
With bearer token : content not available

@rogerpadilla
Copy link
Contributor Author

rogerpadilla commented Sep 11, 2024

hey @whiskeycola, thanks for your help.

Yes, it seems you are right, below is what I get local vs remote server.

So as I am already using BgUtils to get the tokens, what else you suggest I could do to avoid my app recognized as a bot?

Thanks again.

local

yti extractInfo info.playability_status {
  status: 'OK',
  reason: '',
  embeddable: true,
  audio_only_playablility: null,
  error_screen: null
}

remove

** yti extractInfo info.playability_status {
    is_family_safe: undefined,
    category: null,
    has_ypc_metadata: null,
    start_timestamp: null,
    end_timestamp: null,
  status: 'LOGIN_REQUIRED',
  reason: 'Sign in to confirm you’re not a bot',

@IRGC
Copy link

IRGC commented Sep 11, 2024

i think google updated poToken generation. poToken generated by bgutil does not seem to work.

@LuanRT
Copy link
Owner

LuanRT commented Sep 11, 2024

There were no major changes to the BotGuard code. Your IPs are likely blocked. PoTokens do not bypass full IP blocks.

@rogerpadilla
Copy link
Contributor Author

Any way to bypass that @LuanRT? thanks.

@rustynail1984
Copy link

rustynail1984 commented Sep 13, 2024

@LuanRT
i can confirm that the WEB Client is no longer working for/with the trusted session solution aka poToken.
2 days ago, i was able to fix that by using the WEB_EXPERIMENTS client. But that also stopped working today.

Seems Google/YouTube is closing all their backdoors now.

Currently solution is changing the Client to

"clientName": "WEB_CREATOR",
"clientVersion": "1.20220918",

@rogerpadilla
Copy link
Contributor Author

hey @rustynail1984, do you know if this solution may be applied to the code I am using above? thanks.

@rustynail1984
Copy link

hey @rustynail1984, do you know if this solution may be applied to the code I am using above? thanks.

yes it should work.

The reasson is that it works locallly is, your local ip is not banned by youtube while your seerver ip is banned.

This poToken Solution should bypass the ip ban. In other way this bypass is not longer working for the WEB, MWEB and WEM_EXPERIMENTS client.

I found today out that the WEB_CREATOR client is still working, but i expect that this will also stop working in the next 2 days.

@rogerpadilla
Copy link
Contributor Author

So please help me understand something.

What I need is a download URL of the video no matter where it is generated.

Is using the Web client the best way as the IP of the user using my app wont be blocked as it will do a few requests per days from its own IP.

Now if this is true, can the Web be imported and used in the web browser somehow?

Apologies if I said any kind of “stupid” questions but this world is new to me, thanks again.

@rustynail1984
Copy link

You can do Client side requests (in Browser) in this way.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      const postData = async (url = "", data = {}) => {
        const response = await fetch(url, {
          method: "POST",
          mode: "cors",
          cache: "no-cache",
          credentials: "same-origin",
          headers: {
            "Content-Type": "application/json",
            Accept: "application/json",
          },
          redirect: "follow",
          referrerPolicy: "no-referrer",
          body: JSON.stringify(data),
        });

        return response.json();
      };

      const getData = async () => {
        const data = await postData(
          "https://release-youtubei.sandbox.googleapis.com/youtubei/v1/player",
          {
            videoId: "2vjPBrBU-TM",
            context: {
              client: {
                userAgent:
                  "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36",
                clientName: "ANDROID_TESTSUITE",
                clientVersion: "1.9",
              },
            },
          }
        );
      };

      getData();
    </script>
  </body>
</html>

@rogerpadilla
Copy link
Contributor Author

Thank you so much!

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

No branches or pull requests

6 participants