186

I'm trying to put a user's recent Instagram media on a sidebar. I'm trying to use the Instagram API to fetch the media.

http://instagram.com/developer/endpoints/users/

The documentation says to GET https://api.instagram.com/v1/users/<user-id>/media/recent/, but it says to pass an OAuth access token. An access token represents the authorization to act on behalf of a user. I don't want users to log into Instagram to see this on the sidebar. They shouldn't even need to have an Instagram account.

For instance, I can go to http://instagram.com/thebrainscoop without being logged into Instagram and see photos. I want to do that through the API.

In the Instagram API, non-user-authenticated requests pass a client_id instead of an access_token. If I try that, though, I get:

{
  "meta":{
    "error_type":"OAuthParameterException",
    "code":400,
    "error_message":"\"access_token\" URL parameter missing. This OAuth request requires an \"access_token\" URL parameter."
  }
}

So, is this not possible? Is there no way to fetch a user's latest (public) media without asking a user to log into an Instagram account through OAuth first?

Braiam
  • 1
  • 11
  • 47
  • 78
Peeja
  • 13,683
  • 11
  • 58
  • 77
  • It's possible with this plugin, just checkout the source code of how they fetched a user's latest public media without asking a user to log into his or her instagram account. :D https://smashballoon.com/instagram-feed/demo/ You just need a client id, no access token needed. :D – jehzlau Oct 24 '16 at 22:31
  • You need to auth so they can track you and limit your downloads (rates...) like every big API. There is public for real users and public for scrappers/bots, which is usually not the same as real users will see ads and directly use the service. – Christophe Roussy Apr 16 '18 at 13:41
  • 1
    None of these methods work anymore. See https://stackoverflow.com/questions/49852080/is-there-currently-anyway-to-fetch-instagram-user-media-without-authentication – Moradnejad Apr 21 '18 at 04:55
  • https://stackoverflow.com/questions/59526137/my-app-was-rejected-by-instagram-basic-display-api-review-due-to-invalid-reasons – Amrut Bidri Dec 30 '19 at 06:26
  • You can use https://profilepageimages.usecue.com/. Heads up: I am the author of this tool. – Mr. Hugo Jan 22 '21 at 17:32

20 Answers20

340

var name = "smena8m";
$.get("https://images"+~~(Math.random()*3333)+"-focus-opensocial.googleusercontent.com/gadgets/proxy?container=none&url=https://www.instagram.com/" + name + "/", function(html) {
if (html) {
    var regex = /_sharedData = ({.*);<\/script>/m,
        json = JSON.parse(regex.exec(html)[1]),
        edges = json.entry_data.ProfilePage[0].graphql.user.edge_owner_to_timeline_media.edges;

      $.each(edges, function(n, edge) {
          var node = edge.node;
          $('body').append(
              $('<a/>', {
              href: 'https://instagr.am/p/'+node.shortcode,
              target: '_blank'
          }).css({
              backgroundImage: 'url(' + node.thumbnail_src + ')'
          }));
      });
    }
});
html, body {
  font-size: 0;
  line-height: 0;
}

a {
  display: inline-block;
  width: 25%;
  height: 0;
  padding-bottom: 25%;
  background: #eee 50% 50% no-repeat;
  background-size: cover;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

You can download any Instagram user photo feed in JSON format using ?__a=1 next to landing page address like this. No need to get user id or register an app, no tokens, no oAuth.

min_id and max_id variables can be used for pagination, here is example

YQL may not work here inside snipped iframe, so you can always check it manually in YQL Console

APRIL 2018 UPDATE: After latest instagram updates you can't do this on client side (javascript) because custom headers for signed request can't be set with javascript due to CORS Access-Control-Allow-Headers restrictions. It still possible to do this via php or any other server side method with proper signature based on rhx_gis, csrf_token and request parameters. You can read more about it here.

JANUARY 2019 UPDATE: YQL retired, so, check my latest update with Google Image Proxy as CORS proxy for Instagram page! Then only negative moment - pagination not available with this method.

PHP solution:

    $html = file_get_contents('https://instagram.com/apple/');
    preg_match('/_sharedData = ({.*);<\/script>/', $html, $matches);
    $profile_data = json_decode($matches[1])->entry_data->ProfilePage[0]->graphql->user;
350D
  • 11,135
  • 5
  • 36
  • 49
  • I tried but it seems to be we only get about 20 records, could y tell me the way to get all media or photo feed from an instagram account ? – user2659694 Nov 24 '15 at 14:29
  • @user2659694 unfortunately standard url parameters doesn't work in this case – 350D Nov 25 '15 at 05:05
  • 14
    @350D How did you find this? I can't find it anywhere in their documentation. I just want to read more about what is possible with this endpoint (EG square images vs non-square, whether this has plans to end in June, etc) - Thanks! – Phil Johnston Jan 07 '16 at 21:02
  • 9
    @Phil Johnston Just a research Take this another one — you can add /media/?size=L next to the photo landing page URL and get FULL resolution photo. – 350D Jan 07 '16 at 22:00
  • @350D I'd love to know where this research is - do you have a link you could share? I've been searching for a full week now for this. – Phil Johnston Jan 07 '16 at 23:20
  • This is awesome! However, Instagram can shut this down any day. I'm not sure I would use this in an app, etc. :/ It's a shame because this is really nice – CodingMeSwiftly Jan 13 '16 at 23:56
  • 9
    @user2659694 I finally found the solution to get the next pages with this method you can use /media/?max_id=[MAX_ID] – Reza Jan 18 '16 at 18:22
  • 1
    @PhilJohnston today i found that you can get some information about `/media/?size=` in official documentation [here](https://www.instagram.com/developer/embedding/)! – 350D Jan 19 '16 at 16:37
  • How do you get the min_id and max_id? i'm slightly confused i want to get more than 20 images also, I'm using PHP i just cant figure it out. – Kenziiee Flavius Feb 19 '16 at 16:58
  • @KenziieeFlavius you have `items[].id`, so, use this `id` form max/min – 350D Feb 19 '16 at 18:27
  • 1
    Fantastic. Wish they'd put this front and center in the documentation. Wasted half a day looking for a solution this simple. – shacker Mar 02 '16 at 19:57
  • I tried to get more than 20 feeds from instragram using this method, but when I pass max_id or min_id it has no effect I still got the same 20 feeds whatsoever. – Edris Apr 04 '16 at 08:00
  • I've been looking into this as well. The 20 items looks like a sandbox restriction: "Data is restricted to the 10 users and the 20 most recent media from each of those users" from https://www.instagram.com/developer/sandbox/ – bertster Apr 05 '16 at 09:50
  • 4
    FYI this appears to only work if you are logged into an Instagram account yourself. Try doing it in Incognito in Chrome or similar and you will see the JSON response contains no items. I was trying to incorporate this into a script to get the list of URLs on a web server and had to go back to the old authorization methods. – Ryan Zink May 01 '16 at 02:49
  • @350D Is there a way I can have access to my instagram feed like this? instead of just a user feed. – Saber May 24 '16 at 15:34
  • 2
    @RyanZink not true for me - I've even hit it un-authed using Tor – gerbz May 24 '16 at 23:30
  • 9
    @RyanZink were you trying a private account? it works ok for me logged out or incognito on public accounts. – ryan May 24 '16 at 23:30
  • 1
    @VivekSancheti min/max works fine. Just make max_id equal to the 20th id in the previous response. – gerbz May 25 '16 at 01:18
  • @ryan That may have been the difference. The account I was trying was a private account. – Ryan Zink May 25 '16 at 13:02
  • 1
    If you're trying to get around the CORS error in JS, you can make the call on your server instead, or use a reverse proxy. – stephen.hanson Jun 01 '16 at 20:53
  • FYI `count` doesn't work. Even using `max_id` and `min_id` will always return 20 results. If there isn't any more content before/after `max_id`/`min_id` it will still return 20 results. `max_id` and `min_id` are working though as of this comment. – Robbie Trencheny Jun 09 '16 at 01:15
  • For those who need help with pagination: just get the items.id of the last item and pass it in as the `max_id` as shown in above examples. That will then give you the next 20 images. Thanks for the find this is amazing!!! – Micro Jul 17 '16 at 20:19
  • @350D and all. Guys.. How to do this solution using JS. Not able to get response. http://jsfiddle.net/4ozz2nj9/ – bCliks Aug 08 '16 at 15:42
  • 2
    @bCliks No options here, no JSONP or cross-domain available for these endpoints – 350D Aug 09 '16 at 13:52
  • 1
    It seems that this url has a cors problem, and doesn't answer to jsonp request too. – user5363938 Aug 10 '16 at 11:21
  • Awesome solution thanks! Does anyone knows how to get the username from the user id? – João Abrantes Aug 13 '16 at 21:38
  • 1
    I was trying to use jquery and use this code as API '$.getJSON('https://www.instagram.com/smena8m/media/',function (insta) { });' I am getting error _XMLHttpRequest cannot load https://www.instagram.com/smena8m/media/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://s.codepen.io' is therefore not allowed access._ I am trying from codepen. What i am missing? – Hadnazzar Aug 15 '16 at 07:01
  • 2
    @Hadnazzar you missing cross-domain limitations. No cors, no jsonp, no cross-domain available for these endpoints. Server only use. – 350D Aug 15 '16 at 14:02
  • is this possible to get followers count of public profiles without accesstoken?? – Vijaysinh Parmar Sep 08 '16 at 13:09
  • @350D Great...thank you very much... you saved my day.. it worked... can you share me reference link from where you get this?? What other public data I can get? – Vijaysinh Parmar Sep 09 '16 at 04:24
  • 2
    oh my god... why isn't this literally the first thing in Instagram's API docs? – danielgormly Sep 16 '16 at 06:16
  • How can we get multiple user photos ?? Like can we pass multiple user id's seperated by "," ? – Aadil Keshwani Oct 25 '16 at 11:40
  • Thank you for this. I don't know how you found this but thank you so much for sharing! – henk.io Oct 25 '16 at 19:13
  • Is there something similar that I could use to reliably get a user's profile picture? – Luke Taylor Jan 29 '17 at 02:45
  • Is there any C# library that wraps this functionality without having to bother with authentication? – skeletank Jan 31 '17 at 21:46
  • @skeletank this particular: https://www.instagram.com/smena8m/media ? It's available without authentication and is just a plain REST API: you request data from page and receive JSON ;) This is very simple and well documented for C# just google "get and parse JSON c#" – ignacy130 Feb 21 '17 at 20:58
  • @350D based on your research I wrote this https://github.com/whizzzkid/instagram-reverse-proxy – whizzzkid Mar 11 '17 at 10:12
  • @Reza this method wont show all comment texts... limited to 4 last ones. is there a way to see all comments ? (the same for likes and the information about users who liked the post) – AmiNadimi Apr 23 '17 at 18:30
  • Here is a working solution: https://runkit.com/vishnukanwar/scrap-an-instagram-page-s-popular-images – Vishnu Kanwar Jun 17 '17 at 12:13
  • @Legionar Check updated snippet. Old `/media/` endpoint not working today for some reason... – 350D Nov 08 '17 at 16:06
  • @Choletski Check APRIL UPDATE in post – 350D Jun 22 '18 at 19:25
  • hey, thanks for brilliant solution, do you know how to load profile picture using this method ? – zEn feeLo Apr 01 '19 at 23:02
  • @CameronA It's already there, check `user` section in `json` response in snippet example – 350D Apr 02 '19 at 03:37
  • is it possible to get other info like info, name, posts like number ... ? – zEn feeLo Apr 02 '19 at 21:59
  • can you please describe the returned object? – zEn feeLo Apr 02 '19 at 22:07
  • @CameronA log and check your console please – 350D Apr 03 '19 at 15:18
  • 1
    yes thank you , I checked the console and I can access everything about the object – zEn feeLo Apr 04 '19 at 20:47
  • PHP function to download images and create html with links https://stackoverflow.com/questions/17373886/how-can-i-get-a-users-media-from-instagram-without-authenticating-as-a-user/56321726#56321726 – drooh May 27 '19 at 07:44
  • Why isn't it found in their documentation? And how did you manage to get all this information? I'm worried if this endpoint was never meant for public use then it could be shutdown at any moment if proven a security hole. – Shift 'n Tab Jul 25 '20 at 19:49
  • @350D min_id/max_id not working, every time it returns the same result. Have got any update on this? – Yasitha Oct 02 '20 at 02:19
  • 1
    I'm getting 403 forbidden as of the date of this comment. When I visit the URL generated in this request, I get a page that says "We're sorry... but your computer or network may be sending automated queries. To protect our users, we can't process your request right now." It was fun while it lasted!! – kennsorr Apr 01 '21 at 23:30
  • I get Blocked:NotSameOrigin. Also sometimes the images do not show up, please help. – Olajide Olaolorun Apr 27 '21 at 07:03
  • Can anyone help ? – Olajide Olaolorun Jun 09 '21 at 22:20
  • It seems now this required logged-in to an account first. – Sadee Dec 01 '21 at 11:30
  • Works great, no need to log in: `curl https://www.instagram.com/smena8m/?__a=1`. Thanks! – Ulad Kasach Jun 05 '22 at 19:21
128

This is late, but worthwhile if it helps someone as I did not see it in Instagram's documentation.

To perform GET on https://api.instagram.com/v1/users/<user-id>/media/recent/ (at present time of writing) you actually do not need OAuth access token.

You can perform https://api.instagram.com/v1/users/[USER ID]/media/recent/?client_id=[CLIENT ID]

[CLIENT ID] would be valid client id registered in app through manage clients (not related to user whatsoever). You can get [USER ID] from username by performing GET users search request: https://api.instagram.com/v1/users/search?q=[USERNAME]&client_id=[CLIENT ID]

Ersan J Sano
  • 1,384
  • 1
  • 9
  • 8
  • Wow, it looks like you're right. I'm pretty sure it used to respond with some sort of authentication error. Glad they've changed their minds! (Even if it's not documented yet.) – Peeja Dec 12 '13 at 01:03
  • 9
    I think they may have changed their minds again. I'm getting the same error response as shown in the OP – James Jan 26 '14 at 15:50
  • 1
    My mistake, you just need to supply the client_id as documented here: http://instagram.com/developer/authentication/ – James Jan 26 '14 at 16:00
  • can you put a count limit on the media returned? – Asher Jun 05 '15 at 14:05
  • This works great for me, grabbing user id for any user name and then querying the latest for that userid. Thanks – james-see Jun 24 '15 at 00:53
  • 1
    @Asher Just add `&count=5` to the end of the url to get the last 5 items. Replace with any number of items. – jsejcksn Oct 07 '15 at 09:46
  • 37
    This is only valid on apps created before Nov 17 2015, and will not be supported at all after June 2016. After that you will need an oauth access_token. https://instagram.com/developer/changelog/ – Dax Fohl Nov 23 '15 at 17:01
  • 230
    This is so stupid and irritating. Why would they force an access token just to display images that are *already public*? I'm hardly trying to rinse them for every user in the world, I just want to display a client's latest insta without having to spend hours messing with it. Gah! – Matt Fletcher Dec 17 '15 at 14:16
  • 1
    Just a thought: Isn't it possible to query once for an auth token using "https://api.instagram.com/oauth/authorize/?client_id={client_id}&redirect_uri={redirectURI}&response_type=token&scope=public_content" and just use that token for every future request you make? Every instance of your app / web session will query as the same user but what ever if it works? :D – CodingMeSwiftly Jan 13 '16 at 23:46
  • 8
    @Cabus rate limits, mate. – Walf May 25 '16 at 01:56
  • 22
    @MattFletcher it's even more stupid now, one must go through app permission review, and not sure if it's even feasible since this use case "showing client's own feed in their own webpage" is not one of the use cases. Duh, these restrictions suck. – Ciantic Jun 04 '16 at 16:11
  • @ Matt Fletcher you have some idea now, how show public contents frm instgram. i am also have the same issue – Albert Jul 15 '16 at 06:06
  • Oh nooo.. So it's already impossible to fetch another user's instagram photos. That's why my social feeds from different instagramers aren't working anymore. T___T Too bad, even if it's publicly accessible. – jehzlau Oct 24 '16 at 14:56
  • Oh wait, smashballoon's plugin was able to fetched instagram photos without the user's access tokens. So it's still possible displaying other's instagram photos without authentication. :) https://smashballoon.com/instagram-feed/demo/ – jehzlau Oct 24 '16 at 22:33
  • Thanks for the answer. How can we get multiple user photos ?? Like can we pass multiple user id's seperated by "," ? – Aadil Keshwani Oct 25 '16 at 11:39
  • At least with Facebook's API you can just use `app_id|app_secret` as the access token to do public requests – adamj Apr 12 '17 at 01:09
  • You don't have authorization to view this page. HTTP ERROR 403 – Mohsen Molaei Apr 13 '18 at 13:34
61

11.11.2017
Since Instagram changed the way they provide this data, none of above methods work nowadays. Here is the new way to get user's media:
GET https://instagram.com/graphql/query/?query_id=17888483320059182&variables={"id":"1951415043","first":20,"after":null}
Where:
query_id - permanent value: 17888483320059182 (note it might be changed in future).
id - id of the user. It may come with list of users. To get the list of users you can use following request: GET https://www.instagram.com/web/search/topsearch/?context=blended&query=YOUR_QUERY
first - amount of items to get.
after - id of the last item if you want to get items from that id.

Footniko
  • 2,682
  • 2
  • 27
  • 36
  • Could you please let me know from where to get query_id and id of user? – Vijaysinh Parmar Nov 14 '17 at 07:13
  • 2
    @VijaysinhParmar as I mentioned, `query_id` is permanent value. That means it's always **17888483320059182** (at least unless Instagram change it). id of user - is id of user (edited my answer a bit) – Footniko Nov 14 '17 at 12:37
  • 1
    Thanks @Footniko but could you please let me know from where you got this query_id? could you please share any reference to get that? – Vijaysinh Parmar Nov 15 '17 at 06:22
  • 1
    I don't remember exactly, somewhere on the internet. But i don't have any relations with Instagram, so in case it changes i won't be able to tell you the new one :( – Footniko Nov 15 '17 at 11:13
  • 2
    Wonder what is the rate limiting policy of this approach? – kkzxak47 Nov 23 '17 at 05:47
  • 1
    I'm puzzled by this. It works perfectly, and it's trivial to build some HTML to show thumbnails with links to full images from it. But there's no URLs to link back to instagram, to see the full story/comments posted with an image? – Codemonkey Jan 09 '18 at 13:11
  • 1
    Never mind, I was searching for URLs, I see the "shortcode" now which I can build usable URLs from. – Codemonkey Jan 09 '18 at 13:21
  • Has anyone figured out how to get high resolution urls from this thumbnails? – paranoidhominid Jan 13 '18 at 20:08
  • 1
    If anyone have issues with requesting this URL through a CURL request, then you need to get the cookie request header (open Networks tab, after running url, copy cookie header and paste it into curl request header. If you don't do this, you will get a 403 access denied error). – Anders Aug 11 '18 at 20:13
  • 1
    I also checked it throws 403 access denied error. It seem they have blocked it. – OyeHarish Jan 30 '19 at 11:33
  • Any idea how to fetch `Reels`, too? This only returns `Posts`. – Georgios Feb 09 '21 at 10:45
  • 1
    This works great locally but when deployed to a server, it's not working and the response is HTML forcing to login. – yathomasi Sep 10 '21 at 05:23
  • It seems now this is also accessible only for logged-in user same as the other option https://www.instagram.com/{username}/?__a=1 – Sadee Dec 01 '21 at 11:46
52

I was able to get the most recent media of a user using the following API without authentication (including the description, likes, comments count).

https://www.instagram.com/apple/?__a=1

E.g.

https://www.instagram.com/{username}/?__a=1
Michael
  • 1,058
  • 10
  • 17
  • this worked for me. do you have any idea how long this would work?? Could you please provide from where you get this reference? – Vijaysinh Parmar Dec 06 '17 at 06:41
  • 1
    this also worked for me.but when "is_video=true",no video url in data. – didikee Dec 30 '17 at 03:49
  • 4
    Right, you can only get the thumbnails (not the video itself) - unfortunately, I didn't find any official documentation for this and I have no idea if this API is deprecated or how long it's going to be supported. – Michael Jan 11 '18 at 05:21
  • 9
    As of 2018-04-13, this seems to not work anymore. Maybe because of Facebook's latest Cambridge Analytica data scandal, they're tightening things down a ton. Any other suggestions for getting basic user data without authentication? – JasonJensenDev Apr 13 '18 at 18:35
  • 3
    Yes, there was a time that this API wasn't working - But now it's back again – Michael Aug 15 '18 at 04:37
  • 4
    It worked for me, but only when I'm logged in to Instagram. – zundi Sep 07 '18 at 14:14
  • Working for me as of now.. 08/20/2019 – Rishi Aug 21 '19 at 06:25
  • Still working, but I would like to know how to increase the number of nodes returned – Elesin Olalekan Fuad Sep 30 '19 at 12:02
  • @Michael If username can able to modify on Instagram site. So once modified you can't able to get valid data, I think... – Ram Jun 06 '20 at 13:51
  • I'm not sure it's possible to change the username. – Michael Jun 10 '20 at 11:52
15

As of last week, Instagram disabled /media/ URLs, I implemented a workaround, which works pretty well for now.

To solve everyone's problems in this thread, I wrote this: https://github.com/whizzzkid/instagram-reverse-proxy

It provides all of instagram's public data using the following endpoints:

Get user media:

https://igapi.ga/<username>/media
e.g.: https://igapi.ga/whizzzkid/media 

Get user media with limit count:

https://igapi.ga/<username>/media?count=N // 1 < N < 20
e.g.: https://igapi.ga/whizzzkid/media?count=5

Use JSONP:

https://igapi.ga/<username>/media?callback=foo
e.g.: https://igapi.ga/whizzzkid/media?callback=bar

The proxy API also appends next page and previous page URLs to the response so you do not need to calculate that at your end.

double-beep
  • 5,031
  • 17
  • 33
  • 41
whizzzkid
  • 1,174
  • 12
  • 30
  • Works like a charm.. Thanks buddy – Aniket Dhandhukia Jul 21 '17 at 12:03
  • it returns fake data – reza jafari Aug 25 '17 at 07:55
  • This looks great -- any reason you expect IG to block you from providing this service in the future? – rex Sep 01 '17 at 08:45
  • 1
    @rex until they change how things work at their end, we are good! They didn't bother in the last 3 years, probably they won't in the next 3. – whizzzkid Sep 06 '17 at 22:55
  • 3
    @whizzzkid Bad luck, they change it. I saw that you think user endpoint will do the things, but there are limits for requests for not logged in users. Any ideas? – nobilik Nov 08 '17 at 04:41
  • 1
    @nobilik the workaround is in place, https://igpi.ga/whizzzkid/media?count=3 and https://igpi.ga/graphql/query/?user_id=1606740656&count=3 should both return you data. Remember, undefined referrers are disabled for these urls. – whizzzkid Nov 14 '17 at 17:12
  • Great, was using the old media call - glad to see I'm not the only one. Tried your endpoint with my client's username and got the following: {"code":5,"desc":"Referer was denied access."} Any ideas? Thanks! – James Trickey Nov 22 '17 at 02:30
  • @JamesTrickey the prod endpoints reject requests from undefined referers. Try this: http://plnkr.co/4oCwpbMm6p9cyJb1UWld – whizzzkid Nov 22 '17 at 17:48
  • @whizzzkid What is the rate limiting policy of 'graphql/query/'? Have you encountered it in your service? – kkzxak47 Nov 23 '17 at 06:49
  • @whizzzkid Thanks for getting back. I'm not quite sure what I'm looking at though... – James Trickey Nov 23 '17 at 10:28
  • Your call to https://igpi.ga/explore/tags/yyc/media gives me the same result as i mentioned earlier. Not sure where I'm going wrong here. (apologies, i'm an application programmer - totally out of my depthere here) :-) – James Trickey Nov 23 '17 at 10:43
  • This gives me an empty array:"https://igpi.ga/explore/tags/[username]/media". Thanks for ur help. – James Trickey Nov 23 '17 at 10:56
  • @JamesTrickey that's because you're looking on the wrong path. igpi.ga/[username]/media and igpi.ga/explore/tags/[hashtag]/media are two different patterns – whizzzkid Nov 23 '17 at 22:44
  • 1
    @whizzzkid - Got it working! Thanks so much - you are a scholar and a gentleman! – James Trickey Nov 24 '17 at 03:49
  • 1
    I'm getting a "referrer was denied access" error. Maybe this no longer works? – khalid13 Dec 18 '17 at 20:06
  • @khalid13 https://github.com/whizzzkid/instagram-proxy-api/wiki/Why-am-I-getting-referrer-undefined%3F – whizzzkid Dec 21 '17 at 17:31
14

The Instagram API requires user authentication through OAuth to access the recent media endpoint for a user. There doesn't appear to be any other way right now to get all media for a user.

Bill Rollins
  • 1,736
  • 1
  • 12
  • 18
  • 4
    This makes no sense, if I want to display my own media on my own website, why do I need everyone who wants to see it to have an instagram account? – ninjasense Nov 18 '13 at 15:30
  • 5
    ninjasense - I don't think that is how it works. I think your website would need to have a bit of code in it that would query the Instagram API with your oauth credentials provided to pull in your media. You would then show your media to any users of your site. Your site would be the only thing that needed to authenticate with Instagram. – Bill Rawlinson Dec 11 '13 at 21:24
10

Thanks to Instagram's ever changing (and horrifically designed) API schema most of the above will no longer work as of April 2018.

Here is the latest path to access individual post data if you are querying their API directly using the https://www.instagram.com/username/?__a=1 method.

Assuming your returned JSON data is $data you can loop through each result using the following path examples :

foreach ($data->graphql->user->edge_owner_to_timeline_media->edges as $item) {

    $content_id = $item->node->id; 
    $date_posted = $item-node->taken_at_timestamp;
    $comments = $item->node->edge_media_to_comment->count;
    $likes = $item->node->edge_liked_by->count;
    $image = $item->node->display_url;
    $content = $item->node->edge_media_to_caption->edges[0]->node->text;
    // etc etc ....
}

The main things in this recent change were graphql and edge_owner_to_timeline_media.

Looks like they are going to be killing this API access off for non 'business' customers in DEC 2018 so make the most of it while you can.

Hope it helps somebody ;)

spice
  • 1,442
  • 19
  • 35
  • This just helped me, I just want to show the latest instagram posts for a client. Thanks! – weston deboer Apr 12 '18 at 16:50
  • 2
    https://www.instagram.com/username/?__a=1 gives now error: Access to www.instagram.com was denied You don't have authorisation to view this page. HTTP ERROR 403 any other ideas? – Hese Apr 13 '18 at 16:58
  • 2
    Yep Instagram have now killed this off. "To continuously improve Instagram users' privacy and security, we are accelerating the deprecation of Instagram API Platform, making the following changes effective immediately. We understand that this may affect your business or services, and we appreciate your support in keeping our platform secure. These capabilities will be disabled immediately (previously set for July 31, 2018 or December 11, 2018 deprecation). " – spice Apr 16 '18 at 16:53
  • If what I'm reading is correct it will no longer be possible to retrieve images or data from any "non-business" account. They are totally killing off the platform API. I guess that's that then... https://www.instagram.com/developer/changelog/ – spice Apr 16 '18 at 16:58
  • It looks like the https://www.instagram.com/username/?__a=1 url is working again... – JasonJensenDev Apr 16 '18 at 22:30
  • The URL instagram.com/username/?__a=1 seems to have worked temporarily (enough for most of my vendors to update once overnight) and has now stopped working. Think the best thing to do is implement this properly and use the Graph API – james_tookey Apr 17 '18 at 07:55
  • 1
    @james_tookey not gonna be possible mate. Due to their new privacy restrictions it will no longer be able to query or retrieve users / data of personal accounts, only business ones. Basically they just killed all API usage for personal accounts. – spice Apr 17 '18 at 10:45
  • 2020, works fine. curl -I "https://www.instagram.com/onhate/?__a=1" HTTP/2 405 but returns correct data – Marcelo Luiz Onhate Mar 01 '20 at 18:11
  • July 2020 still works, but it only returns 12 most recent media. Is there any way to show all media? – Cid Jul 22 '20 at 04:15
9

Here's a rails solutions. It's kind of back-door, which is actually the front door.

# create a headless browser
b = Watir::Browser.new :phantomjs
uri = 'https://www.instagram.com/explore/tags/' + query
uri = 'https://www.instagram.com/' + query if type == 'user'

b.goto uri

# all data are stored on this page-level object.
o = b.execute_script( 'return window._sharedData;')

b.close

The object you get back varies depending on whether or not it's a user search or a tag search. I get the data like this:

if type == 'user'
  data = o[ 'entry_data' ][ 'ProfilePage' ][ 0 ][ 'user' ][ 'media' ][ 'nodes' ]
  page_info = o[ 'entry_data' ][ 'ProfilePage' ][ 0 ][ 'user' ][ 'media' ][ 'page_info' ]
  max_id = page_info[ 'end_cursor' ]
  has_next_page = page_info[ 'has_next_page' ]
else
  data = o[ 'entry_data' ][ 'TagPage' ][ 0 ][ 'tag' ][ 'media' ][ 'nodes' ]
  page_info = o[ 'entry_data' ][ 'TagPage' ][ 0 ][ 'tag' ][ 'media' ][ 'page_info' ]
  max_id = page_info[ 'end_cursor' ]
  has_next_page = page_info[ 'has_next_page' ]
end

I then get another page of results by constructing a url in the following way:

  uri = 'https://www.instagram.com/explore/tags/' + query_string.to_s\
    + '?&max_id=' + max_id.to_s
  uri = 'https://www.instagram.com/' + query_string.to_s + '?&max_id='\
    + max_id.to_s if type === 'user'
  • this solution is working for me, but I'm having some trouble with it. After loading the data, my rails server (using Rails 5.0.0, Puma 3.6.0 server) restarts inexplicably... Any possible solution? – Luis Eduardo Rojas Cabrera Aug 02 '16 at 20:20
8

If you are looking for a way to generate an access token for use on a single account, you can try this -> https://coderwall.com/p/cfgneq.

I needed a way to use the instagram api to grab all the latest media for a particular account.

Craig Heneveld
  • 389
  • 2
  • 7
  • 5
    This is more or less what I did in the end: made a new account, made an access token for it, and stored that token in my server config next to the API key. This is a poor solution for JS apps, though, since it requires shipping your access token to the user (which I've seen lots of example code do). Luckily for me, I can do it server-side. – Peeja Jul 18 '13 at 12:47
  • 4
    @CraigHeneveld How do you go about keeping hat access_token up to date? Hasn't it expired on you? – Ryan Ore Oct 10 '13 at 12:59
  • Does the token expire some time? – Monitus Apr 17 '15 at 05:42
  • If my memory serves me, the key only expires if you change your password. Here is another thread on the matter -> http://stackoverflow.com/questions/22753170/instagram-access-token-expire – Craig Heneveld Apr 20 '15 at 14:46
  • How can we get multiple user photos ?? Like can we pass multiple user id's seperated by "," ? – Aadil Keshwani Oct 25 '16 at 11:40
8

Just want to add to @350D answer, since it was hard for me to understand.

My logic in code is next:

When calling API first time, i'm calling only https://www.instagram.com/_vull_ /media/. When I receive response, I check boolean value of more_available. If its true, I get the last photo from the array, get its id and then call Instagram API again but this time https://www.instagram.com/_vull_/media/?max_id=1400286183132701451_1642962433.

Important thing to know here, this Id is the Id of the last picture in the array. So when asking for maxId with the last id of the picture in the array, you will get next 20 pictures, and so on.

Hope this clarify things.

Vulovic Vukasin
  • 1,540
  • 2
  • 21
  • 30
8

One more trick, search photos by hashtags:

GET https://www.instagram.com/graphql/query/?query_hash=3e7706b09c6184d5eafd8b032dbcf487&variables={"tag_name":"nature","first":25,"after":""}

Where:

query_hash - permanent value(i belive its hash of 17888483320059182, can be changed in future)

tag_name - the title speaks for itself

first - amount of items to get (I do not know why, but this value does not work as expected. The actual number of returned photos is slightly larger than the value multiplied by 4.5 (about 110 for the value 25, and about 460 for the value 100))

after - id of the last item if you want to get items from that id. Value of end_cursor from JSON response can be used here.

kara4k
  • 407
  • 5
  • 11
7

JSFiddle

Javascript:

$(document).ready(function(){

    var username = "leomessi";
    var max_num_items = 5;

    var jqxhr = $.ajax( "https://www.instagram.com/"+username+"/?__a=1" ).done(function() {
        //alert( "success" );
    }).fail(function() {
        //alert( "error" );
    }).always(function(data) {
        //alert( "complete" )
        items = data.graphql.user.edge_owner_to_timeline_media.edges;
        $.each(items, function(n, item) {
            if( (n+1) <= max_num_items )
            {
                var data_li = "<li><a target='_blank' href='https://www.instagram.com/p/"+item.node.shortcode+"'><img src='" + item.node.thumbnail_src + "'/></a></li>";
                $("ul.instagram").append(data_li);
            }
        });

    });

});

HTML:

<ul class="instagram">
</ul>

CSS:

ul.instagram {
    list-style: none;
}

ul.instagram li {
  float: left;
}

ul.instagram li img {
    height: 100px;
}
Leo
  • 1,753
  • 3
  • 20
  • 23
  • could you please suggest which Instagram API should I choose for search Instagram users and their data like instanavigation.com Should I choose graph API or basic display API? I am using Next.js – Deep Kakkar Jun 30 '23 at 08:42
6

If you want to search users without having clientID and access token:

1: If you want to search all users having your names similar to your search word :

replace SeachName with text you want to search:

https://www.instagram.com/web/search/topsearch/?query=SearchName

2: if you want to search exact same name user :

replace UserName with your desired search Name:

https://www.instagram.com/UserName/?__a=1

Rahul Gusain
  • 269
  • 3
  • 6
4

If you bypass Oauth you probably wouldn't know which instagram user they are. That being said there are a few ways to get instagram images without authentication.

  1. Instagram's API allows you to view a user's most popular images without authenticating. Using the following endpoint: Here is link

  2. Instagram provides rss feeds for tags at this.

  3. Instagram user pages are public, so you can use PHP with CURL to get their page and a DOM parser to search the html for the image tags you want.

user1791574
  • 1,729
  • 2
  • 16
  • 30
Dorian Damon
  • 105
  • 3
3

Well, as /?__a=1 stopped working by now, it's better to use curl and parse the instagram page as written at this answer: Generate access token Instagram API, without having to log in?

altinturk
  • 147
  • 1
  • 13
2

You can use this API to retrieve public info of the instagram user:

https://api.lityapp.com/instagrams/thebrainscoop?limit=2 (edit: broken/malware link on Feb 2021)

If you don't set the limit parameter, the posts are limited at 12 by default

This api was made in SpringBoot with HtmlUnit as you can see in the code:

    public JSONObject getPublicInstagramByUserName(String userName, Integer limit) {
        String html;
        WebClient webClient = new WebClient();
    
        try {
            webClient.getOptions().setCssEnabled(false);
            webClient.getOptions().setJavaScriptEnabled(false);
            webClient.getOptions().setThrowExceptionOnScriptError(false);
            webClient.getCookieManager().setCookiesEnabled(true);
    
            Page page = webClient.getPage("https://www.instagram.com/" + userName);
            WebResponse response = page.getWebResponse();
    
            html = response.getContentAsString();
        } catch (Exception ex) {
            ex.printStackTrace();
    
            throw new RuntimeException("Ocorreu um erro no Instagram");
        }
    
        String prefix = "static/bundles/es6/ProfilePageContainer.js";
        String suffix = "\"";
        String script = html.substring(html.indexOf(prefix));
    
        script = script.substring(0, script.indexOf(suffix));
    
        try {
            Page page = webClient.getPage("https://www.instagram.com/" + script);
            WebResponse response = page.getWebResponse();
    
            script = response.getContentAsString();
        } catch (Exception ex) {
            ex.printStackTrace();
    
            throw new RuntimeException("Ocorreu um erro no Instagram");
        }
    
        prefix = "l.pagination},queryId:\"";
    
        String queryHash = script.substring(script.indexOf(prefix) + prefix.length());
    
        queryHash = queryHash.substring(0, queryHash.indexOf(suffix));
        prefix = "<script type=\"text/javascript\">window._sharedData = ";
        suffix = ";</script>";
        html = html.substring(html.indexOf(prefix) + prefix.length());
        html = html.substring(0, html.indexOf(suffix));
    
        JSONObject json = new JSONObject(html);
        JSONObject entryData = json.getJSONObject("entry_data");
        JSONObject profilePage = (JSONObject) entryData.getJSONArray("ProfilePage").get(0);
        JSONObject graphql = profilePage.getJSONObject("graphql");
        JSONObject user = graphql.getJSONObject("user");
        JSONObject response = new JSONObject();
    
        response.put("id", user.getString("id"));
        response.put("username", user.getString("username"));
        response.put("fullName", user.getString("full_name"));
        response.put("followedBy", user.getJSONObject("edge_followed_by").getLong("count"));
        response.put("following", user.getJSONObject("edge_follow").getLong("count"));
        response.put("isBusinessAccount", user.getBoolean("is_business_account"));
        response.put("photoUrl", user.getString("profile_pic_url"));
        response.put("photoUrlHD", user.getString("profile_pic_url_hd"));
    
        JSONObject edgeOwnerToTimelineMedia = user.getJSONObject("edge_owner_to_timeline_media");
        JSONArray posts = new JSONArray();
    
        try {
            loadPublicInstagramPosts(webClient, queryHash, user.getString("id"), posts, edgeOwnerToTimelineMedia, limit == null ? 12 : limit);
        } catch (Exception ex) {
            ex.printStackTrace();
    
            throw new RuntimeException("Você fez muitas chamadas, tente mais tarde");
        }
    
        response.put("posts", posts);
    
        return response;
    }
    
    private void loadPublicInstagramPosts(WebClient webClient, String queryHash, String userId, JSONArray posts, JSONObject edgeOwnerToTimelineMedia, Integer limit) throws IOException {
        JSONArray edges = edgeOwnerToTimelineMedia.getJSONArray("edges");
    
        for (Object elem : edges) {
            if (limit != null && posts.length() == limit) {
                return;
            }
    
            JSONObject node = ((JSONObject) elem).getJSONObject("node");
    
            if (node.getBoolean("is_video")) {
                continue;
            }
    
            JSONObject post = new JSONObject();
    
            post.put("id", node.getString("id"));
            post.put("shortcode", node.getString("shortcode"));
    
            JSONArray captionEdges = node.getJSONObject("edge_media_to_caption").getJSONArray("edges");
    
            if (captionEdges.length() > 0) {
                JSONObject captionNode = ((JSONObject) captionEdges.get(0)).getJSONObject("node");
    
                post.put("caption", captionNode.getString("text"));
            } else {
                post.put("caption", (Object) null);
            }
    
            post.put("photoUrl", node.getString("display_url"));
    
            JSONObject dimensions = node.getJSONObject("dimensions");
    
            post.put("photoWidth", dimensions.getLong("width"));
            post.put("photoHeight", dimensions.getLong("height"));
    
            JSONArray thumbnailResources = node.getJSONArray("thumbnail_resources");
            JSONArray thumbnails = new JSONArray();
    
            for (Object elem2 : thumbnailResources) {
                JSONObject obj = (JSONObject) elem2;
                JSONObject thumbnail = new JSONObject();
    
                thumbnail.put("photoUrl", obj.getString("src"));
                thumbnail.put("photoWidth", obj.getLong("config_width"));
                thumbnail.put("photoHeight", obj.getLong("config_height"));
                thumbnails.put(thumbnail);
            }
    
            post.put("thumbnails", thumbnails);
            posts.put(post);
        }
    
        JSONObject pageInfo = edgeOwnerToTimelineMedia.getJSONObject("page_info");
    
        if (!pageInfo.getBoolean("has_next_page")) {
            return;
        }
    
        String endCursor = pageInfo.getString("end_cursor");
        String variables = "{\"id\":\"" + userId + "\",\"first\":12,\"after\":\"" + endCursor + "\"}";
    
        String url = "https://www.instagram.com/graphql/query/?query_hash=" + queryHash + "&variables=" + URLEncoder.encode(variables, "UTF-8");
        Page page = webClient.getPage(url);
        WebResponse response = page.getWebResponse();
        String content = response.getContentAsString();
        JSONObject json = new JSONObject(content);
    
        loadPublicInstagramPosts(webClient, queryHash, userId, posts, json.getJSONObject("data").getJSONObject("user").getJSONObject("edge_owner_to_timeline_media"), limit);
    }

It's an example of response:

    {
      "id": "290482318",
      "username": "thebrainscoop",
      "fullName": "Official Fan Page",
      "followedBy": 1023,
      "following": 6,
      "isBusinessAccount": false,
      "photoUrl": "https://scontent-gru2-1.cdninstagram.com/vp/447ffd0262082f373acf3d467435f130/5C709C77/t51.2885-19/11351770_612904665516559_678168252_a.jpg",
      "photoUrlHD": "https://scontent-gru2-1.cdninstagram.com/vp/447ffd0262082f373acf3d467435f130/5C709C77/t51.2885-19/11351770_612904665516559_678168252_a.jpg",
      "posts": [
        {
          "id": "1430331382090378714",
          "shortcode": "BPZjtBUly3a",
          "caption": "If I have any active followers anymore; hello! I'm Brianna, and I created this account when I was just 12 years old to show my love for The Brain Scoop. I'm now nearly finished high school, and just rediscovered it. I just wanted to see if anyone is still active on here, and also correct some of my past mistakes - being a child at the time, I didn't realise I had to credit artists for their work, so I'm going to try to correct that post haste. Also; the font in my bio is horrendous. Why'd I think that was a good idea? Anyway, this is a beautiful artwork of the long-tailed pangolin by @chelsealinaeve . Check her out!",
          "photoUrl": "https://scontent-gru2-1.cdninstagram.com/vp/ab823331376ca46136457f4654bf2880/5CAD48E4/t51.2885-15/e35/16110915_400942200241213_3503127351280009216_n.jpg",
          "photoWidth": 640,
          "photoHeight": 457,
          "thumbnails": [
            {
              "photoUrl": "https://scontent-gru2-1.cdninstagram.com/vp/43b195566d0ef2ad5f4663ff76d62d23/5C76D756/t51.2885-15/e35/c91.0.457.457/s150x150/16110915_400942200241213_3503127351280009216_n.jpg",
              "photoWidth": 150,
              "photoHeight": 150
            },
            {
              "photoUrl": "https://scontent-gru2-1.cdninstagram.com/vp/ae39043a7ac050c56d741d8b4355c185/5C93971C/t51.2885-15/e35/c91.0.457.457/s240x240/16110915_400942200241213_3503127351280009216_n.jpg",
              "photoWidth": 240,
              "photoHeight": 240
            },
            {
              "photoUrl": "https://scontent-gru2-1.cdninstagram.com/vp/ae7a22d09e3ef98d0a6bbf31d621a3b7/5CACBBA6/t51.2885-15/e35/c91.0.457.457/s320x320/16110915_400942200241213_3503127351280009216_n.jpg",
              "photoWidth": 320,
              "photoHeight": 320
            },
            {
              "photoUrl": "https://scontent-gru2-1.cdninstagram.com/vp/1439dc72b70e7c0c0a3afcc30970bb13/5C8E2923/t51.2885-15/e35/c91.0.457.457/16110915_400942200241213_3503127351280009216_n.jpg",
              "photoWidth": 480,
              "photoHeight": 480
            },
            {
              "photoUrl": "https://scontent-gru2-1.cdninstagram.com/vp/1439dc72b70e7c0c0a3afcc30970bb13/5C8E2923/t51.2885-15/e35/c91.0.457.457/16110915_400942200241213_3503127351280009216_n.jpg",
              "photoWidth": 640,
              "photoHeight": 640
            }
          ]
        },
        {
          "id": "442527661838057235",
          "shortcode": "YkLJBXJD8T",
          "caption": null,
          "photoUrl": "https://scontent-gru2-1.cdninstagram.com/vp/dc94b38da679826b9ac94ccd2bcc4928/5C7CDF93/t51.2885-15/e15/11327349_860747310663863_2105199307_n.jpg",
          "photoWidth": 612,
          "photoHeight": 612,
          "thumbnails": [
            {
              "photoUrl": "https://scontent-gru2-1.cdninstagram.com/vp/c1153c6513c44a6463d897e14b2d8f06/5CB13ADD/t51.2885-15/e15/s150x150/11327349_860747310663863_2105199307_n.jpg",
              "photoWidth": 150,
              "photoHeight": 150
            },
            {
              "photoUrl": "https://scontent-gru2-1.cdninstagram.com/vp/47e60ec8bca5a1382cd9ac562439d48c/5CAE6A82/t51.2885-15/e15/s240x240/11327349_860747310663863_2105199307_n.jpg",
              "photoWidth": 240,
              "photoHeight": 240
            },
            {
              "photoUrl": "https://scontent-gru2-1.cdninstagram.com/vp/da0ee5b666ab40e4adc1119e2edca014/5CADCB59/t51.2885-15/e15/s320x320/11327349_860747310663863_2105199307_n.jpg",
              "photoWidth": 320,
              "photoHeight": 320
            },
            {
              "photoUrl": "https://scontent-gru2-1.cdninstagram.com/vp/02ee23571322ea8d0992e81e72f80ef2/5C741048/t51.2885-15/e15/s480x480/11327349_860747310663863_2105199307_n.jpg",
              "photoWidth": 480,
              "photoHeight": 480
            },
            {
              "photoUrl": "https://scontent-gru2-1.cdninstagram.com/vp/dc94b38da679826b9ac94ccd2bcc4928/5C7CDF93/t51.2885-15/e15/11327349_860747310663863_2105199307_n.jpg",
              "photoWidth": 640,
              "photoHeight": 640
            }
          ]
        }
      ]
    }
Flimtix
  • 356
  • 1
  • 4
  • 17
Ruan Barroso
  • 79
  • 1
  • 4
2

I really needed this function but for Wordpress. I fit and it worked perfectly

<script>
    jQuery(function($){
        var name = "caririceara.comcariri";
        $.get("https://images"+~~(Math.random()*33)+"-focus-opensocial.googleusercontent.com/gadgets/proxy?container=none&url=https://www.instagram.com/" + name + "/", function(html) {
            if (html) {
                var regex = /_sharedData = ({.*);<\/script>/m,
                  json = JSON.parse(regex.exec(html)[1]),
                  edges = json.entry_data.ProfilePage[0].graphql.user.edge_owner_to_timeline_media.edges;
              $.each(edges, function(n, edge) {
                   if (n <= 7){
                     var node = edge.node;
                    $('.img_ins').append('<a href="https://instagr.am/p/'+node.shortcode+'" target="_blank"><img src="'+node.thumbnail_src+'" width="150"></a>');
                   }
              });
            }
        });
    }); 
    </script>
Karra Max
  • 112
  • 2
  • 9
1

The below nodejs code scrapes popular Images from an Instagram Page. The function 'ScrapeInstagramPage' takes care of post ageing effect.

var request = require('parse5');
var request = require('request');
var rp      = require('request-promise');
var $       = require('cheerio'); // Basically jQuery for node.js 
const jsdom = require("jsdom");    
const { JSDOM } = jsdom;


function ScrapeInstagramPage (args) {
    dout("ScrapeInstagramPage for username -> " + args.username);
    var query_url = 'https://www.instagram.com/' + args.username + '/';

    var cookieString = '';

    var options = {
        url: query_url,
        method: 'GET',
        headers: {
            'x-requested-with' : 'XMLHttpRequest',
            'accept-language'  : 'en-US,en;q=0.8,pt;q=0.6,hi;q=0.4', 
            'User-Agent'       : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36',
            'referer'          : 'https://www.instagram.com/dress_blouse_designer/',
            'Cookie'           : cookieString,
            'Accept'           : '*/*',
            'Connection'       : 'keep-alive',
            'authority'        : 'www.instagram.com' 
        }
    };


    function dout (msg) {
        if (args.debug) {
            console.log(msg);
        }
    }

    function autoParse(body, response, resolveWithFullResponse) {
        // FIXME: The content type string could contain additional values like the charset. 
        // Consider using the `content-type` library for a robust comparison. 
        if (response.headers['content-type'] === 'application/json') {
            return JSON.parse(body);
        } else if (response.headers['content-type'] === 'text/html') {
            return $.load(body);
        } else {
            return body;
        }
    }

    options.transform = autoParse;


    rp(options)
        .then(function (autoParsedBody) {
            if (args.debug) {
                console.log("Responce of 'Get first user page': ");
                console.log(autoParsedBody);
                console.log("Creating JSDOM from above Responce...");
            }

            const dom = new JSDOM(autoParsedBody.html(), { runScripts: "dangerously" });
            if (args.debug) console.log(dom.window._sharedData); // full data doc form instagram for a page

            var user = dom.window._sharedData.entry_data.ProfilePage[0].user;
            if (args.debug) {
                console.log(user); // page user
                console.log(user.id); // user ID
                console.log(user.full_name); // user full_name
                console.log(user.username); // user username
                console.log(user.followed_by.count); // user followed_by
                console.log(user.profile_pic_url_hd); // user profile pic
                console.log(autoParsedBody.html());
            }

            if (user.is_private) {
                dout ("User account is PRIVATE");
            } else {
                dout ("User account is public");
                GetPostsFromUser(user.id, 5000, undefined);
            }
        })
        .catch(function (err) {
            console.log( "ERROR: " + err );
        });  

    var pop_posts = [];
    function GetPostsFromUser (user_id, first, end_cursor) {
        var end_cursor_str = "";
        if (end_cursor != undefined) {
            end_cursor_str = '&after=' + end_cursor;
        }

        options.url = 'https://www.instagram.com/graphql/query/?query_id=17880160963012870&id=' 
                        + user_id + '&first=' + first + end_cursor_str;

        rp(options)
            .then(function (autoParsedBody) {
                if (autoParsedBody.status === "ok") {
                    if (args.debug) console.log(autoParsedBody.data);
                    var posts = autoParsedBody.data.user.edge_owner_to_timeline_media;

                    // POSTS processing
                    if (posts.edges.length > 0) {
                        //console.log(posts.edges);
                        pop_posts = pop_posts.concat
                        (posts.edges.map(function(e) {
                            var d = new Date();
                            var now_seconds = d.getTime() / 1000;

                            var seconds_since_post = now_seconds - e.node.taken_at_timestamp;
                            //console.log("seconds_since_post: " + seconds_since_post);

                            var ageing = 10; // valuses (1-10]; big value means no ageing
                            var days_since_post = Math.floor(seconds_since_post/(24*60*60));
                            var df = (Math.log(ageing+days_since_post) / (Math.log(ageing)));
                            var likes_per_day = (e.node.edge_liked_by.count / df);
                            // console.log("likes: " + e.node.edge_liked_by.count);
                            //console.log("df: " + df);
                            //console.log("likes_per_day: " + likes_per_day);
                            //return (likes_per_day > 10 * 1000);
                            var obj = {};
                            obj.url = e.node.display_url;
                            obj.likes_per_day = likes_per_day;
                            obj.days_since_post = days_since_post;
                            obj.total_likes = e.node.edge_liked_by.count;
                            return obj;
                        }
                        ));

                        pop_posts.sort(function (b,a) {
                          if (a.likes_per_day < b.likes_per_day)
                            return -1;
                          if (a.likes_per_day > b.likes_per_day)
                            return 1;
                          return 0;
                        });

                        //console.log(pop_posts);

                        pop_posts.forEach(function (obj) {
                            console.log(obj.url);
                        });
                    }

                    if (posts.page_info.has_next_page) {
                        GetPostsFromUser(user_id, first, posts.page_info.end_cursor);
                    }
                } else {
                    console.log( "ERROR: Posts AJAX call not returned good..." );
                }
            })
            .catch(function (err) {
                console.log( "ERROR: " + err );
            }); 
    }
}


ScrapeInstagramPage ({username : "dress_blouse_designer", debug : false});

Try it here

Example: For given a URL 'https://www.instagram.com/dress_blouse_designer/' one may call function

ScrapeInstagramPage ({username : "dress_blouse_designer", debug : false});
Vishnu Kanwar
  • 761
  • 5
  • 22
-1

This works using a simple ajax call and iterating image paths.

        var name = "nasa";
        $.get("https://www.instagram.com/" + name + "/?__a=1", function (data, status) {
            console.log('IG_NODES', data.user.media.nodes);
            $.each(data.user.media.nodes, function (n, item) {
                console.log('ITEMS', item.display_src);
                $('body').append(
                    "<div class='col-md-4'><img class='img-fluid d-block' src='" + item.display_src + "'></div>"
                );
            });
        })
-3

Here is a php script that downloads the images and creates an html file with links on the images. Credit 350D for php version, this is just elaborated..I would suggest putting this is a cron job and firing however often you need. Verified working as of May 2019.

<?
$user = 'smena8m';
$igdata = file_get_contents('https://instagram.com/'.$user.'/');
preg_match('/_sharedData = ({.*);<\/script>/',$igdata,$matches);
$profile_data = json_decode($matches[1])->entry_data->ProfilePage[0]->graphql->user;
$html = '<div class="instagramBox" style="display:inline-grid;grid-template-columns:auto auto auto;">';
$i = 0;
$max = 9;
while($i<$max){
    $imglink = $profile_data->edge_owner_to_timeline_media->edges[$i]->node->shortcode;
    $img = $profile_data->edge_owner_to_timeline_media->edges[$i]->node->thumbnail_resources[0]->src;
    file_put_contents('ig'.$i.'.jpg',file_get_contents($img));
    $html .= '<a href="https://www.instagram.com/p/'.$imglink.'/" target="_blank"><img src="ig'.$i.'.jpg" /></a>';
    $i++;
}
$html .= '</div>';
$instagram = fopen('instagram.html','w');
fwrite($instagram,$html);
fclose($instagram);
?>
drooh
  • 578
  • 4
  • 18
  • 46