Greasy Fork is available in English.

InstaMagnify: Instagram Media Downloader

Best! Greatly enhance your Instagram navigation experience! And magically view or download the highest-quality, largest versions of Instagram stories, albums, images/photos, videos and profile avatars. If you have ever wanted to save a story, album, image/photo, video or avatar, then this is for you!

< Feedback on InstaMagnify: Instagram Media Downloader

Review: Good - script works

§
Posted: 21.11.2017

Excellent script, small feature request

Hello,

I have a small grievance with IG and I'm just about ready(but not quite) to roll my own userscript: Can anything be done about the annoying pop-up about "Experience the best version of Instagram by getting the app." I've managed to remove the bottom bar that's also about that with uBO, but that could be a useful feature for other folks. It all seems to be related to the "#reactivated" anchor auto-added to the URL on login. Just removing that should fix this.

Thank you!

§
Posted: 21.11.2017
Edited: 21.11.2017

Hi. Thanks for letting me know you like the script. Brightened my day. :-)

Hmm, I've never seen the popup you are talking about. It seems related to you never having used Instagram via any mobile apps.

But you are right, I was able to make it appear forcefully by adding #reactivated to the URL after I had logged in.

I observed the HTML, and saw that there are no "landmarks" that can be used to find that dialog (it's all randomly named (compressed) CSS classes which can change at any moment).

But I devised the following test-code (not finished by a long shot, just a proof of concept):

var links = document.querySelectorAll('a[href*="itunes.apple.com"]');
var buttons = links[0].parentNode.parentNode.getElementsByTagName('button');
if (buttons[0].textContent.match(/Close/)) {
    buttons[0].click();
}

It finds the link to the iTunes App Store, then looks 2 levels up (at its parents), and searches for a <button>. Then it checks if that button has the text "Close" and if so it clicks it.

That code gets rid of the dialog successfully.

The problem is that I have no account which gets that popup so that I can code this proof of concept into a finished "product" in the best way possible. For example, I need to know if the login adds the '#reactivated' via AJAX or if it navigates to that page (important distinction).

I need to know if the popup ONLY appears while '#reactivated' is in the URL, or if it can appear without that too.

Etc.

Would you be willing to share your account details with me via email, so that I can check how such a popup-login works, to do this testing and implementation work? You should simply change the password again afterwards.

If not then I hope you know Javascript? You spoke about rolling your own. Perhaps you can do the rest of the research then. Basically, this is what needs to be done:

  1. Test how their login works. Does it replace HTML (via AJAX) and virtually edit the page? Or does it force a true page navigation/reload. If it uses AJAX, we need a repeated timer (setInterval) that looks for '#reactivated' in the URL hash, perhaps every 500 milliseconds. If it uses a reload, we do not need any timer.
  2. Does the popup only appear with '#reactivated' in the URL?
  3. The code above need cleanup to use proper loops etc, to find the elements and check them all. Rather than hardcoding their "0th" index as in the test-code.
  4. Does the popup (and '#reactivated') re-appear if you log out and then log back in within the same web tab? If so, we need a permanent setInterval. If not, we can stop the timer after the first time we've cleared that popup.

Let's see how we can proceed with this.

Best Regards :-)

§
Posted: 21.11.2017
Edited: 21.11.2017

I also just remembered a complicating factor (which is easy to forget): The "Close" will not say Close in the rest of the world... So more work needs to be done to make this proof-of-concept code internationally safe. I can never, ever search for any phrases. :-\ But it will be possible to solve that somehow, such as also finding the androidstore-button (and checking that they're both hosted within a "Dialog" box, to be totally sure it's such a dialog (rather than the main login page which also has such links)...

But the main concern right now is all the other research, which is necessary before I can code anything to close that dialog.

The best thing would be if the dialog ONLY appears when '#reactivated' is in the URL. Because it's very slow and CPU-intensive to do this search: document.querySelectorAll('a[href*="itunes.apple.com"]');. Every anchor URL on the whole page needs to be searched. So that is why all the research is needed to figure out when the search is really necessary. If we can limit the search to only performing it when '#reactivated' is in window.location.hash, then that's great.

§
Posted: 21.11.2017

Hello and thank you for your interest!

Perhaps i spoke a bit out of term about my JS skills in saying that i could roll my own(I was thinking about just redirecting from the page with the anchor to without :)

Reasons i considered for said pop-up: browser, setting cookies as allowed only per session to ensure "logout" on browser close, using a classical login instead of FB and not having ever used a mobile app(though i do use the W10 native one sometimes). All turned out to be false as I have made a new account today to test, and it doesn't manifest said behavior AT ALL(!!), even if i oscillate logging in between the two accounts in the same tab(the original one manifests the issue every time, while the new one doesn't). Btw., when ever in need of testing i highly recommend this addon: https://is.gd/P0na53

I'm going to try to answer as best i can:
1. I don't think it's a true navigation/reload
2. IF and ONLY IF '#reactivated' is in the URL. Interestingly, if it's there and you open a "story", when you close that, the pop-up appears again. You can test this.
4. Yes, even if i oscillate between accounts and only on the one with the issue

All that beeing said, as far as i can tell, the js that deals with this can be found here: https://is.gd/MBBpxy

Just search for "reactivated". There are only 11 instances, and i couldn't find the word in any of teh js files loaded bot with the login and the index page.

Speaking of the new "story" feature recently added to IG web, when using your script on a picture from that it fails with the message: "Invalid URL signature" and on a video it redirects to the main .com. Any ideas on that?

Thank again for your incredible interest!

§
Posted: 22.11.2017
Edited: 23.11.2017

Hi again! I've just released a new version, which has been tested to the best of my ability (by manually adding #reactivated to the URL, since I have no accounts that exhibit the issue). Thanks for your information about what conditions trigger it, and for telling me that it seems linked to legacy accounts (not new ones). I was even able to reproduce the "view story, close story, see dialog again" issue via the URL trick. Thorough research like that has made me confident that this solution is correct, and as always I optimized it for efficiency.

Here's the changed code. Please install it and run it with your "weird" (hehe) account and see how it works out when logging out and in etc, but I think it's going to be perfect since you say the dialog only appears when #reactivated is in the URL and that it seems to be AJAX, so that's what I used as guideline.

https://greasyfork.org/en/scripts/34821-instamagnify-instagram-media-downloader/diff?v1=232443&v2=230637

It's been over an hour of work to help with your situation, so if you'd like to send in a small tip as thanks, you know where to find the donation info (on the main page's readme). It'd be really appreciated. ;-)

As for the Story media issue, I know what's wrong there. A few days ago, Instagram rolled out secure URLs for stories. I'll add support for them in a separate update soon. :-)

  • Johnny

Edit: After working on this on-and-off all day, I've now released the next major version which features support for protected (signed) media URLs, story photos/videos, and their brand new story viewer... Hope you like it.

§
Posted: 01.12.2017
Edited: 01.12.2017

Hello again!
I've been meaning to get back to you and thank you, but been busy as hell. This worked excellently on all functionalities until today, when it stopped working altogether. By the way, that new account I made to test this stuff started getting the "reactivated" stuff after a day or two.
If and when you get to fixing this, I'll be recommending it to all my peeps.
Thanks again!

EDIT: This seems to have been Firefox related as Chrome was fine. My script manager updated and now it's all good. Thanks again!

§
Posted: 03.12.2017
Edited: 03.12.2017

Hi again! Thanks for recommending the script to others. Please also support it by adding it to your GreasyFork favorites (it helps and costs you nothing).

I don't understand your edit. It sounds like the only problem was that your Firefox had an old version of this script from before my #reactivated update?

§
Posted: 03.12.2017

Hi,
It was a purely Firefox issue, since the 57.0.1 update and it got fixed when Violentmonkey updated aswell. I think this describes what happened: https://violentmonkey.github.io/2017/10/28/Inject-scripts-with-BLOB-URLs/

§
Posted: 03.12.2017

Ahh, I read the page and their explanation sounds very likely. Thanks for the details! I am glad it works now. I guess we're done then. Take care and happy holidays! :-)

§
Posted: 05.12.2017

Same to you, man!

§
Posted: 27.01.2018
Edited: 29.01.2018

Hello again!
Instagram has started using secure URLs for all profile pictures and some normal posts. Can you do something about that?

Thank you!

§
Posted: 28.01.2018
Edited: 28.01.2018

@HlHlHl That's unfortunate news. :-( Signatures are a "sum" that validates the entire URL, and they prevent modifying the URL. It is a secure system used by Facebook to prevent downloading (and sharing media links, since signed URLs expire after a while). Sadly Instagram (which is owned by Facebook) is now getting the same system for some reason. I'll just have to add some code to detect signatures and leave such URLs as-is. Because Instagram has sadly decided that such URLs are "forbidden".

§
Posted: 28.01.2018
Edited: 28.01.2018

@HlHlHl Heeeeeey, wait a minute... I felt DEJA VU about your request. But it has been 66 days since the last update so I didn't remember it clearly: I have actually already added code to support signed URLs. Just update your browser to the latest version of InstaMagnify (the one from 66 days ago). It detects the protected URLs and ensures that they work (can be viewed and easily downloaded, especially in Chrome with the Alt-Shift click). So that means you're using an older version of InstaMagnify...

§
Posted: 28.01.2018
Edited: 29.01.2018

[edited]

§
Posted: 29.01.2018
Edited: 29.01.2018

@HlHlHl ...

§
Posted: 29.01.2018

Done. So you will not be adding support for profile pictures and the newly protected posts?

§
Posted: 29.01.2018
Edited: 03.02.2018

@HlHlHl I won't make anything public since it would definitely backfire when they discover it...

§
Posted: 29.01.2018
Edited: 03.02.2018

The ... webextension already deals with this publicly so it's already an open secret. This being a bit over my head, can they really lock down access?

§
Posted: 30.01.2018
Edited: 02.02.2018

Oh god... enjoy it while it lasts. This is a sad day...

Well, thanks for letting me know others are being idiots by publicizing it. Now I know that we must all expect the method to be closed down soon... and I won't be taken by surprise when it happens.

§
Posted: 30.01.2018
Edited: 04.02.2018

PS: I am taking a long vacation from programming and can't guarantee that I'll be checking greasyfork. Take care! :)

§
Posted: 31.01.2018

Alright then, let's hope it lasts. Have a happy break and thanks again for the great script!

§
Posted: 01.02.2018
Edited: 04.02.2018
Alright then, let's hope it lasts. Have a happy break and thanks again for the great script!

Thank you, I'm having a relaxing break... :-) I just decided to check here again to see if you had replied. And you had. Hehe.

I really hope it lasts, but chances aren't good, since they've spent 3 whole months working on adding and revising the new system for Instagram media. But sure, let's hope it lasts for a long time anyway... maybe we'll get super lucky and they never notice it/don't care.

Fingers crossed for that! It's stupid that they're messing up timeline media. Stories? Fine, those are often private and need the extra security. But they should have left the timelines alone.

§
Posted: 03.02.2018

Hey, here's a thought(don't judge if this is stupid): they can't block this because it would invalidate their API. Thoughts?

§
Posted: 04.02.2018
Edited: 04.02.2018

That was a good question so I don't judge you for it. ;) But "unfortunately" my project description is telling the truth about "written by the author of the largest 3rd party Instagram API library in the world". I know everything there is to know about their API...

And the API doesn't let the clients (not even their own apps) generate the media URLs. The API delivers the finished URLs to the client in the JSON replies, which means that even the oldest clients all get the new, protected URLs. The clients just dutifully connect to the finished media URLs provided by their API server.

It looks like this (fresh data I just grabbed from their API to demonstrate it):

{
            "taken_at": "1515479862",
            "pk": "1688289910093757664",
            "id": "1688289910093757664_13460080",
            "device_timestamp": "1515479740",
            "media_type": 1,
            "code": "BduArpxA7zg",
            "filter_type": 0,
            "image_versions2": {
                "candidates": [
                    {
                        "width": 1080,
                        "height": 1350,
                        "url": "https://scontent-arn2-1.cdninstagram.com/vp/ed56fed40d39fe8bfb1edbbe65691ef9/5B254673/t51.2885-15/e35/26181434_525536554492575_219301309306634240_n.jpg?se=7&ig_cache_key=MTY4ODI44TkxMDA5Mzc1NzY2NA%3D%3D.2"
                    },
                    {
                        "width": 240,
                        "height": 300,
                        "url": "https://scontent-arn2-1.cdninstagram.com/vp/7f874f91ee10b79538234c5e3282702a/5B0A67E1/t51.2885-15/e35/p240x240/26181434_525536554492575_219301309306634240_n.jpg?se=7&ig_cache_key=MTY4ODI44TkxMDA5Mzc1NzY2NA%3D%3D.2"
                    }
                ]
            },
            "original_width": 1080,
            "original_height": 1350,
            ...
 }

Full paste: https://pastebin.com/3PBWEbyU

However... While grabbing the API data example for you, I just noticed something really great: Instagram has FINALLY uncapped the max-res files on timelines! It has happened sometime in the last months! WOW! There's no more "p#x#" resizing on the highest res image file above. As you can see, the first imageversions2 candidate matches the size of originalwidth/height (the exact size uploaded by the media author)! So there's really no need to rewrite the URLs anymore! (The remaining /e35/ crap in the protected URL just controls some EXIF metadata and doesn't affect the image pixels; as I verified with composite clean.jpg e35.jpg -compose difference diff.png where clean.jpg is a "totally scrubbed/clean URL", and "e35" is the media URL I list below, and the comparison gave a pitch black result, proving that there's zero difference between the image with/without e35 (and protection) in the URL. I also verified with compare -metric AE clean.jpg e35.jpg diff.png which gave 0 meaning equal, in other words ZERO pixels are different between a fully scrubbed URL and the top-res protected URL below!)

So it doesn't really matter that they have protected URLs. Because as you can see, this IS already the max-resolution file: https://scontent-arn2-1.cdninstagram.com/vp/ed56fed40d39fe8bfb1edbbe65691ef9/5B254673/t51.2885-15/e35/26181434_525536554492575_219301309306634240_n.jpg?se=7&ig_cache_key=MTY4ODI44TkxMDA5Mzc1NzY2NA%3D%3D.2 (the URL may be expired by the time you click it though, hehe).

What a great day! It means that there's never going to be anything blocking us from getting the top quality photos.

As for videos, those are never capped/modified by their server via any URL params. Those are always max-res.

So you'll get the top resolution timeline media via these 2 steps:

  1. Click on the media to open it in the overlay view so that your browser gets the top-resolution media URL (rather than the timeline preview URL).
  2. THEN shift-click (or alt-f or whatever shortcut you wanna use) to view/save the full-resolution file.

It worked. I just tested it on Nike's timeline. That's FANTASTIC news. :-)

As for stories, the images and videos are likewise all full-res.

The preview-screenshots for videos (on both timeline and stories) are almost full-res (640px wide instead of 720px), but those don't really matter since they're just a static frame screenshot and you just want the video anyway.

So what this means: For the first time ever, Instagram provides protected URLs leading to the max-resolution URLs for all photos and all videos, on both timelines and stories. Only the video-preview screenshots are slightly lower res and those don't matter. As for avatars, it's probably only a matter of time until Instagram officially gives those out in max-res too...

So we don't need to worry. Everything is going to work out fine. Just click on the media on the timeline and then use alt-f/shift-f to view the full res file or alt-shift-f to download it (in supported browsers), and use left/right arrows to navigate between media rapidly. It will give you the best media quality via their officially protected URLs. Try it! :smiley:

This is a great day... it means that even when protected URLs become permanent, they now give us access to the best-quality files anyway! That's HUGE news!

§
Posted: 05.02.2018

Thanks for the detailed explanation. Cool stuff!

§
Posted: 27.02.2018

Hey again, man!
Stories have stopped working since today :(
Everything else seems fine.

§
Posted: 04.03.2018
Edited: 04.03.2018

Hey. Well, the story stuff is still working via Shift+F and Alt+F and Alt-Shift=F, so it's not actually broken. I can see that Instagram has simply added some kinda click-overlay which prevents our regular click detection, so the mouse method doesn't work since their code is now what runs on each mouse-click instead of our code... I don't have time to investigate how to defeat their click-blocking. It's probably pretty simple but I have no time at all. If anyone contributes a solution, feel free to post it here.

§
Posted: 05.03.2018

Didn't even check the keyboard shortcuts. Cool. Thanks!

§
Posted: 23.03.2018

@HlHlHl Aaaand now it has happened (a few hours ago, today):

- Instagram now REQUIRES `/vp/` (signed URLs) in EVERY media URL (timeline AND stories). If you try to download media via a "fully cleaned URL", you will always get "Access Denied" as the response.

This is why I didn't publicize the method. But enough people already shared it and Instagram has noticed and blocked the method now.

There's no more workaround.

Luckily my tests above were done before the change, where I was able to verify that they now provide the highest quality media as the "top URL" and that the pixels are identical either way. So we don't lose much. We do get some garbage EXIF metadata appended to our files due to the `/e35/` and `/e15` stuff, but that's all. And that data doesn't identify the user that downloaded the file. It's some generic metadata which describes what URL flags were used on an image...

Just letting you know.

§
Posted: 23.03.2018

Thanks for the heads up.
In the end, if one can get the full quality image and there's no tracking involved, it doesn't really matter, does it? You looking to update your script or still busy? :)

§
Posted: 23.03.2018
Edited: 23.03.2018

Hehe, well I am very happy and relieved that I did the thorough tests *before* the lockdown, otherwise we would never have known the difference between clean and signed URLs (or rather: That there is no pixel difference.)... So yeah, it's alright in the end. ;-)

About the script: Still too busy. But felt bad for you, so I took a deeper look and found the problem. It wasn't their new "click handler" that was causing this. They had just moved the story media to another HTML container a bit higher up. So here's a gift for you: https://greasyfork.org/en/scripts/34821-instamagnify-instagram-media-downloader/versions :-) - this is the final update for the foreseeable future though. I'm still too busy to program.

§
Posted: 23.03.2018

Nice one! Thanks, man!

§
Posted: 23.03.2018

You're welcome. Enjoy :-)

Post reply

Sign in to post a reply.