YouTube.js icon indicating copy to clipboard operation
YouTube.js copied to clipboard

Request to https://www.youtube.com/youtubei/v1/player?prettyPrint=false&alt=json failed with status 400

Open CasandraRos opened this issue 1 year ago • 36 comments

How to fix this error?

Error: InnertubeError: Request to https://www.youtube.com/youtubei/v1/player?prettyPrint=false&alt=json failed with status 400 at HTTPClient.fetch (/home/ubuntu/scrape/node_modules/youtubei.js/bundle/node.cjs:2074:11) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async Actions.execute (/home/ubuntu/scrape/node_modules/youtubei.js/bundle/node.cjs:24255:22) at async Innertube.getBasicInfo (/home/ubuntu/scrape/node_modules/youtubei.js/bundle/node.cjs:29778:22) at async Innertube.download (/home/ubuntu/scrape/node_modules/youtubei.js/bundle/node.cjs:29988:18) at async /home/ubuntu/scrape/ytm4.js:61:20 { info: '{\n' + ' "error": {\n' + ' "code": 400,\n' + ' "message": "Request contains an invalid argument.",\n' + ' "errors": [\n' + ' {\n' + ' "message": "Request contains an invalid argument.",\n' + ' "domain": "global",\n' + ' "reason": "badRequest"\n' + ' }\n' + ' ],\n' + ' "status": "INVALID_ARGUMENT"\n' + ' }\n' + '}\n', date: 2024-11-15T09:16:23.932Z, version: '11.0.1'

CasandraRos avatar Nov 15 '24 09:11 CasandraRos

it was working since yesterday

yestoall avatar Nov 15 '24 10:11 yestoall

it was working since yesterday

Yesterday it was still running, only recently did it start to have such an error.

CasandraRos avatar Nov 15 '24 10:11 CasandraRos

Same thing here, we started encountering this error around 24 hours ago. It was working fine before that.

leamarty avatar Nov 15 '24 11:11 leamarty

I believe this issue is the same as https://github.com/yt-dlp/yt-dlp/issues/11462

If YouTube is limiting the current OAuth sign-in to just the TV client, then I suppose we'd have to return to passing cookies. I hope I'm wrong - the OAuth method is really convenient for users.

patrickkfkan avatar Nov 15 '24 12:11 patrickkfkan

started getting the same error today aswell

babli118 avatar Nov 15 '24 14:11 babli118

I believe this issue is the same as yt-dlp/yt-dlp#11462

If YouTube is limiting the current OAuth sign-in to just the TV client, then I suppose we'd have to return to passing cookies. I hope I'm wrong - the OAuth method is really convenient for users.

Hello, good day,

I think the same, we should each implement a personalized OAuth authentication or, as you mentioned, use cookies.

I don't have experience with cookies, so I would appreciate it if you could provide me with an example of how to obtain those session cookies and use them for authentication.

LArroyoS avatar Nov 15 '24 16:11 LArroyoS

I believe this issue is the same as yt-dlp/yt-dlp#11462 If YouTube is limiting the current OAuth sign-in to just the TV client, then I suppose we'd have to return to passing cookies. I hope I'm wrong - the OAuth method is really convenient for users.

Hello, good day,

I think the same, we should each implement a personalized OAuth authentication or, as you mentioned, use cookies.

I don't have experience with cookies, so I would appreciate it if you could provide me with an example of how to obtain those session cookies and use them for authentication.

I have already tried using a custom OAuth, and for now, it seems to solve this error.

However, it might be necessary to learn how to use cookies if we want to perform operations without YouTube's consumption limits.

LArroyoS avatar Nov 15 '24 18:11 LArroyoS

Como coloca esse OAuth personalizado, tem exemplo de código?

tonykx avatar Nov 15 '24 18:11 tonykx

Como coloca esse OAuth personalizado, tem exemplo de código?

Yes, there is an example in the official YouTube.js documentation. I basically copied and pasted it to test if it would work.

Here is the link: https://github.com/LuanRT/YouTube.js/blob/main/examples/auth/custom-oauth2-creds/index.ts

LArroyoS avatar Nov 15 '24 18:11 LArroyoS

I have written a guide on how to get the cookie value.

So, after getting the value, you pass it like this:

const innertube = await Innertube.create({  cookie });

I have already tried using a custom OAuth, and for now, it seems to solve this error.

Interesting. Appreciate if you could share the process too?

patrickkfkan avatar Nov 15 '24 18:11 patrickkfkan

He escrito una guía sobre cómo obtener el valor de la cookie.

Entonces, después de obtener el valor, lo pasa así:

What might be a bit complicated is obtaining the OAuth credentials.

  • To do this, you need to create a new project.
  • Go to APIs and services.
  • Configure the OAuth consent screen.
  • Then go to credentials and create a new credential 'OAuth client ID'.
  • Select the type of application, in my case, since I have it locally, I use "Desktop app", as the others have restrictions for using http://localhost:.
  • When you create the credential, copy the client ID and the key.

This video can guide you, it's not about OAuth, but the steps are the same, you just need to choose 'OAuth ID' in credentials.

https://www.youtube.com/watch?time_continue=76&v=LLAZUTbc97I&embeds_referring_euri=https%3A%2F%2Fwww.bing.com%2F&embeds_referring_origin=https%3A%2F%2Fwww.bing.com&source_ve_path=Mjg2NjY

LArroyoS avatar Nov 15 '24 18:11 LArroyoS

Será que vai ter uma atualização na biblioteca que resolva, ou precisamos mexer no código?

tonykx avatar Nov 15 '24 18:11 tonykx

¿Habrá una actualización de la biblioteca que lo resuelva, o necesitamos cambiar el código?

No, I know, but I recommend starting to learn about these settings.

LArroyoS avatar Nov 15 '24 18:11 LArroyoS

Custom OAuth could be an effective solution too. I remember creating a few for use with the official YouTube API a couple years back. Then came this project that made everything so much more simple and powerful :heart_eyes:

patrickkfkan avatar Nov 15 '24 19:11 patrickkfkan

O OAuth personalizado também pode ser uma solução eficaz. Lembro-me de criar alguns para usar com a API oficial do YouTube alguns anos atrás. Então veio esse projeto que tornou tudo muito mais simples e poderoso 😍

Envie seu código aqui pra eu ver como devo fazer

tonykx avatar Nov 15 '24 19:11 tonykx

I have written a guide on how to get the cookie value.

So, after getting the value, you pass it like this:

const innertube = await Innertube.create({  cookie });

I have already tried using a custom OAuth, and for now, it seems to solve this error.

Interesting. Appreciate if you could share the process too?

I have written a guide on how to get the cookie value.

So, after getting the value, you pass it like this:

const innertube = await Innertube.create({  cookie });

I have already tried using a custom OAuth, and for now, it seems to solve this error.

Interesting. Appreciate if you could share the process too?

I am going to opt for using cookies. I have conducted some tests as you indicated, and I must say it works. However, I have a question: how can I obtain data from a specific channel?

For instance, I have two channels on my YouTube account, the main one and a secondary one. By passing the cookies, I only get data from my main user, but I want to access my secondary channel.

Is there any way to do this using cookies?

LArroyoS avatar Nov 15 '24 20:11 LArroyoS

Can any of you tell what is missing in my function, I tried using cookies:

case 'play2': { if (args.length < 1) return reply("Insira o comando, e em seguida um nome para a pesquisa!");

const { Innertube } = require('youtubei.js');
const fetch = (await import("node-fetch")).default;
const fs = require('fs');

// Criação da instância do Innertube com cookies
const cookie = 'z'; // Substitua pelo cookie adequado
const youtube = await Innertube.create({ cookie });

try {
    // Realiza a pesquisa diretamente
    const searchResults = await youtube.search(args.join(" "));
    const firstResult = searchResults.results[0];
    
    if (!firstResult) {
        return reply("Nenhum vídeo encontrado.");
    }

    const videoId = firstResult.id;
    const videoInfo = await youtube.getBasicInfo(videoId);
    const audioFormat = videoInfo.streaming_data?.formats[0]; 
    
    if (!audioFormat) {
        return reply("Formato de áudio não encontrado.");
    }

    const audioUrl = audioFormat.decipher(youtube.session.player);
    const vidName = `audio_${Date.now()}.mp3`;
    const path = `Del/${vidName}`;
    const writer = fs.createWriteStream(path);

    const audioStream = await fetch(audioUrl);
    
    if (!audioStream.ok) {
        throw new Error(`Erro ao baixar áudio: ${audioStream.statusText}`);
    }
    
    audioStream.body.pipe(writer);

    writer.on("finish", async () => {
        console.log("Download Completo!");
        await conn.sendMessage(from, { audio: { url: path }, mimetype: "audio/mpeg" }, { quoted: info });
        fs.unlink(path, (err) => {
            if (err) console.error("Erro ao deletar o arquivo:", err);
        });
    });

} catch (error) {
    console.error("Erro durante o processo:", error);
    reply("Ocorreu um erro ao tentar reproduzir o áudio.");
}

break;

}

tonykx avatar Nov 16 '24 00:11 tonykx

The error says the audio format was not found

tonykx avatar Nov 16 '24 00:11 tonykx

I have written a guide on how to get the cookie value. So, after getting the value, you pass it like this:

const innertube = await Innertube.create({  cookie });

I have already tried using a custom OAuth, and for now, it seems to solve this error.

Interesting. Appreciate if you could share the process too?

I have written a guide on how to get the cookie value. So, after getting the value, you pass it like this:

const innertube = await Innertube.create({  cookie });

I have already tried using a custom OAuth, and for now, it seems to solve this error.

Interesting. Appreciate if you could share the process too?

I am going to opt for using cookies. I have conducted some tests as you indicated, and I must say it works. However, I have a question: how can I obtain data from a specific channel?

For instance, I have two channels on my YouTube account, the main one and a secondary one. By passing the cookies, I only get data from my main user, but I want to access my secondary channel.

Is there any way to do this using cookies?

How do I use cookies?, I used cookies before but I have to change my cookies frequently, is there a way to solve that?

CasandraRos avatar Nov 16 '24 06:11 CasandraRos

@LArroyoS Does that not require google to approve you?

sgebr01 avatar Nov 17 '24 11:11 sgebr01

I am getting the same error :(

farhaanaliii avatar Nov 17 '24 15:11 farhaanaliii

@LArroyoS Does that not require google to approve you?

No, you do not need YouTube to approve your app unless you need to store more than 100 users.

LArroyoS avatar Nov 17 '24 17:11 LArroyoS

Como coloca esse OAuth personalizado, tem exemplo de código?

Yes, there is an example in the official YouTube.js documentation. I basically copied and pasted it to test if it would work.

Here is the link: https://github.com/LuanRT/YouTube.js/blob/main/examples/auth/custom-oauth2-creds/index.ts

Thanks! This method worked for me.

farhaanaliii avatar Nov 19 '24 07:11 farhaanaliii

Como coloca esse OAuth personalizado, tem exemplo de código?

Yes, there is an example in the official YouTube.js documentation. I basically copied and pasted it to test if it would work.

Here is the link: https://github.com/LuanRT/YouTube.js/blob/main/examples/auth/custom-oauth2-creds/index.ts

The first time I try, it's successful, but the streaming links give me a 403 error. When I try again, I get this error.

Screenshot from 2024-11-24 14-39-47(1)

mhi-iranmanesh avatar Nov 24 '24 11:11 mhi-iranmanesh

The first time I try, it's successful, but the streaming links give me a 403 error. When I try again, I get this error.

Screenshot from 2024-11-24 14-39-47(1)

It may be due to your configuration in the 'OAuth Consent Screen'.

LArroyoS avatar Nov 24 '24 22:11 LArroyoS

The first time I try, it's successful, but the streaming links give me a 403 error. When I try again, I get this error. Screenshot from 2024-11-24 14-39-47(1)

It may be due to your configuration in the 'OAuth Consent Screen'.

thank you it solved. but my streaming links get 403 error! do you have idea?

mhi-iranmanesh avatar Nov 25 '24 16:11 mhi-iranmanesh

Previously I used Oauth but now it's no longer possible, and I tried using cookies, previously it was possible but now for some reason it can no longer respond to the code always asking for login, I have used txt/json and it's still the same, this is the code I used, can anyone help me?

`const { Innertube, Utils } = require('youtubei.js'); const path = require('path'); const fs = require('fs'); const { createWriteStream, existsSync, mkdirSync } = fs;

function extractVideoId(url) { const regex = /(?:https?://)?(?:www.)?(?:m.)?(?:youtube.com/(?:shorts/|[^/\n\s]+/\S+/|(?:v|e(?:mbed)?)/|\S*?[?&]v=)|youtu.be/)([a-zA-Z0-9_-]{11})/; const match = url.match(regex); return match ? match[1] : null; }

async function youtubeAudio(audioUrl) { try { const cookies = './cookies.json';

const yt = await Innertube.create({ cookie: cookies });

const audioId = extractVideoId(audioUrl);
if (!audioId) {
  throw new Error('Invalid URL. Please provide a valid YouTube URL.');
}

console.log(`🔍 Video ID found: ${audioId}`);

const stream = await yt.download(audioId, {
  type: 'audio',
  quality: 'best',
  format: 'mp4',
  client: 'YTMUSIC',
});

console.info(`📥 Starting audio download for video ${audioId}...`);

const tempFileName = `audio_${audioId}.mp3`;
const downloadDir = path.join(__dirname, 'tmp');
const tempFilePath = path.join(downloadDir, tempFileName);

if (!existsSync(downloadDir)) {
  mkdirSync(downloadDir, { recursive: true });
}

const tempFile = createWriteStream(tempFilePath);
for await (const chunk of Utils.streamToIterable(stream)) {
  tempFile.write(chunk);
}
tempFile.end();

console.info(`✅ Download completed: ${tempFilePath}`);

return tempFileName;

} catch (err) { console.error(❌ Error: ${err.message}); } }`

And `async function youtubeAudio(audioUrl) { try { const CREDENTIALS_PATH = './credentials.json';

const loadCredentials = () => {
  if (existsSync(CREDENTIALS_PATH)) {
    return JSON.parse(fs.readFileSync(CREDENTIALS_PATH, 'utf-8'));
  }
  return null;
};

const saveCredentials = (credentials) => {
  fs.writeFileSync(CREDENTIALS_PATH, JSON.stringify(credentials));
};

const yt = await Innertube.create({
  cache: new UniversalCache(false),
  generate_session_locally: true,
});

yt.session.on('auth-pending', (data) => {
  console.log(`Go to ${data.verification_url} in your browser and enter code ${data.user_code} to authenticate.`);
});

yt.session.on('auth', ({ credentials }) => {
  console.log('Sign in successful:', credentials);
  saveCredentials(credentials);
});

yt.session.on('update-credentials', async ({ credentials }) => {
  console.log('Credentials updated:', credentials);
  saveCredentials(credentials);
  await yt.session.oauth.cacheCredentials();
});

const credentials = loadCredentials();
await yt.session.signIn(credentials);

const audioId = extractVideoId(audioUrl);
if (!audioId) {
  throw new Error('Invalid URL');
}

const stream = await yt.download(audioId, {
  type: 'audio',
  quality: 'best',
  format: 'mp4',
  client: 'YTMUSIC',
});

console.info(`Downloading audio from video ${audioId}`);

const tempFileName = `audio_${audioId}.mp3`;
const downloadDir = path.join(__dirname,  'file');
const tempFilePath = path.join(downloadDir, tempFileName);

if (!existsSync(downloadDir)) {
  mkdirSync(downloadDir, { recursive: true });
}

const tempFile = createWriteStream(tempFilePath);

for await (const chunk of Utils.streamToIterable(stream)) {
  tempFile.write(chunk);
}

tempFile.end();

const stats = await new Promise((resolve, reject) => {
  fs.stat(tempFilePath, (err, stats) => {
    if (err) reject(err);
    else resolve(stats);
  });
});

console.log(`Download completed: ${tempFilePath}`);
return tempFilePath;

} catch (err) { console.error('Error:', err); } } `

ClayzaAubert avatar Nov 27 '24 08:11 ClayzaAubert

@mhi-iranmanesh

thank you it solved. but my streaming links get 403 error! do you have idea?

You're probably not passing in PoTokens. It is required when requesting video info with the WEB client.

LuanRT avatar Nov 27 '24 10:11 LuanRT

How do I use cookies?, I used cookies before but I have to change my cookies frequently, is there a way to solve that?

And about this; get your cookies from an incognito tab. If you extract it from a normal session, YouTube will eventually rotate it when you open the website again and invalidate your old cookies. Sign in, get them, and then close it immediately.

LuanRT avatar Nov 27 '24 14:11 LuanRT

How do I use cookies?, I used cookies before but I have to change my cookies frequently, is there a way to solve that?

And about this; get your cookies from an incognito tab. If you extract it from a normal session, YouTube will eventually rotate it when you open the website again and invalidate your old cookies. Sign in, get them, and then close it immediately.

I second this. The cookie I obtained early last week is still working today :)

patrickkfkan avatar Nov 27 '24 15:11 patrickkfkan