Reputation: 173
I made a simple 3 line project with pyTube library. All it does is download a video from YT. With it I usually download videos of handball games which are around 100 minutes long. It all worked fine 7 days ago when i last used it but now it throws an "HTTP Error 400: Bad Request" error.
from pytube import YouTube
youtubeObject = YouTube('https://www.youtube.com/watch?v=DASMWPUFFP4')
youtubeObject = youtubeObject.streams.get_highest_resolution()
youtubeObject.download('D:\\Utakmice')
It works with a shorter videos but it doesnt work with any other videos of the similar length (~100mins). I tried upgrading pyTube library and cleaning browser cache but it didnt help. Tried to dig dipper into the urllib but couldnt find anything there either. The error I am getting is:
urllib.error.HTTPError: HTTP Error 400: Bad Request
Couldnt find any solution online so any help is appreciated. Thanks in advance.
I found an issue about this on the pytube GitHub. The fix requiered the change of certain client versions in innertube.py file. The link to the issue: https://github.com/pytube/pytube/issues/1894#issue-2180600881
Upvotes: 16
Views: 32206
Reputation: 1
!pip install yt_dlp
import yt_dlp
ydl_opts = {}
def dwl_vid(video_url):
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
ydl.download([video_url])
channel = 1
while channel == 1:
link_of_the_video = input("Copy & paste the URL of the YouTube video you want to download: ")
zxt = link_of_the_video.strip()
dwl_vid(zxt)
channel = int(input("Enter 1 if you want to download more videos\nEnter 0 if you are done: "))
Upvotes: 0
Reputation: 1
pip install tk --upgrade
pip install ctk --upgrade
pip install pytube --upgrade
pip install customtkinter --upgrade
pip install pytubefix --upgrade
import tkinter as tk
import customtkinter as ctk
from pytubefix import YouTube
from pytubefix.cli import on_progress
def download_video():
try:
yt_link = url_var.get()
yt_object = YouTube(yt_link, on_progress_callback = on_progress)
video = yt_object.streams.get_highest_resolution()
video.download()
print("Download Complete")
except Exception as e:
print(f"Invalid link{e}")
ctk.set_appearance_mode("System")
ctk.set_default_color_theme("blue")
app = ctk.CTk()
app.geometry("720x480")
app.title("YouTube Download")
url_var = tk.StringVar()
title = ctk.CTkLabel(app, text="Insert a YouTube link")
title.pack(padx=10, pady=10)
link = ctk.CTkEntry(app, width=350, height=40, textvariable=url_var)
link.pack()
download = ctk.CTkButton(app, text="Download", command=download_video)
download.pack()
app.mainloop()
Upvotes: -1
Reputation: 455
I tried this and it worked fine for me
pip install pytubefix
from pytubefix import YouTube
from pytubefix.cli import on_progress
url = "url"
yt = YouTube(url, on_progress_callback = on_progress)
print(yt.title)
ys = yt.streams.get_highest_resolution()
ys.download()
#This is a link to the library. https://pypi.org/project/pytubefix/
Upvotes: 13
Reputation: 323
This is a recent issue that has been raised in the Pytube project: issue link
In the meantime, you can use a new package as suggested by Tomtunn. It serves a similar purpose named pytubefix
I hope this solves your issue
Upvotes: 13
Reputation: 11
I got the same issue and I fixed it by changing this line from innertube.py:
def __init__(self, client='ANDROID', use_oauth=False, allow_cache=True):
to this:
def __init__(self, client='WEB', use_oauth=False, allow_cache=True):
Upvotes: 1
Reputation: 21
File "/var/www/html/ytd_web_app/venv/lib/python3.10/site-packages/flask/app.py", line 2213, in __call__
return self.wsgi_app(environ, start_response)
File "/var/www/html/ytd_web_app/venv/lib/python3.10/site-packages/flask/app.py", line 2193, in wsgi_app
response = self.handle_exception(e)
File "/var/www/html/ytd_web_app/venv/lib/python3.10/site-packages/flask/app.py", line 2190, in wsgi_app
response = self.full_dispatch_request()
File "/var/www/html/ytd_web_app/venv/lib/python3.10/site-packages/flask/app.py", line 1486, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/var/www/html/ytd_web_app/venv/lib/python3.10/site-packages/flask/app.py", line 1484, in full_dispatch_request
rv = self.dispatch_request()
File "/var/www/html/ytd_web_app/venv/lib/python3.10/site-packages/flask/app.py", line 1469, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
File "/var/www/html/ytd_web_app/Routes/Media.py", line 90, in getMedia
file = getMetaData(file_name)
File "/var/www/html/ytd_web_app/Routes/Media.py", line 43, in getMetaData
response = json.dumps(media.verifyPlatform(), indent=4)
File "/var/www/html/ytd_web_app/Models/Media.py", line 164, in verifyPlatform
"data": self.handleYouTube()
File "/var/www/html/ytd_web_app/Models/Media.py", line 227, in handleYouTube
youtube = self._YouTubeDownloader.search()
File "/var/www/html/ytd_web_app/Models/YouTubeDownloader.py", line 297, in search
"author_channel": self.getVideo().channel_url,
File "/var/www/html/ytd_web_app/venv/lib/python3.10/site-packages/pytube/__main__.py", line 432, in channel_url
return f'https://www.youtube.com/channel/{self.channel_id}'
File "/var/www/html/ytd_web_app/venv/lib/python3.10/site-packages/pytube/__main__.py", line 424, in channel_id
return self.vid_info.get('videoDetails', {}).get('channelId', None)
File "/var/www/html/ytd_web_app/venv/lib/python3.10/site-packages/pytube/__main__.py", line 246, in vid_info
innertube_response = innertube.player(self.video_id)
File "/var/www/html/ytd_web_app/venv/lib/python3.10/site-packages/pytube/innertube.py", line 448, in player
return self._call_api(endpoint, query, self.base_data)
File "/var/www/html/ytd_web_app/venv/lib/python3.10/site-packages/pytube/innertube.py", line 390, in _call_api
response = request._execute_request(
File "/var/www/html/ytd_web_app/venv/lib/python3.10/site-packages/pytube/request.py", line 37, in _execute_request
return urlopen(request, timeout=timeout) # nosec
File "/usr/lib/python3.10/urllib/request.py", line 216, in urlopen
return opener.open(url, data, timeout)
File "/usr/lib/python3.10/urllib/request.py", line 525, in open
response = meth(req, response)
File "/usr/lib/python3.10/urllib/request.py", line 634, in http_response
response = self.parent.error(
File "/usr/lib/python3.10/urllib/request.py", line 563, in error
return self._call_chain(*args)
File "/usr/lib/python3.10/urllib/request.py", line 496, in _call_chain
result = func(*args)
File "/usr/lib/python3.10/urllib/request.py", line 643, in http_error_default
raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 400: Bad Request
Moreover, the error is generated as a client-side error given that the request is a POST request as when it is further and research and analysis is done it is found that PyTube is using the version 1.0 given that the YouTube's API as the latest version for that API is 3.0.
def _execute_request(
url: str,
method: str | None = None,
headers: dict[str, str] | None = None,
data: bytes | None = None,
timeout: float = socket._GLOBAL_DEFAULT_TIMEOUT
) -> _UrlopenRet:
"""
Executing the request from the PyTube's API towards the
YouTube API endpoint to retrieve the Stream's data.
Parameters:
url: string: The uniform resource locator of the API endpoint.
method: string: The HTTP request method to be used.
headers: object: The HTTP headers to be used by the API.
data: bytes: The data to be passed into the request.
timeout: float: The timeout delay to close the connection.
Returns:
_UrlopenRet
"""
base_headers = {"User-Agent": "Mozilla/5.0", "accept-language": "en-US,en"}
if headers:
base_headers.update(headers)
if data:
if not isinstance(data, bytes):
data = bytes(json.dumps(data), encoding="utf-8")
if url.lower().startswith("http"):
request = Request(url, headers=base_headers, method=method, data=data)
else:
raise ValueError("Invalid URL")
return urlopen(request, timeout=timeout)
def _call_api(self, endpoint: str, query: list[str], data: bytes):
"""
Generating the request to a given endpoint withe the
provided query parameters and data.
Parameters:
endpoint: string: The uniform resource locator of the endpoint to the YouTube's API.
query: array: The HTTP query to be sent to the API.
data: bytes: The data to be passed into the request.
"""
if self.use_oauth:
del query['key']
endpoint_url = f'{endpoint}?{parse.urlencode(query)}'
headers = {
'Content-Type': 'application/json',
}
if self.use_oauth:
if self.access_token:
self.refresh_bearer_token()
headers['Authorization'] = f'Bearer {self.access_token}'
else:
self.fetch_bearer_token()
headers['Authorization'] = f'Bearer {self.access_token}'
headers.update(self.header)
response = request._execute_request(
endpoint_url,
'POST',
headers=headers,
data=data
)
return json.loads(response.read())
def player(self, video_id: str) -> dict:
"""
Making the request to the player endpoint.
Parameters:
video_id: string: The identifier of the video to get the player data for.
Returns:
object
"""
endpoint = f'{self.base_url}/player'
query = {
'videoId': video_id,
}
query.update(self.base_params)
return self._call_api(endpoint, query, self.base_data)
@property
def base_url(self) -> str:
"""
Returning the base uniform resource locator endpoint for the
InnerTube API.
Returns:
string
"""
return 'https://www.youtube.com/youtubei/v1'
Upvotes: 2