pytube: [BUG] 'NoneType' object has no attribute 'span'
arr = yt.streams.filter(only_video=True, file_extension='mp4')
line 292, in streams
return StreamQuery(self.fmt_streams)
File "...\Python39\lib\site-packages\pytube\__main__.py", line 177, in fmt_streams
extract.apply_signature(stream_manifest, self.vid_info, self.js)
File "...\Python39\lib\site-packages\pytube\extract.py", line 409, in apply_signature
cipher = Cipher(js=js)
File "...\Python39\lib\site-packages\pytube\cipher.py", line 44, in __init__
self.throttling_array = get_throttling_function_array(js)
File "...\Python39\lib\site-packages\pytube\cipher.py", line 323, in get_throttling_function_array
str_array = throttling_array_split(array_raw)
File "...\Python39\lib\site-packages\pytube\parser.py", line 158, in throttling_array_split
match_start, match_end = match.span()
AttributeError: 'NoneType' object has no attribute 'span'
Pytube version: 11.0.1
Python 3.9.7
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Reactions: 15
- Comments: 53 (2 by maintainers)
Please re open this issue, I encountered the same error
seems to happen, because YouTube added functions without parameters in the javascript. e.g.:
So in my opinion the best fix would be to allow the regex to accept these too. That is, change the regex
function\([^)]+\)
tofunction\([^)]*\)
. The*
allows the function to have no parameters.So https://github.com/pytube/pytube/blob/f06e0710dcf5089e582487fee94f7bb0afbf7ba9/pytube/parser.py#L152 should be changed to
Any opinion about that?
Literally yesterday everything worked, but today it gives this error.
I have create a pull request to fix this error. checkout here https://github.com/pytube/pytube/pull/1166
11.0.2 is the latest right? I am having the same issue on that version.
Please update to the latest version.
I implemented this in my environment and it works! Hopefully we can get it merged into master. Thanks for posting this.
there is a writing error in the line from @Reaperswag this is the correct line to change line 268 in cipher.py:
r'([A-Za-z]{3})=function\(a\){var b=a\.split\(""\)\,'
here’s what worked for me, courtesy of czarnoff (although glubsy is correct that this is a temporary workaround). Hopefully it will last until an update can be released that lets removes this vulnerability.
"I think the javascipt changed. If you search for Bpa, you don’t find a function. Instead you get
var Bpa=[iha];g.k=Jz.prototype;g.k.GC=function(a){this.segments.push(a)}; Thus Bpa is an array with the function “iha” in location zero . If you use iha for the name, you get a function. I kludged line 293 of cipher.py to go from
name = re.escape(get_throttling_function_name(js)) to
name = “iha” And I now its working.
I’m not sure how to correctly change the code yet, but if I figure out a proper patch I’ll post it."
comment from @seekwest
I tried pytube today and I still get the error stating that
NoneType object has no attribute Span
Happening here as well. I reckon it’s probably because Youtube changed something on their end just now and it’s caused pytube to stop working. I don’t know, but I think pytube is essentially a battle between a community trying to develop ways to download vs the Youtube devs who are trying to stop the downloading of videos.
I made an EXE of my project about 2 days ago and that doesn’t work anymore, so it definitely isn’t any code that any of us have changed that caused the issues, it’s to do with pytube.
I summarize:
If your are using the latest version pytube: 11.0.2 the fix: old:
func_regex = re.compile(r"function([^)]+)")
new:
func_regex = re.compile(r"function([^)]*)")
in pytube/pytube/parser.py Line 152 is already INCLUDED!
So update to pytube: 11.0.2 if you havent done it yet.
If you already changed line 293 of pytube/pytube/cipher.py old:
name = re.escape(get_throttling_function_name(js))
to new:name = "iha"
change it back to:
name = re.escape(get_throttling_function_name(js))
Just change line 268 in pytube/pytube/cipher.py: old:
r'a\.[A-Z]&&\(b=a\.get\("n"\)\)&&\(b=([^(]+)\(b\)',
to new:
r'([A-Za-z]{3})=function\(a\){var b=a\.split\(""\)\,'
pay attention that the code is correct and the special characters are correct encoded/masked!! WRONG:
r'([A-Za-z]{3})=function(a){var b=a.split(""),'
RIGHT:
r'([A-Za-z]{3})=function\(a\){var b=a\.split\(""\)\,'
That should work, i downloaded 3.000 Videos from Youtube yesterday with these settings.
regards Chris
Hello! I just want to tell You, that I’ve implemented @seekwest solution for cipher.py from 2022-02-09:
there is a writing error in the line from @Reaperswag this is the correct line to change line 268 in cipher.py: r’([A-Za-z]{3})=function(a){var b=a.split(“”),’
and alexeichhorn solution for parser.py from 2021-11-22:
seems to happen, because YouTube added functions without parameters in the javascript. e.g.:
function(){for(var d=64,e=[];++d-e.length-32;){switch(d){case 58:d-=14;case 91:case 92:case 93:continue;case 123:d=47;case 94:case 95:case 96:continue;case 46:d=95}e.push(String.fromCharCode(d))}return e} So in my opinion the best fix would be to allow the regex to accept these too. That is, change the regex function([^)]+) to function([^)]*). The * allows the function to have no parameters.
So
pytube/pytube/parser.py
Line 152 in f06e071
func_regex = re.compile(r"function([^)]+)")
should be changed to func_regex = re.compile(r"function([^)]*)") Any opinion about that?
It worked! I’m useing pytube version of 11.0.2
Thanks for sharing , it worked, kudos to you! @mytja
True
I was trying to fix the bug before I found this pull request. It hasn’t been approved/merged yet but when I tried that change in my code, it worked.
In Cipher.py, line 411:
transform_plan_raw = find_object_from_startpoint(raw_code, match.span()[1] - 1)
Change it to:transform_plan_raw = js
I don’t know when this pull request will get merged into the main module, but for anyone facing this problem, you can try doing the above changes.
Okay, I also faced this problem lately and maybe at least could get a step ahead. In
Cipher.py
, at line 401,transform_start = r"try{" plan_regex = re.compile(transform_start) match = plan_regex.search(raw_code)
In the above code snippet, the
match
object is defined as the regex matches ofplan_regex
(which isr"try{"
) found in theraw_code
object. However, when I tried to get what theraw_code
object actually returns, I got this value:mma=function(a){var b=a.split(""),c=[1298660008,function(d,e,f,h,l,m){return e(h,l,m)},968655468,function(){for(var d=64,e=[];++d-e.length-32;)switch(d){case 46:d=95;default:e.push(String.fromCharCode(d));case 94:case 95:case 96:break;case 123:d-=76;case 92:case 93:continue;case 58:d=44;case 91:}return e},56115230,-578061081,-516346513,b,-1739695292,-1031455761,/[,\]],[\]];}
.As you can notice, there is not a single mention of
try{
here, hence when theplan_regex.search
method is called forraw_code
, it finds no matches and returnNone
. Therefore, while seeking for thespan
attribute ofmatch
object, it raises the Error:AttributeError: 'NoneType' object has no attribute 'span'
.This could be caused due to a recent change in YouTube’s code (which is not new, I’ve faced such bugs in the past year a couple of times as well. It broke my app that is based on this module, now I’m thinking shifting to yt-dlp for my app).
I might be wrong about it since I’m not a professional programmer and my theory might prove wrong, but this is the best explanation I could give as for now. I don’t know what the
search
method was supposed to find in the original code so I don’t think I can find a direct fix for now, however I’m working on it.pytube 12.1.2 Python 3.7.6
Traceback (most recent call last): File “F:\PyCharm Community Edition 2022.3.1\Robin2bin_Youtube\test.py”, line 4, in <module> print(link.streams.all()) File “C:\Users\User\AppData\Local\Programs\Python\Python37\lib\site-packages\pytube_main_.py”, line 296, in streams return StreamQuery(self.fmt_streams) File “C:\Users\User\AppData\Local\Programs\Python\Python37\lib\site-packages\pytube_main_.py”, line 181, in fmt_streams extract.apply_signature(stream_manifest, self.vid_info, self.js) File “C:\Users\User\AppData\Local\Programs\Python\Python37\lib\site-packages\pytube\extract.py”, line 409, in apply_signature cipher = Cipher(js=js) File “C:\Users\User\AppData\Local\Programs\Python\Python37\lib\site-packages\pytube\cipher.py”, line 43, in init self.throttling_plan = get_throttling_plan(js) File “C:\Users\User\AppData\Local\Programs\Python\Python37\lib\site-packages\pytube\cipher.py”, line 411, in get_throttling_plan transform_plan_raw = find_object_from_startpoint(raw_code, match.span()[1] - 1) AttributeError: ‘NoneType’ object has no attribute ‘span’
thanks, man. your answer was right for me this day. i get back the string: name = re.escape(get_throttling_function_name(js))
and added regex r’([A-Za-z]{3})=function(a){var b=a.split(“”),’
instead of r’a.[A-Z]&&(b=a.get(“n”))&&(b=([^(]+)(b)',
Thanks.
Presento otro error a estas alturas no se que es lo que pasa porque solo escribí lo más básico posible en pytube pero igual no funciono 😦 me salio el mismo error#1218 les paso el error Este el código que ejecute
from pytube import YouTube YouTube("https://youtu.be/96L5sV7rqX0").streams.first().download()
les paso el error
Traceback (most recent call last): File "C:\Users\Fam. Cose Rojas\Desktop\Py-TUBE-Proyect\test2.py", line 3, in <module> YouTube("https://youtu.be/96L5sV7rqX0").streams.first().download() File "C:\Users\Fam. Cose Rojas\AppData\Local\Programs\Python\Python310\lib\site-packages\pytube\__main__.py", line 292, in streams return StreamQuery(self.fmt_streams) File "C:\Users\Fam. Cose Rojas\AppData\Local\Programs\Python\Python310\lib\site-packages\pytube\__main__.py", line 177, in fmt_streams extract.apply_signature(stream_manifest, self.vid_info, self.js) File "C:\Users\Fam. Cose Rojas\AppData\Local\Programs\Python\Python310\lib\site-packages\pytube\extract.py", line 409, in apply_signature cipher = Cipher(js=js) File "C:\Users\Fam. Cose Rojas\AppData\Local\Programs\Python\Python310\lib\site-packages\pytube\cipher.py", line 43, in __init__ self.throttling_plan = get_throttling_plan(js) File "C:\Users\Fam. Cose Rojas\AppData\Local\Programs\Python\Python310\lib\site-packages\pytube\cipher.py", line 387, in get_throttling_plan raw_code = get_throttling_function_code(js) File "C:\Users\Fam. Cose Rojas\AppData\Local\Programs\Python\Python310\lib\site-packages\pytube\cipher.py", line 301, in get_throttling_function_code code_lines_list = find_object_from_startpoint(js, match.span()[1]).split('\n') AttributeError: 'NoneType' object has no attribute 'span'