node-ytdl-core
node-ytdl-core copied to clipboard
MinigetError: Status code: 403
I run on the local successfully but I got this error when run on the firebase function cloud.
version: "axios": "^1.2.0", "ytdl-core": "^4.11.5"
I have faces the same problem , I got this error when run on the server.
Is there any update
on dev it works fine, but on prod it breaks, Is there any solution ?
I ended up looking at yt-dlp to figure out why they do not get 403'd. I also needed to use fetch (which is built-in, now, and needed in places like cloudflare workers) instead of a http-lib. This javascript code works, without any deps:
export async function getInfo (videoId) {
// hard-coded from https://github.com/yt-dlp/yt-dlp/blob/master/yt_dlp/extractor/youtube.py
const apiKey = 'AIzaSyB-63vPrdThhKuerbB2N_l7Kwwcxj6yUAc'
const headers = {
'X-YouTube-Client-Name': '5',
'X-YouTube-Client-Version': '19.09.3',
Origin: 'https://www.youtube.com',
'User-Agent': 'com.google.ios.youtube/19.09.3 (iPhone14,3; U; CPU iOS 15_6 like Mac OS X)',
'content-type': 'application/json'
}
const b = {
context: {
client: {
clientName: 'IOS',
clientVersion: '19.09.3',
deviceModel: 'iPhone14,3',
userAgent: 'com.google.ios.youtube/19.09.3 (iPhone14,3; U; CPU iOS 15_6 like Mac OS X)',
hl: 'en',
timeZone: 'UTC',
utcOffsetMinutes: 0
}
},
videoId,
playbackContext: { contentPlaybackContext: { html5Preference: 'HTML5_PREF_WANTS' } },
contentCheckOk: true,
racyCheckOk: true
}
return fetch(`https://www.youtube.com/youtubei/v1/player?key${apiKey}&prettyPrint=false`, { method: 'POST', body: JSON.stringify(b), headers }).then(r => r.json())
}
Working URLs are in streamingData.adaptiveFormats. Here is usage-example:
import { getInfo } from './yt.js'
import { writeFile } from 'fs/promises'
const info = await getInfo('C0DPdy98e4c')
const video = info.streamingData.adaptiveFormats.find(f => f.mimeType.includes('video/mp4'))
await writeFile('test.mp4', await fetch(video.url).then(async r => new Uint8Array(await r.arrayBuffer())))
I ended up looking at yt-dlp to figure out why they do not get 403'd. I also needed to use
fetch(which is built-in, now, and needed in places like cloudflare workers) instead of a http-lib. This javascript code works, without any deps:export async function getInfo (videoId) { // hard-coded from https://github.com/yt-dlp/yt-dlp/blob/master/yt_dlp/extractor/youtube.py const apiKey = 'AIzaSyB-63vPrdThhKuerbB2N_l7Kwwcxj6yUAc' const headers = { 'X-YouTube-Client-Name': '5', 'X-YouTube-Client-Version': '19.09.3', Origin: 'https://www.youtube.com', 'User-Agent': 'com.google.ios.youtube/19.09.3 (iPhone14,3; U; CPU iOS 15_6 like Mac OS X)', 'content-type': 'application/json' } const b = { context: { client: { clientName: 'IOS', clientVersion: '19.09.3', deviceModel: 'iPhone14,3', userAgent: 'com.google.ios.youtube/19.09.3 (iPhone14,3; U; CPU iOS 15_6 like Mac OS X)', hl: 'en', timeZone: 'UTC', utcOffsetMinutes: 0 } }, videoId, playbackContext: { contentPlaybackContext: { html5Preference: 'HTML5_PREF_WANTS' } }, contentCheckOk: true, racyCheckOk: true } return fetch(`https://www.youtube.com/youtubei/v1/player?key${apiKey}&prettyPrint=false`, { method: 'POST', body: JSON.stringify(b), headers }).then(r => r.json()) }Working URLs are in
streamingData.adaptiveFormats. Here is usage-example:import { getInfo } from './yt.js' import { writeFile } from 'fs/promises' const info = await getInfo('C0DPdy98e4c') const video = info.streamingData.adaptiveFormats.find(f => f.mimeType.includes('video/mp4')) await writeFile('test.mp4', await fetch(video.url).then(async r => new Uint8Array(await r.arrayBuffer())))
The video from stream url has no audio output. Appears to be muted in the video player and there's no way to unmute it!
The video from stream url has no audio output. Appears to be muted in the video player and there's no way to unmute it!
@makanakidev yeh, it seems to separate them. I didn't notice because my test-video is silent. It does provide audio as well, though.
This is a complete download CLI (that can also be used as library for info) that grabs the first audio & video for a format (hd1080|hd720|large|medium|small|tiny) and merges them, including progress bars and stuff. I recommend looking at how it works and customizing it to your needs.
It's also published at @konsumer/ytdownload.
Hi everyone,
Is there a way yet to retrieve videos with audio included, similar to how it happens when sending the request with:
"context": {
"client": {
"clientName": "ANDROID_TESTSUITE",
"clientVersion": "1.9"
}
}
but being able to obtain different qualities of videos with audio included? Any guidance or updates on this would be greatly appreciated.
Thank you!
@elvismdev see above. I am doing that. You need to merge the 2 streams.
this is unusable, it works insanely slow
I ended up looking at yt-dlp to figure out why they do not get 403'd. I also needed to use
fetch(which is built-in, now, and needed in places like cloudflare workers) instead of a http-lib. This javascript code works, without any deps:export async function getInfo (videoId) { // hard-coded from https://github.com/yt-dlp/yt-dlp/blob/master/yt_dlp/extractor/youtube.py const apiKey = 'AIzaSyB-63vPrdThhKuerbB2N_l7Kwwcxj6yUAc' const headers = { 'X-YouTube-Client-Name': '5', 'X-YouTube-Client-Version': '19.09.3', Origin: 'https://www.youtube.com', 'User-Agent': 'com.google.ios.youtube/19.09.3 (iPhone14,3; U; CPU iOS 15_6 like Mac OS X)', 'content-type': 'application/json' } const b = { context: { client: { clientName: 'IOS', clientVersion: '19.09.3', deviceModel: 'iPhone14,3', userAgent: 'com.google.ios.youtube/19.09.3 (iPhone14,3; U; CPU iOS 15_6 like Mac OS X)', hl: 'en', timeZone: 'UTC', utcOffsetMinutes: 0 } }, videoId, playbackContext: { contentPlaybackContext: { html5Preference: 'HTML5_PREF_WANTS' } }, contentCheckOk: true, racyCheckOk: true } return fetch(`https://www.youtube.com/youtubei/v1/player?key${apiKey}&prettyPrint=false`, { method: 'POST', body: JSON.stringify(b), headers }).then(r => r.json()) }Working URLs are in
streamingData.adaptiveFormats. Here is usage-example:import { getInfo } from './yt.js' import { writeFile } from 'fs/promises' const info = await getInfo('C0DPdy98e4c') const video = info.streamingData.adaptiveFormats.find(f => f.mimeType.includes('video/mp4')) await writeFile('test.mp4', await fetch(video.url).then(async r => new Uint8Array(await r.arrayBuffer())))The video from stream url has no audio output. Appears to be muted in the video player and there's no way to unmute it!
this is unusable, it works insanely slow
@Piliponful It seems reasonably fast to me, but feel free to write it another way. This is a proof-of-concept. My method is the only working way to get video URLs from youtube, that I know of. If you figure it out, let the rest of us know.
MinigetError: Status code: 403
at ClientRequest.
i use distubejs/ytdl-core library while waiting this library fix this bug, and it work fine. Btw you guys can check this quick fix https://github.com/fent/node-ytdl-core/issues/1301#issuecomment-2223004197
import ytdl from "@distube/ytdl-core";
I ended up looking at yt-dlp to figure out why they do not get 403'd. I also needed to use
fetch(which is built-in, now, and needed in places like cloudflare workers) instead of a http-lib. This javascript code works, without any deps:export async function getInfo (videoId) { // hard-coded from https://github.com/yt-dlp/yt-dlp/blob/master/yt_dlp/extractor/youtube.py const apiKey = 'AIzaSyB-63vPrdThhKuerbB2N_l7Kwwcxj6yUAc'
const headers = { 'X-YouTube-Client-Name': '5', 'X-YouTube-Client-Version': '19.09.3', Origin: 'https://www.youtube.com', 'User-Agent': 'com.google.ios.youtube/19.09.3 (iPhone14,3; U; CPU iOS 15_6 like Mac OS X)', 'content-type': 'application/json' }
const b = { context: { client: { clientName: 'IOS', clientVersion: '19.09.3', deviceModel: 'iPhone14,3', userAgent: 'com.google.ios.youtube/19.09.3 (iPhone14,3; U; CPU iOS 15_6 like Mac OS X)', hl: 'en', timeZone: 'UTC', utcOffsetMinutes: 0 } }, videoId, playbackContext: { contentPlaybackContext: { html5Preference: 'HTML5_PREF_WANTS' } }, contentCheckOk: true, racyCheckOk: true }
return fetch(
https://www.youtube.com/youtubei/v1/player?key${apiKey}&prettyPrint=false, { method: 'POST', body: JSON.stringify(b), headers }).then(r => r.json()) } Working URLs are instreamingData.adaptiveFormats. Here is usage-example:import { getInfo } from './yt.js' import { writeFile } from 'fs/promises'
const info = await getInfo('C0DPdy98e4c') const video = info.streamingData.adaptiveFormats.find(f => f.mimeType.includes('video/mp4')) await writeFile('test.mp4', await fetch(video.url).then(async r => new Uint8Array(await r.arrayBuffer())))
This doesnt work anymore, does it?
I ended up looking at yt-dlp to figure out why they do not get 403'd. I also needed to use
fetch(which is built-in, now, and needed in places like cloudflare workers) instead of a http-lib. This javascript code works, without any deps: export async function getInfo (videoId) { // hard-coded from https://github.com/yt-dlp/yt-dlp/blob/master/yt_dlp/extractor/youtube.py const apiKey = 'AIzaSyB-63vPrdThhKuerbB2N_l7Kwwcxj6yUAc' const headers = { 'X-YouTube-Client-Name': '5', 'X-YouTube-Client-Version': '19.09.3', Origin: 'https://www.youtube.com', 'User-Agent': 'com.google.ios.youtube/19.09.3 (iPhone14,3; U; CPU iOS 15_6 like Mac OS X)', 'content-type': 'application/json' } const b = { context: { client: { clientName: 'IOS', clientVersion: '19.09.3', deviceModel: 'iPhone14,3', userAgent: 'com.google.ios.youtube/19.09.3 (iPhone14,3; U; CPU iOS 15_6 like Mac OS X)', hl: 'en', timeZone: 'UTC', utcOffsetMinutes: 0 } }, videoId, playbackContext: { contentPlaybackContext: { html5Preference: 'HTML5_PREF_WANTS' } }, contentCheckOk: true, racyCheckOk: true } return fetch(https://www.youtube.com/youtubei/v1/player?key${apiKey}&prettyPrint=false, { method: 'POST', body: JSON.stringify(b), headers }).then(r => r.json()) } Working URLs are instreamingData.adaptiveFormats. Here is usage-example: import { getInfo } from './yt.js' import { writeFile } from 'fs/promises' const info = await getInfo('C0DPdy98e4c') const video = info.streamingData.adaptiveFormats.find(f => f.mimeType.includes('video/mp4')) await writeFile('test.mp4', await fetch(video.url).then(async r => new Uint8Array(await r.arrayBuffer())))This doesnt work anymore, does it?
Doesn't work. I get,
status: 'LOGIN_REQUIRED',
reason: 'Sign in to confirm you’re not a bot',