Is there anyway to use paging for the media results obtained using the Instagram Basic Display API? I’ve read the following documentations but they don’t have any examples for using pagination:
- https://developers.facebook.com/docs/instagram-basic-display-api/reference/media/children
- https://developers.facebook.com/docs/graph-api/using-graph-api#paging
I would like to limit the media returned in the response e.g. media 1-15 for the first call, then get the next set e.g. 16-30 in the next call.
TIA
3
Answers
Found an answer by playing around with the pagination parameters from this documentation: https://developers.facebook.com/docs/graph-api/using-graph-api#paging
Currently, the Basic Display API returns the most recent 20 media by default. If you want to return more or less than this, use the following url:
https://graph.instagram.com/{user-id}/media?fields={media-fields-you-want-to-return}&access_token={access-token}&limit={number-of-media-you-want-to-return}
To do pagination, you need to have a "next" endpoint to call. To try this out, limit your first call to less than the number of media that you have. You should get 3 endpoints for pagination:
Now add your next endpoint to the original url above: https://graph.instagram.com/{user-id}/media?fields={media-fields-you-want-to-return}&access_token={access-token}&limit={number-of-media-you-want-to-return}&next={next-endpoint}
I was not able to get things working with the answer by CDS. Instead, used an approach that looks for the "next" tag in the returned json formatted string, and used that directly.
In my case, I have built a Storage Access Framework implementation for Instagram, and so here is the flow:
In the "add rows" call that the SAF makes to my provider, I do the initial query of Instagram:
This method in turn looks like:
The initial check has to do with a constant DEFAULT_MEDIA_SERVICE_ACCESS_TOKEN_DEFAULT which is initialized elsewhere in my DocumentsProvider as a default value which means they haven’t yet entered their Instagram credentials, so in that case I bail out.
Where you see calls to "InTouchUtils", this is my own class that encapsulates a bunch of utility functions, like using Volley to make the web API calls.
This method gets called from a couple of places in the DocumentsProvider, so one of the parameters is whether I am processing
nextPageUrl
or not. If not (nextPageUrl is null), we construct the default URL, in which I am calling the Media "Edge" API for the given user. This method puts the limit in the params hashtable along with the Instagram access token (which are both defined in the preferences aspect of my app), and the fields string.Note that if
nextPageUrl
IS passed in, then I completely bypass creating this url, and simply usenextPageUrl
instead.Here is the
callWebsiteFunction
code fromInTouchUtils
that uses Volley in synchronous mode to make the website API call (this entire code sample is already being run on a separate thread, and I have given INTERNET permission in my app):Now that I have a result, I can process it. The first thing to do is convert the string to a JSONObject so I can start to parse it. Then see if I got back a JSONArray of media items by parsing out the "data" key (constant
MEDIA_DATA_ARRAY
in my code).For my purposes, what I want to do is normalize my returned data to a complete list of images and/or videos – so I have to check to see if what got returned is a CAROUSEL_ALBUM type, and if so I make another call to get the media children of that CAROUSEL.
Ultimately, I repackage all the media entries, plus any pagination that was returned from Instagram, and return that back to the caller.
Now back in the caller, I can inspect what I got, and see if I have pagination going on, in particular a "next" url.
If I don’t have one, then I reset the SAF "loading" flag (this is an SAF thing that causes an indeterminate progress bar to show or not show back in the file chooser while your provider is doing work fetching more entries) and I’m done. Notice that the definition of "I don’t have one" is if EITHER the "paging" element or the "next" element are not present. This is because it is possible you won’t get a paging element at all, or you do get a paging element and you don’t get a "next" element within it.
If I do, I indicate to the SAF that I am "loading", then I start a thread ("BatchFetcher") that essentially loops doing the same call to query Instagram, but passing in the "next" url as long as it finds one:
The thread "batchFetcher" handles checking the return value for media items and continues in a loop until no more entries are found, no more "next url" is returned from Instagram, or until it is interrupted.
It populates an internal cache, which is read on the subsequent request from the SAF to my provider, until there are no more to fetch, in which case the "loading" aspect of the cursor is reset and the SAF will stop requesting data from my provider.
Here is the simple python function I have created on @CDS answer.