High-Resolution-Downloader-For-Instagram
High-Resolution-Downloader-For-Instagram copied to clipboard
Some Instagram videos are now blobs and can't download
Example: https://www.instagram.com/p/CIWG0RZq01F/
Same problem that exists for live videos.
Some notes after investigating. Seems like the objectURL being used here is revoked, so there's no way to fetch the blog:https://www...
url and reconvert it into a blob / new objectURL.
On photo pages the CDN video url is stored in the video_url
key in the window variable __additionalData
. When the photo appears in a modal, that same key is in the _sharedData
variable. On the feed it seems like videos are still being served with real urls.
I think the only way to resolve this is to set up an injected script which can pass these window variables into the extension sandbox. The extension would have to send a message to the injected script on click, which would send back either both whole objects, or parse it itself and send back the url.
Ran into this problem. Example: https://www.instagram.com/p/CJW3dDshazB/
This can be fixed by performing a XHR request. More specifically, a query for the Instagram post in question. For example, if the post you want to download is https://www.instagram.com/p/CJWeXy4nD17/ , then you perform a fetch at https://www.instagram.com/p/CJWeXy4nD17/?__a=1 .
This returns some JSON from the Instagram server, and it's just a matter of finding the video_url attribute. This will be an .mp4 file (with some query params attached), but it's a direct source file that can then be downloaded.
@mahye82 that seems like a better idea than the injected script. Nice!
@mahye82 I'm not that familiar with graphql. Is there any documentation on how to use get params with Instagram specifically? Where does the __a param come from?
It's been a while since I did any GraphQL myself, so I'm not the best person to ask (I've forgotten most of it). Here's a good video to get you familiar with the basic concepts: https://www.youtube.com/watch?v=ed8SzALpx1Q Follow along with the video for the first 20 mins or so.
Note, that while the video does an excellent job of explaining concepts behind GraphQL, the actual implementation has received updates, and you're better off consulting the official graphql docs: https://graphql.org/learn/ or this: https://www.howtographql.com/ It's a lot simpler than it initially seems.
I'm fairly sure that the ?__a=1 param comes from Instagram's legacy API. I don't know how long it's going to last though - in 2020, Instagram updated their API considerably. They really don't like web scraping apps like your extension, unfortunately!
Got a partial fix merged. Keeping this open until I can get a fix out that includes videos in modals and the feed.
GraphQL is working reliably for standalone videos and modal videos, but when videos in the feed are blobs, there's no way to use GraphQL because there's no clear way to get the video ID / url. Same with stories, which are intermittently blobs for me.
This can be fixed by performing a XHR request. More specifically, a query for the Instagram post in question. For example, if the post you want to download is https://www.instagram.com/p/CJWeXy4nD17/ , then you perform a fetch at https://www.instagram.com/p/CJWeXy4nD17/?__a=1 .
This returns some JSON from the Instagram server, and it's just a matter of finding the video_url attribute. This will be an .mp4 file (with some query params attached), but it's a direct source file that can then be downloaded.
Dude, @mahye82 , are you God? Man, you just blowed my mind, really:) Thanks! I have some knowledge about javascript, fw like nodejs, other language like Python, SQL, but because of my ignorance, this just seems to be magic, thanks again!
Dude, @mahye82 , are you God? Man, you just blowed my mind, really:) Thanks! I have some knowledge about javascript, fw like nodejs, other language like Python, SQL, but because of my ignorance, this just seems to be magic, thanks again!
There's only one God. But thank you. :)
There's nothing special about what I did. Most complex modern websites like Instagram, Twitter, etc are Single Page Applications which return a very basic HTML page, which is then dynamically populated with information provided in XHRs.
Whenever you're trying to figure out how a website works, it's always worth checking those XHRs in the Chrome Dev Tools, because you can often find what you're looking for in them.
This can be fixed by performing a XHR request. More specifically, a query for the Instagram post in question. For example, if the post you want to download is https://www.instagram.com/p/CJWeXy4nD17/ , then you perform a fetch at https://www.instagram.com/p/CJWeXy4nD17/?__a=1 .
This returns some JSON from the Instagram server, and it's just a matter of finding the video_url attribute. This will be an .mp4 file (with some query params attached), but it's a direct source file that can then be downloaded.
Thank you very much 🤎 I'm really appreciate this
Thanks! @mahye82 I did what you said and I created this script for downloading videos directly from console. A few important notes:
- It assumes that there are no GET parameters in the URL.
- Because of crossorigin issues you have to reload the site after being redirected. Sometimes F5 does not work but focusing the url and pressing enter did. Don't ask me why.
Here is the code:
function downloadBlob(){
let xhr = new XMLHttpRequest();
xhr.open("GET", window.location.toString() + "?__a=1");
xhr.onload = () => {
window.location = JSON.parse(xhr.response).graphql.shortcode_media.video_url;
}
xhr.send();
}
downloadBlob();
This can be fixed by performing a XHR request. More specifically, a query for the Instagram post in question. For example, if the post you want to download is https://www.instagram.com/p/CJWeXy4nD17/ , then you perform a fetch at https://www.instagram.com/p/CJWeXy4nD17/?__a=1 .
This returns some JSON from the Instagram server, and it's just a matter of finding the video_url attribute. This will be an .mp4 file (with some query params attached), but it's a direct source file that can then be downloaded.
Does this work anymore? I have attempted but it appears there is no video_url attribute per se, and all urls are "bad URL hash", I assume this is becasue the URL's expire and im doing the XHR wrong...
This can be fixed by performing a XHR request. More specifically, a query for the Instagram post in question. For example, if the post you want to download is https://www.instagram.com/p/CJWeXy4nD17/ , then you perform a fetch at https://www.instagram.com/p/CJWeXy4nD17/?__a=1 . This returns some JSON from the Instagram server, and it's just a matter of finding the video_url attribute. This will be an .mp4 file (with some query params attached), but it's a direct source file that can then be downloaded.
Does this work anymore? I have attempted but it appears there is no video_url attribute per se, and all urls are "bad URL hash", I assume this is becasue the URL's expire and im doing the XHR wrong...
Yes, it's still possible to download it in Chrome console, with a modification of the code by @security-somanos
- Press F12 to open developer tools.
- Click the console tab.
- Copy & paste in this code snippet.
function downloadBlob(){
let xhr = new XMLHttpRequest();
xhr.open("GET", window.location.toString() + "?__a=1");
xhr.onload = () => {
let data = JSON.parse(xhr.response);
let newLink = data.items[0].video_versions[0].url;
console.log(newLink);
}
xhr.send();
}
downloadBlob();
- Copy that link in the console into a new tab. If you tried doing window.location or window.open with that URL, the video won't load because of CORS policy.
It seems it is not working anymore. How does IG block downloading videos using blob? It's scary.
I successfully downloaded a video using this approach: https://stackoverflow.com/a/53481372/4158755
Hope it helps.
if you open the post in chrome's mobile view and browse the html, you will find the link in an mp4 format, as they seem to have backwards support since the normal desktop web view supplies the blob format... tested with
https://www.instagram.com/p/CzZUJ3FPiBf
It's blob url in my case QAQ
and ?__a=1
magic is also not working :(
video_versions
is not in the response json
@jimmylee850328 you need to open the post while already been in the mobile dev view, in order for insta to give you the fallback video url