'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