'Python - youtube-dl force login everytime
I want to download multiple files using youtube-dl from a site the needs login.
The issue that I have is that youtube-dl is login for the first video with no issue, but doesn't login again for next video.
How do I force youtube-dl to login for each video, every time the function is called ? Maybe reset,stop youtube-dl every time.
def video_download(path, url):
ydl = youtube_dl.YoutubeDL(
{
'outtmpl': path + '.mp4',
'format': 'bestvideo+bestaudio/best',
'username': email,
'password': password,
# 'quiet': True
})
with ydl:
ydl.download([url])
time.sleep(45)
The function is actually called in a loop, because I set outtmpl for each file/video.
Different instances, the first one is working, the next don't login again. I need every time the login to repeat.
<youtube_dl.YoutubeDL.YoutubeDL object at 0x0000000004E74C18>
<youtube_dl.YoutubeDL.YoutubeDL object at 0x00000000032BED68>
WARNING: Unable to download kaltura session JSON: HTTP Error 401: UNAUTHORIZED
<youtube_dl.YoutubeDL.YoutubeDL object at 0x0000000004D6D898>
WARNING: Unable to download kaltura session JSON: HTTP Error 401: UNAUTHORIZED
Terminal/Output:
<youtube_dl.YoutubeDL.YoutubeDL object at 0x00000000050E4C18>
**[safari] Downloading login form
[safari] Login successful**
[safari] 9781787283664/video1_1: Downloading webpage
.............................
<youtube_dl.YoutubeDL.YoutubeDL object at 0x000000000337DD68>
[safari] 9781787283664/video1_2: Downloading webpage
[safari] 9781787283664/video1_2: Downloading kaltura session JSON
WARNING: Unable to download kaltura session JSON: HTTP Error 401: UNAUTHORIZED
---- Update ---
I tried to use command line but I have the following error, which is not appearing if I use the python import:
ERROR: fixed output name but more than one file to download
The cmd:
youtube-dl -u username_paceholder -p password_paceholder -o 'D:\DevProj\DownloadCourses\Safari\x_downloads\Django1 \_01_Django ABC' https://www.site_placeholder.com/library/view/django-example/9781787283664/video1_2.html
Solution 1:[1]
Why not use the command-line ?
You can personalize the filename and folder location - and you will be sure that authentication will be done each time you run youtube-dl command (if -u and -p arguments are given)
Try something like:
import os
def video_download(path="c:\\mydir\\myfile", url="http://myvideo./url"):
#user information
user="myuser"
pwd="mypwd"
#build cmd line
cmd="youtube-dl -u "+user+" -p "+pwd+' -o "'+path+'" '+url
#execute commande line
os.system(cmd)
[...]
Solution 2:[2]
I'm assuming that since you want multiple videos, your URL argument will be in the form of a list such as ['url1', 'url2', 'url3']. If that is the case you should be able to loop over each element with a for loop, and call the download function on each element.
def video_download(path, url):
ydl = youtube_dl.YoutubeDL(
{
'outtmpl': path + '.mp4',
'format': 'bestvideo+bestaudio/best',
'username': email,
'password': password,
'cachedir': False,
'noplaylist': True
# 'quiet': True
})
for i in url:
ydl.download(i)
There is also a command-line version of this tool which I use and it is very handy.
Solution 3:[3]
The same happened with me too. So I searched for it and found that in the yt_dlp.excractor.instagram.InstagramBaseIE class the _login function sets _IS_LOGGED_IN to True for the class which then remains True for all instances created after the first login. See this:
NOTE: I am using yt_dlp over here as the solution is diff for youtubedl. Also yt_dlp is more updated than youtubedl. Also only found it for instagram
class InstagramBaseIE(InfoExtractor):
_NETRC_MACHINE = 'instagram'
_IS_LOGGED_IN = False
def _login(self):
username, password = self._get_login_info()
if username is None or self._IS_LOGGED_IN:
return
login_webpage = self._download_webpage(
'https://www.instagram.com/accounts/login/', None,
note='Downloading login webpage', errnote='Failed to download login webpage')
shared_data = self._parse_json(
self._search_regex(
r'window\._sharedData\s*=\s*({.+?});',
login_webpage, 'shared data', default='{}'),
None)
login = self._download_json('https://www.instagram.com/accounts/login/ajax/', None, note='Logging in', headers={
'Accept': '*/*',
'X-IG-App-ID': '936619743392459',
'X-ASBD-ID': '198387',
'X-IG-WWW-Claim': '0',
'X-Requested-With': 'XMLHttpRequest',
'X-CSRFToken': shared_data['config']['csrf_token'],
'X-Instagram-AJAX': shared_data['rollout_hash'],
'Referer': 'https://www.instagram.com/',
}, data=urlencode_postdata({
'enc_password': f'#PWD_INSTAGRAM_BROWSER:0:{int(time.time())}:{password}',
'username': username,
'queryParams': '{}',
'optIntoOneTap': 'false',
'stopDeletionNonce': '',
'trustedDeviceRecords': '{}',
}))
if not login.get('authenticated'):
if login.get('message'):
raise ExtractorError(f'Unable to login: {login["message"]}')
elif login.get('user'):
raise ExtractorError('Unable to login: Sorry, your password was incorrect. Please double-check your password.', expected=True)
elif login.get('user') is False:
raise ExtractorError('Unable to login: The username you entered doesn\'t belong to an account. Please check your username and try again.', expected=True)
raise ExtractorError('Unable to login')
InstagramBaseIE._IS_LOGGED_IN = True
In the last line you can clearly see that True is set for _IS_LOGGED_IN as a class variable. So to fix this issue i have a hack, just set this value to False after each extraction(for you its loop). See the working code:
from yt_dlp import YoutubeDL
from yt_dlp.extractor.instagram import InstagramBaseIE
def video_download(path, url):
ytops = {
'outtmpl': path + '.mp4',
'format': 'bestvideo+bestaudio/best',
'username': email,
'password': password
}
with YoutubeDL(ytops) as ydl:
ydl.download(url)
# the hack
InstagramBaseIE._IS_LOGGED_IN = False
time.sleep(45)
I hope it will work now. I will make a issue about it on their repo so that it can soon be patched.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | J'e |
| Solution 3 |
