piplongrun.github.io
piplongrun.github.io copied to clipboard
Update bookmarklet.js
Bypasses the 403 Error Introduced with the latest Plex Media Server update.
:+1: for this change.
The thing I've noticed is that the name of the file that is downloaded is always "file.mkv". In the past it was the same as the filename on the server.
Would anyone be able to let me know how to implement @fkik's change to the bookmarklet?
I came across the 403 error today, but am not au fait with coding etc. Thanks!
@trodscudgeon
Figured out myself through some exploring.
So to start...
Right click the bookmark, hit edit.
It will show you some javascript, you will see it in the URL area.
Switch out the bookmarklet.js URL found in the code with this:
https%3A%2F%2Fgithub.com%2Ffkick%2Fpiplongrun.github.io%2Fblob%2F09fb91a603c825cd2e2adc1f08c962ca258a3223%2Fplxdwnld%2Fbookmarklet.js%3Fts%3D
That will link it to the updated file found here.
Haven't fully tested it yet so there's a chance it might not work.
@Suffice Hmmm. Tried according to your instructions, but not working. Thanks for replying and let me know if you figure it out!
@Suffice Hmmm. Tried according to your instructions, but not working. Thanks for replying and let me know if you figure it out!
Paste this inside your bookmarklet
javascript:(function()%7B%2F***%20Download%20original%20files%20from%20the%20Plex%20web%20interface**%20This%20project%20is%20licensed%20under%20the%20terms%20of%20the%20MIT%20license%2C%20see%20https%3A%2F%2Fpiplongrun.github.io%2Fplxdwnld%2FLICENSE.txt**%20%40author%20%20%20%20%20%20Pip%20Longrun%20%3Cpip.longrun%40protonmail.com%3E*%20%40version%20%20%20%20%200.3*%20%40see%20%20%20%20%20%20%20%20%20https%3A%2F%2Fpiplongrun.github.io%2Fplxdwnld%2F**%2F%22use%20strict%22%3Bif%20(typeof%20plxDwnld%20%3D%3D%3D%20%22undefined%22)%20%7Bwindow.plxDwnld%20%3D%20(function()%20%7Bconst%20self%20%3D%20%7B%7D%3Bconst%20clientIdRegex%20%3D%20new%20RegExp(%22server%5C%2F(%5Ba-f0-9%5D%7B40%7D)%5C%2F%22)%3Bconst%20metadataIdRegex%20%3D%20new%20RegExp(%22key%3D%252Flibrary%252Fmetadata%252F(%5C%5Cd%2B)%22)%3Bconst%20apiResourceUrl%20%3D%20%22https%3A%2F%2Fplex.tv%2Fapi%2Fresources%3FincludeHttps%3D1%26X-Plex-Token%3D%7Btoken%7D%22%3Bconst%20apiLibraryUrl%20%3D%20%22%7Bbaseuri%7D%2Flibrary%2Fmetadata%2F%7Bid%7D%3FX-Plex-Token%3D%7Btoken%7D%22%3Bconst%20downloadUrl%20%3D%20%22%7Bbaseuri%7D%7Bpartkey%7D%3Fdownload%3D0%26X-Plex-Token%3D%7Btoken%7D%22%3Bconst%20accessTokenXpath%20%3D%20%22%2F%2FDevice%5B%40clientIdentifier%3D'%7Bclientid%7D'%5D%2F%40accessToken%22%3Bconst%20baseUriXpath%20%3D%20%22%2F%2FDevice%5B%40clientIdentifier%3D'%7Bclientid%7D'%5D%2FConnection%5B%40local%3D'0'%5D%2F%40uri%22%3Bconst%20partKeyXpath%20%3D%20%22%2F%2FMedia%2FPart%5B1%5D%2F%40key%22%3Blet%20accessToken%20%3D%20null%3Blet%20baseUri%20%3D%20null%3Bconst%20getXml%20%3D%20function(url%2C%20callback)%20%7Bconst%20request%20%3D%20new%20XMLHttpRequest()%3Brequest.onreadystatechange%20%3D%20function()%20%7Bif%20(request.readyState%20%3D%3D%204%20%26%26%20request.status%20%3D%3D%20200)%20%7Bcallback(request.responseXML)%3B%7D%7D%3Brequest.open(%22GET%22%2C%20url)%3Brequest.send()%3B%7D%3Bconst%20getMetadata%20%3D%20function(xml)%20%7Bconst%20clientId%20%3D%20clientIdRegex.exec(window.location.href)%3Bif%20(clientId%20%26%26%20clientId.length%20%3D%3D%202)%20%7Bconst%20accessTokenNode%20%3D%20xml.evaluate(accessTokenXpath.replace('%7Bclientid%7D'%2C%20clientId%5B1%5D)%2C%20xml%2C%20null%2C%20XPathResult.FIRST_ORDERED_NODE_TYPE%2C%20null)%3Bconst%20baseUriNode%20%3D%20xml.evaluate(baseUriXpath.replace('%7Bclientid%7D'%2C%20clientId%5B1%5D)%2C%20xml%2C%20null%2C%20XPathResult.FIRST_ORDERED_NODE_TYPE%2C%20null)%3Bif%20(accessTokenNode.singleNodeValue%20%26%26%20baseUriNode.singleNodeValue)%20%7BaccessToken%20%3D%20accessTokenNode.singleNodeValue.textContent%3BbaseUri%20%3D%20baseUriNode.singleNodeValue.textContent%3Bconst%20metadataId%20%3D%20metadataIdRegex.exec(window.location.href)%3Bif%20(metadataId%20%26%26%20metadataId.length%20%3D%3D%202)%20%7BgetXml(apiLibraryUrl.replace('%7Bbaseuri%7D'%2C%20baseUri).replace('%7Bid%7D'%2C%20metadataId%5B1%5D).replace('%7Btoken%7D'%2C%20accessToken)%2C%20getDownloadUrl)%3B%7D%20else%20%7Balert(%22You%20are%20currently%20not%20viewing%20a%20media%20item.%22)%3B%7D%7D%20else%20%7Balert(%22Cannot%20find%20a%20valid%20accessToken.%22)%3B%7D%7D%20else%20%7Balert(%22You%20are%20currently%20not%20viewing%20a%20media%20item.%22)%3B%7D%7D%3Bconst%20getDownloadUrl%20%3D%20function(xml)%20%7Bconst%20partKeyNode%20%3D%20xml.evaluate(partKeyXpath%2C%20xml%2C%20null%2C%20XPathResult.FIRST_ORDERED_NODE_TYPE%2C%20null)%3Bif%20(partKeyNode.singleNodeValue)%20%7Bwindow.location.href%20%3D%20downloadUrl.replace('%7Bbaseuri%7D'%2C%20baseUri).replace('%7Bpartkey%7D'%2C%20partKeyNode.singleNodeValue.textContent).replace('%7Btoken%7D'%2C%20accessToken)%3B%7D%20else%20%7Balert(%22You%20are%20currently%20not%20viewing%20a%20media%20item.%22)%3B%7D%7D%3Bself.init%20%3D%20function()%20%7Bif%20(typeof%20localStorage.myPlexAccessToken%20!%3D%20%22undefined%22)%20%7BgetXml(apiResourceUrl.replace('%7Btoken%7D'%2C%20localStorage.myPlexAccessToken)%2C%20getMetadata)%3B%7D%20else%20%7Balert(%22You%20are%20currently%20not%20browsing%20or%20logged%20into%20a%20Plex%20web%20environment.%22)%3B%7D%7D%3Breturn%20self%3B%7D)()%3B%7DplxDwnld.init()%7D)()
👍 for this change.
The thing I've noticed is that the name of the file that is downloaded is always "file.mkv". In the past it was the same as the filename on the server.
Have you found out how to get it working correctly with naming?
Also it looks like the site where the javascript is located is down... It doesn't work at all now...
I tried this locally and the change results in a response of "400 Bad Request" rather than a "403 Forbidden" so it seems that another way to download needs to be discovered
edit: it dawned on me that the 400 may be because i was hosting locally as http instead of https. so that may have something to do with it.
Hopefully this all gets resolved soon, my friend has shared their library with me so I can become a wannabe datahoarder lol
@piplongrun The website is down atm. please bring it back up!!!
Also it looks like the site where the javascript is located is down... It doesn't work at all now...
Use the code in @LampPrinter 's post for the download - no need for an external server.
Have you found out how to get it working correctly with naming?
As far as the filename issue, I've been thinking about coding a Tampermonkey / GreaseMoney script in the browser that scrapes the Plex media page and copies the name into the clipboard. I've procrastinated doing it because I don't use this download method much. Maybe I'll get some time over the next weekend or two and see what I could slap together.
Hopefully this all gets resolved soon, my friend has shared their library with me so I can become a wannabe datahoarder lol
@piplongrun The website is down atm. please bring it back up!!!
Use the code in @LampPrinter 's post for the download - no need for an external server.
@isuelt @LampPrinter Is it possible that the new web layout screwed with the script?
It's not working on my end :/
Oh... ignore half of that. It works one one server but doesnt on the other. So maybe the other server is behind 7 proxies.
It's more likely to be due to this change in Plex Media Server 1.23.6.4881 and later:
NEW:
- (Downloads) Download access now enforced on the server via shared user settings (#12859)
its not working because the piplong.run site is down, the bookmarklet relies on the site to work so until then you can use this code instead (you can change it in chrome by right clicking it and pressing edit and changing the URL field to:
javascript:(function()%7B%2F**%0A * Download original files from the Plex web interface%0A *%0A * This project is licensed under the terms of the MIT license%2C see https%3A%2F%2Fpiplongrun.github.io%2Fplxdwnld%2FLICENSE.txt%0A *%0A * %40author Pip Longrun <pip.longrun%40protonmail.com>%0A * %40version 0.3%0A * %40see https%3A%2F%2Fpiplongrun.github.io%2Fplxdwnld%2F%0A *%0A *%2F%0A"use strict"%3B%0A%0Aif (typeof plxDwnld %3D%3D%3D "undefined") %7B%0A%0A window.plxDwnld %3D (function() %7B%0A%0A const self %3D %7B%7D%3B%0A const clientIdRegex %3D new RegExp("server%5C%2F(%5Ba-f0-9%5D%7B40%7D)%5C%2F")%3B%0A const metadataIdRegex %3D new RegExp("key%3D%252Flibrary%252Fmetadata%252F(%5C%5Cd%2B)")%3B%0A const apiResourceUrl %3D "https%3A%2F%2Fplex.tv%2Fapi%2Fresources%3FincludeHttps%3D1%26X-Plex-Token%3D%7Btoken%7D"%3B%0A const apiLibraryUrl %3D "%7Bbaseuri%7D%2Flibrary%2Fmetadata%2F%7Bid%7D%3FX-Plex-Token%3D%7Btoken%7D"%3B%0A const downloadUrl %3D "%7Bbaseuri%7D%7Bpartkey%7D%3Fdownload%3D1%26X-Plex-Token%3D%7Btoken%7D"%3B%0A const accessTokenXpath %3D "%2F%2FDevice%5B%40clientIdentifier%3D'%7Bclientid%7D'%5D%2F%40accessToken"%3B%0A const baseUriXpath %3D "%2F%2FDevice%5B%40clientIdentifier%3D'%7Bclientid%7D'%5D%2FConnection%5B%40local%3D'0'%5D%2F%40uri"%3B%0A const partKeyXpath %3D "%2F%2FMedia%2FPart%5B1%5D%2F%40key"%3B%0A let accessToken %3D null%3B%0A let baseUri %3D null%3B%0A%0A const getXml %3D function(url%2C callback) %7B%0A const request %3D new XMLHttpRequest()%3B%0A request.onreadystatechange %3D function() %7B%0A if (request.readyState %3D%3D 4 %26%26 request.status %3D%3D 200) %7B%0A callback(request.responseXML)%3B%0A %7D%0A %7D%3B%0A request.open("GET"%2C url)%3B%0A request.send()%3B%0A %7D%3B%0A%0A const getMetadata %3D function(xml) %7B%0A const clientId %3D clientIdRegex.exec(window.location.href)%3B%0A%0A if (clientId %26%26 clientId.length %3D%3D 2) %7B%0A const accessTokenNode %3D xml.evaluate(accessTokenXpath.replace('%7Bclientid%7D'%2C clientId%5B1%5D)%2C xml%2C null%2C XPathResult.FIRST_ORDERED_NODE_TYPE%2C null)%3B%0A const baseUriNode %3D xml.evaluate(baseUriXpath.replace('%7Bclientid%7D'%2C clientId%5B1%5D)%2C xml%2C null%2C XPathResult.FIRST_ORDERED_NODE_TYPE%2C null)%3B%0A%0A if (accessTokenNode.singleNodeValue %26%26 baseUriNode.singleNodeValue) %7B%0A accessToken %3D accessTokenNode.singleNodeValue.textContent%3B%0A baseUri %3D baseUriNode.singleNodeValue.textContent%3B%0A const metadataId %3D metadataIdRegex.exec(window.location.href)%3B%0A%0A if (metadataId %26%26 metadataId.length %3D%3D 2) %7B%0A getXml(apiLibraryUrl.replace('%7Bbaseuri%7D'%2C baseUri).replace('%7Bid%7D'%2C metadataId%5B1%5D).replace('%7Btoken%7D'%2C accessToken)%2C getDownloadUrl)%3B%0A %7D else %7B%0A alert("You are currently not viewing a media item.")%3B%0A %7D%0A %7D else %7B%0A alert("Cannot find a valid accessToken.")%3B%0A %7D%0A %7D else %7B%0A alert("You are currently not viewing a media item.")%3B%0A %7D%0A %7D%3B%0A%0A const getDownloadUrl %3D function(xml) %7B%0A const partKeyNode %3D xml.evaluate(partKeyXpath%2C xml%2C null%2C XPathResult.FIRST_ORDERED_NODE_TYPE%2C null)%3B%0A%0A if (partKeyNode.singleNodeValue) %7B%0A window.location.href %3D downloadUrl.replace('%7Bbaseuri%7D'%2C baseUri).replace('%7Bpartkey%7D'%2C partKeyNode.singleNodeValue.textContent).replace('%7Btoken%7D'%2C accessToken)%3B%0A %7D else %7B%0A alert("You are currently not viewing a media item.")%3B%0A %7D%0A %7D%3B%0A%0A self.init %3D function() %7B%0A if (typeof localStorage.myPlexAccessToken !%3D "undefined") %7B%0A getXml(apiResourceUrl.replace('%7Btoken%7D'%2C localStorage.myPlexAccessToken)%2C getMetadata)%3B%0A %7D else %7B%0A alert("You are currently not browsing or logged into a Plex web environment.")%3B%0A %7D%0A %7D%3B%0A%0A return self%3B%0A %7D)()%3B%0A%7D%0A%0AplxDwnld.init()%3B%7D)()%3B
Hello! Why does it work on one server but not the other?
It's more likely to be due to this change in Plex Media Server 1.23.6.4881 and later:
NEW:
- (Downloads) Download access now enforced on the server via shared user settings (#12859)
Again, it sometimes doesn't work even if you correct the source because some servers will have updated to this version where Plex blocked it.
It's more likely to be due to this change in Plex Media Server 1.23.6.4881 and later:
NEW:
- (Downloads) Download access now enforced on the server via shared user settings (#12859)
Again, it sometimes doesn't work even if you correct the source because some servers will have updated to this version where Plex blocked it.
Thanks for the reply! Do you think Plex will get a new update where it will let users do this as before?
I doubt it, you're probably going to have to talk to the administrators of the Plex instances you want to download from about permitting downloads.
You mean talking to the person that's sharing the server? I got them to enable the ''Allow Downloads'' option, but still nothing. And with another server that the person didn't enabled this option, the code works. Really weird.
It's not weird. The code used a bug with the software, enabling you to download from servers who specifically did not enable downloading. The new update fixed that bug, now you need the admin to enable downloads and use the plex functionality
I got the option to download enabled from the server owner! But the button does not appear to me. Is it a Plex Pass only thing? Or with a regular account I could still download and watch it offline on the Plex app/browser page.
Any chance the website could be recovered? Would be great :) this script has always been great, the script above is good too but it doesn't name the file.
@Juzzotec use the code from my earlier comment, it still works
@Juzzotec use the code from my earlier comment, it still works
Man, to call you a legend would be an understatement. I love this script and you brought it back to life. Thank you x100... keep plxdwnld alive ❤️
@Juzzotec use the code from my earlier comment, it still works
'403 Forbidden' error for me.
if you copy the code and put it in the dev console (f12 on chrome) does that work?
if you copy the code and put it in the dev console (f12 on chrome) does that work?
I did not tried that way. I just edit the bookmark code and press on it with a movie opened on Plex.
How do I do it?
@mateussaa copy the all code from plxdwnld/bookmarklet.js and paste it into the dev console
@nmcc1212 It doesn't work. I tried on Mozilla by editing the bookmarklet and I get a '403 Forbidden'. And it doesn't work by copying and pasting too.
@mateussaa try using this: http://nmcc1212.github.io/ it is a backup of the old site, if it doesn't work ill try the code from this PR