5
votes

I am trying to make a YouTube video downloader using Python pytube3 but it doesn't download all the videos. Some videos download very easily but some videos won't download and instead of download it shows error:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\tarun\PycharmProjects\YTDownloader\venv\lib\site-packages\pytube\extract.py", line 297, in apply_descrambler
    for format_item in formats
  File "C:\Users\tarun\PycharmProjects\YTDownloader\venv\lib\site-packages\pytube\extract.py", line 297, in <listcomp>
    for format_item in formats
KeyError: 'url'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\tarun\AppData\Local\Programs\Python\Python37-32\lib\tkinter\__init__.py", line 1705, in __call__
    return self.func(*args)
  File "C:/Users/tarun/PycharmProjects/YTDownloader/YTD.py", line 15, in video_download
    my_video = YouTube(input_user)
  File "C:\Users\tarun\PycharmProjects\YTDownloader\venv\lib\site-packages\pytube\__main__.py", line 92, in __init__
    self.descramble()
  File "C:\Users\tarun\PycharmProjects\YTDownloader\venv\lib\site-packages\pytube\__main__.py", line 132, in descramble
    apply_descrambler(self.player_config_args, fmt)
  File "C:\Users\tarun\PycharmProjects\YTDownloader\venv\lib\site-packages\pytube\extract.py", line 301, in apply_descrambler
    parse_qs(formats[i]["cipher"]) for i, data in enumerate(formats)
  File "C:\Users\tarun\PycharmProjects\YTDownloader\venv\lib\site-packages\pytube\extract.py", line 301, in <listcomp>
    parse_qs(formats[i]["cipher"]) for i, data in enumerate(formats)
KeyError: 'cipher'
5
Welcome to stackoverflow. Can you provide the code that is triggering the download? - Nico Müller
Kindly share the code. - droid_31

5 Answers

12
votes

This is an error in the file extract.py from pytube.

  1. Go to the location where the package was installed. If you don't know where, run the command

    pip show pytube3
    

    And it'll give you something like this:

pip show package

We can see Location: c:\users\tiago\anaconda3\lib\site-packages.

  1. Go to that location, open the folder pytube and the file extract.py

pythube location

  1. In the file, line no. 306 or 301, you will find parse_qs(formats[i]["cipher"]). If yes, then change "cipher" to "signatureCipher" (make sure 'C' is capital).

    So, you'll initially have

     cipher_url = [
                     parse_qs(formats[i]["cipher"]) for i, data in enumerate(formats)
                 ]
    

    but it should be

     cipher_url = [
                     parse_qs(formats[i]["signatureCipher"]) for i, data in enumerate(formats)
                 ]
    

pytube extract cypher error fixed

  1. Run the following script to see it working

     # -*- coding: utf-8 -*-
     """
     Created on Mon Jun 15 12:21:49 2020
    
     @author: tiago
     """
     from pytube import YouTube
    
     video_url = "https://youtu.be/gp5tziO5lXg" # YouTube video URL
     youtube = YouTube(video_url)
     video = youtube.streams.first()
     video.download("C:/Users/tiago/Desktop/videos/") # Path where to store the video
    

You'll then see the video downloaded in that folder

How to download video from YouTube in Python

1
votes
  1. Just go to the pytube\extract.py (in pytube library) file. The path of file will be (in Windows): C:\ProgramData\Anaconda3\lib\site-packages\pytube\extract.py

  2. Open extract.py file and search for line:

    parse_qs(formats[i]["cipher"]) for i, data in enumerate(formats)

  3. Now replace 'cipher' with 'signatureCipher'.

  4. Save it.

  5. Now run your code again

0
votes

This is a problem with pytube3, I believe as of now they have not submitted a fix yet. Here is the link to the issue on github

0
votes

In case you are getting error as Keyerror:"cipher", then go to location of pytube open extract.py and on line no.301 you will get this

cipher_url = [
                parse_qs(formats[i]["Cipher"]) for i, data in enumerate(formats)
            ]

now edit this line to this

cipher_url = [
                parse_qs(formats[i]["signatureCipher"]) for i, data in enumerate(formats)
            ]

save the changes and....Boom you are done. now try downloading the video you won't get any error now.

-1
votes

in pytube library ,there is a extract.py file in this file change the cipher to signaturecipher