Articles

Use MaxURL to Create a Realtime Instagram Collage

New with Max 6.1.7, the maxurl object gives you the ability to easily connect Max with the web using HTTP messages. If you've been thinking about creating a crowd-sourced multimedia patch or a data-driven interactive work, now is a good time to give it a shot. To demonstrate one possible direction, in this tutorial we'll look at creating a Jitter collage with Instagram photos.

Diving In

If you haven't looked inside the maxurl help patch, I recommend you start there and familiarize yourself with the different tabs. There's a lot there and lots of practical examples that will give you an idea of how to use this object in a Max patch. For this tutorial, we'll be using the Javascript version of the object, XMLHttpRequest (should be familar to anyone doing Web development). The easy text manipulation in Javascript and built-in JSON parsing are a huge help for this sort of stuff.

Since we're using the Instagram API to run this, you will need to visit the Instagram developer site to get your own API client ID. If you already have an Instagram account, it's really simple. Keep the client ID handy because you'll need it later.

Setting up the XMLHttpRequest

The "bang" function in our Javascript will be used to create and send our HTTP messages.
function bang()
{
    //create a XMLHttpRequest object
    ajaxreq = new XMLHttpRequest();
    //set the HTTP message to be sent (usually a special formatted URL)
    ajaxreq.open("GET",api_string);
    //set the callback function
    ajaxreq.onreadystatechange = getPictures;
    //send the request
    ajaxreq.send();
}

The message that gets sent in this function is defined by the "api_string" variable. In order to have a valid request, we're going to need to set up a proper request string. By reading over the Instagram API reference, I found that we can get recent popular images by sending the string "https://api.instagram.com/v1/tags/"+tag+"/media/recent?client_id=client-id" Knowing this, we can make this simple function to grab recently popular images:
function popular(){
    api_string = "https://api.instagram.com/v1/media/popular?client_id="+clientID;
    bang();
}

Handling the Response

Back in our bang() function, we need to set up a callback function that gets triggered when the API response comes back. In our case, we are going to get a JSON object describing a collection of images. There's a lot of data that comes in there, but we are only focusing on the source URL of the images themselves. Here is what our callback function looks like:
function getPictures()
{
    payload = JSON.parse(ajaxreq.response);
    imageurl = new Array();
    for (i=0;i < payload.data.length;i++){
        imageurl[i]= payload.data[i].images.standard_resolution.url;
        getImageURL(i);
    }
}

In there we convert the response JSON to a Javascript object (JSON.parse), and for each image in the response we save the names of the image into an array and then call a function that downloads the image to the /media folder of the project.
function getImageURL(image){
        var pname = imageurl[image].replace(/^.*(\\|\/|\:)/, '');
        var pp = new XMLHttpRequest();
        pp.open("GET",imageurl[image]);
        pp._setRequestKey("filename_out",imagepath+pname);
        pp.onreadystatechange= filewriteCallback;
        pp.send();
        outlet(0,pname);
}

Back in the Patcher

Once we've got the image files downloaded we can just take advantage of the auto-populate feature of umenu in our Max patcher to create an easy interface to randomly load those image files in jit.qt.movie. To try a search, you'll want to go in the Max patcher and send a message to the Javascript that sets the client ID (remember that?). Once that is set, you can try sending the "popular" message to trigger the search and download process. Once that is going, you can turn on the qmetro to the right and watch the images accumulate. Try using the "offset" attrui to animate the collage.

Now that you've got the basics in place to start pulling in and using photos, try exploring the API and doing other types of image search. There are also lots of different web APIs that you can explore to connect your Max patch.

by Andrew Benson on June 9, 2014

Creative Commons License
estevancarlos's icon

This looks impressive and I really want to check it out. When I open the project it says I'm missing "jit.*.mxo" and thus I don't see anything in the patch. Is that related to something on my end or something relating to this project?

Screen-Shot-2014-06-09-at-1.11.09-PM.png
png
Andrew Pask's icon

@estevancarlos

Sounds like your Max install is messed up. Try a reinstall of the latest version, and if that does not help, please get in touch with support@

apcuddling's icon

Really into this. Thanks for sharing.
Is there any possible way to tell the script to skip over duplicates? For example, if I command it to find and populate images from a certain hashtag, and then later AGAIN tell it to find and populate images from the same hashtag, it brings in the same images again as well as new ones.

@estevancarlos make sure you place the attachment files in the projects folder within your MAX folder. I had the same problem and that seemed to fix it.

nealriley's icon

@apcuddling -
You could store the id's of the images that were downloaded (maybe in a Dict?), and if the API request returned those images again, you could simply throw them out. You would need some logic to request more images (I think the API provides for a startAt value, or something similar), which would be called if the results returned did not provide enough "new" images.

apcuddling's icon

@nealriley Right. Yeah I noticed that they could be manually removed. But the idea I had was to set up a metro to bang the messages requesting the images. So then it would just keep fetching new images. But if I could find a way to automate the dumping of the duplicates, then I could just let it keep running and the newer images would be added in with out duplicating the old ones. Thanks for the response.

nealriley's icon

Unfortunately I think the Instagram API lacks this capability. The "automating" of this process could come from a JS function you automatically pass the results from the API call to. ie each bang would fetch new images and clean out the dupes.

Hope you get it up and running!

apcuddling's icon

@nealriley Yeah I didn't even entertain the idea that it could be done through the API. I'll toy around with some things and see what happens. I'll post back with any progress. Thanks!

kirkpearson's icon

I'm having the same problem as EstevanCarlos-- tried updating and still got the same result. Anyone know what's up?

Thanks!

Screen-Shot-2014-06-10-at-11.24.25-AM.png
png
Andrew Pask's icon

The implicit loading of jit.*.mxo is expected, as it should already be installed on your machine.

Please describe the problem in more detail to us in support - it maybe be that you have not configured your Instagram ID correctly

Send us screen shots, Max window errors etc

support at cycling 74 dot com

Cheers

-A

kirkpearson's icon

Thanks! I'm afraid it's really just that simple. This error dialogue pops up saying the jit.*.mxo is "implicit." I've never heard of an object called jit.*.mxo, and my computer certainly doesn't have one. Is there supposed to be one installed?

The error message was popping up before and after I registered with Instagram developer. I'd attach some screenshots, I'm just not sure what of, outside of that error box.

Thanks again!

Andrew Pask's icon

@KirkPearson - actually, that isn't really an error and shouldn't slow you down. Any errors in the Max window?

apcuddling's icon

@kirkpearson Not sure if this helps, But I've been messing around with the patch for the last couple of days and have noticed 2 things.

1. Make sure when you unarchived the files that they were placed in the projects folder.
2. Make sure that the Client ID for the Instagram API is getting inputted correctly.

Things seem to be working fine for me. I would like to note though, that the "jit.*.mxo" is still highlighted red in the project window. But everything is working the way what I want it to.

Good luck.

apcuddling's icon

@nealriley

and all

Found a way to prevent the patch from including duplicate images. I know it works on my Mac and it may work on windows. But it all depends on how you have your computer set up to handle files with the same name...

-Open up the inspector for the umenu that lists the names of the included images that were grabbed from Instagram and stored in the media folder.
-Click on the ALL tab.
-Under the FILES section, click the EDIT button next to FILE TYPES and type in ".jpg"

What happens is when you fetch for more instagram images of the same hashtag or category, they are all stored in the same folder together (the media folder).
Mac OS automatically adds a number to the end of a filename if a file with same name already exists in that location. It will add a (1) or a (2) and so on.
However, it adds it AFTER the file extension (.jpg).
So, in turn, umenu won't include those images to be populated and used in the patch because it doesn't register them as being a .jpg file.

The duplicates will still be stored in the media folder, but umenu will just look over them when they are being populated into the patch.

Again, like I said, not sure if this will work for everybody as it could depend on how your computer or OS handles documents of the same name.

But it worked for me.

Take care!

Screen-Shot-2014-06-10-at-12.07.42-PM.png
png
hhelt's icon

same error here :-(

inside the project window under other:
jit*.mxo (implicit)

and in the message window:

js: bad outlet index 1 [instagtest.js]
instagtest.js: Javascript SyntaxError: JSON.parse, line 32

mac osx 10.8.5
mac 6.1.7

kirkpearson's icon

For some reason, none of the images are even downloading. There seems to be a variable problem on line 15 in the code. When tagsearch is banged, the .js window says "XMLHttpRequest is not defined, line 15." Despite the problem being so simple, I actually can't find any deficiency in the code.

hzd's icon

Sorry if this sounds really stupid, but if I don't have a web site, can I still get a client ID?

apcuddling's icon

@hzd I don't think you have to have a website. I have a website that I used when entering in the info, but I haven't used it in regards to the Instagram API. I just entered it so that I could continue and get the Client ID. I would imagine you could type in any random website url. But who knows. Good luck.

dvdsmoke's icon

@hhelt

and all:

i was having the same problem you all were having but i fixed it. previously i had entered my client ID in the message box incorrectly with my id number inside the "<>" . when i deleted the little "<>" the patch started working. so whatever problem you're encountering probably has to do with your client id

dvdsmoke's icon

has anybody spent much time with this yet? i would like to be able to use this to generate images with a specific hashtag and only those images. it's hard to completely understand what is actually happening onscreen. i'm sending it a "tagsearch" message and it seems to bring up all of the previous tagsearches i have made and maybe even the popular page as well? hard to tell.

i want to use this for a performance tomorrow in which i/the audience will be taking pictures/uploading to instagram during the performance. anyone present can tag their photo with the special hashtag for the evening. i'll do a "tagsearch" for that hashtag in max and project the result on a large screen, so that everyone (with a smart phone) can contribute to the visual spectacle. does that make sense?

yes, i just want to be able to make this thing generate images of only one hashtag.

dvdsmoke's icon

i'm asking for help if that wasn't clear.

apcuddling's icon

@dvdsmoke what you're saying makes perfect sense.

See if this helps...

When you tell the patch to grab photos from instagram (be it "popular" or a specified hashtag), it grabs them and then saves them to a file on your hard drive. When you tell the patch to "populate" the found pictures, it just loads what is in that folder. That's why you keep seeing previous pictures showing up.

Assuming you're using a mac, this folder it located in "/Applications/Max 6.1/projects/media".

Inside the media folder you will find a bunch of pictures. If you delete all of those, you can start fresh.

Knowing this also allows you to place pictures into the folder as well.

Hope this helps.
Good luck!

Screen-Shot-2014-06-12-at-5.35.43-PM.png
png
hzd's icon

Sorry, if I'm the one asking newbie questions, but I'm not at all familiar with web stuff, like urls and OAuth or what you kids like to call it now a days :)

In web site, as I don't have a web site of my own, I could for instance use the web site of the recordcompany that I use?
and "OAuth redirect_uri:"…. what is that?

As I said, I'm in way over my head with this stuff, but when I get this into Max, I can do magic :)

Sukandar Kartadinata's icon

I have exactly the same error messages as HHELT.
DVDSMOKE's suggestion doesn't apply - my ID isn't inside <>.
Besides I get the first part of the error message (js: bad outlet index 1 [instagtest.js]) on opening the patch, i.e. before I even send the message with the client ID to the javascript.

petcode's icon

on my machine i get the same errors as Sukandar Kartadinata and HHELT
it seems, that there must be something wrong with the patch.

cheers,
petcode

Sukandar Kartadinata's icon

OK, here's what fixed it for me.
1. In the javascript I had to delete line 10, instead calling init() from the Max patch (messagebox with "init" connected to the input of the js object). This took care of the "bad outlet index" message
2. The other problem was that I used my Instagram user ID instead of the developer client ID, duh. Should have read the explanation before diving into the patch...

kirkpearson's icon

@SUKANDAR KARTADINATA, thanks! For some reason, I'm still getting a "XMLHttpRequest is not defined, line 13" message inside the javascript. Do you know what's up with that?

Screen-Shot-2014-06-13-at-12.28.12-PM.png
png
Sukandar Kartadinata's icon

@kirkpearson
sorry, can't help much here. I didn't get this error message during my debugging. upon which message did you get it? (init, setID, or tagsearch)

dvdsmoke's icon

@apcuddling thanks! that worked.

@hzd you can put in whatever website you want. i used cia.gov

Andrew Benson's icon

@kirkpearson Please check that you have the latest version of Max installed from the DOWNLOAD page of this site. This feature was introduced in Max 6.1.7, so any previous versions won't have the ability to run this code. I look forward to seeing what you all create with this new feature. I also encourage everyone to visit the Wiki page linked in the article for future updates and other web examples, or add your own.

dvdsmoke's icon

i've got this patch working pretty functionally, but....

eventually i get these two lines of error in the max window:

maxurl: Failed to connect to 2a03:2880:2130:9f02:face:b00c::1: No route to host
instagtest.js: Javascript SyntaxError: JSON.parse, line 32

so the patch will still (mostly) work even with these errors but it will no longer "refresh" the feed. i think these errors might be coming up because i'm "refreshing" the feed too frequently, but i can't be sure. it fixes itself when i restart max. and the internet connection appears to be working fine.

any thoughts on this?

hzd's icon

So I got it to work. I understood, that I could use any web site, but I didn't get, that I could use the same url for both fields. Duh :)

So, now some questions.
It only finds images from open profiles. Is it somehow possible, to log into my instagram, so I can use images shared with me?

Thx so far :)

dvdsmoke's icon

@hzd

hey i figured out how to allow this patch to access your personal feed. it's a little complicated so follow closely.

first:
- go to http://instagram.com/developer/api-console/
- when you open this page a pop up menu should appear.
- under the first part labeled USERS click "GET" next to where it says users/self/feed
- before you can send this request, you need an authentication
- see the "authentication" drop down menu? if you are logged in to Instagram, then one of the options when you click on it should be "instagram - authenticated user." select that. if you are not logged in, then at some point it should ask you to log in.
- click the orange button that says "send"
- if you have done everything correctly up to this point, then the RESPONSE section on the lower right side should come back with a message in green letters that says "OK"
- keep this page open in your internet browser. we are going to come back to it.

next:
- go back into your max patch
- double click on the "js instaG.js" object
- copy and paste the following code into there, maybe do it below the "function tagsearch" command

ok we are almost there:
- the link in the code i have pasted above is abitrary and will not give you anyone's feed. i just put it there because it shows the proper syntax
- you now want to go back to the api console where we made the request.
- in the column labeled REQUEST, it should say GET and then a link beginning with v1/users/self, etc...
- copy this link and paste it into the code on the max patch, replacing the arbitrary link i gave you
- make sure the link looks right, no extraneous text or whatever, etc
- now make sure to SAVE the code

THIS SHOULD BE ALL YOU NEED! now you can send the message "feed" to the "js instaG.js" object and it should work.

apcuddling's icon

@llcooljeans

(This won't solve you problem but I think it may help to keep in mind when moving forward.)

I'm fairly new to jitter and still getting used to it and I could be wrong on this, but...

From what I can tell the patch AS IS will display video files but will only display a still image as the output.

I would like to mention that I did NOT have the patch load instagram videos through API.

Instead I loaded some .mov files into the media folder where the found instagram images are dropped in. Then I told the umenu to only recognize .mov files.

The patch worked as normal but only displayed the .mov files as a still image as if it were an image file.

I imagine something else will need to be changed in the patch to tell the video files to automatically play.

I'll toy around with it some more and let you know if I come across a solution.

Good luck!

truet85's icon

HI,

Im really struggling to get this patch to work mainly due to my lack of knowledge of Java Script and API. Please find what I have entered in Java Script below. Please could someone point me in the right direction to link this patch to my instagram developer account?

function bang()
{

    ajaxreq = new XMLHttpRequest();

    ajaxreq.onreadystatechange = getPictures;

    ajaxreq.send();
}

function setID(id){

    clientID = 000000000000000;

hzd's icon

Hello everybody. Cheers @dvdsmoke
I now have set this up, so it only gets files from my instagram user account.
Next thing :) How do I narrow it down to a tag in my user? So that it only shows pictures from my account with a sertain tag.

I will try to figure something out, but my javascript knowledge is comparable to a small rock :)

thx
Heðin

apcuddling's icon

@truet85

Not sure if this will help you out much...

I have my patch set up where the [js instagtest.js] is reading outside messages being sent that designate specific script details.

I'm not all that well versed in javascript either and it did take me awhile to get the patch to finally work correctly the way I wanted...but maybe these attached screen caps will help.

Good luck!

Screen-Shot-2014-10-21-at-10.14.23-PM.png
png
Screen-Shot-2014-10-21-at-10.12.03-PM.png
png
truet85's icon

@apcuddling

Thank you for the help all appears to be working now!

Spa's icon

hi andrew,
once i've got:
payload = JSON.parse(ajaxreq.response);

i'd like to pass this payload to a dict object in the patch.
i'd like to write this json to a file on disk.

How do you do that inside the JS
is payload a json structure, a javascript obj, etc...?

Julien Bayle's icon

Hi dear you!

Did you already try to subscribe to tags' update notifications using Max ?

I asked the question there in order to keep the reference in the forum: https://cycling74.com/forums/instagram-api-realtime-notifications-within-max

nilzie's icon

Thanks for sharing this beautiful patch :-)

Dana Karwas's icon

Hi,
How can i grab more than 20 images? And how can I grab them for a specific time?
Has anyone adjusted the js file to use pagination with next_url? The instagram API has some info about pagination and if there are more than 20 images the pagination will give the next_url.

I need to download all the images for a certain hashtag from one day in March.

Thanks
D.K.

hzd's icon

Any luck in Max7?

I had this working in Max6 but it won't work in 7.

I did a new download and to no avail.

I get this message in the max console:
"maxurl . Could not resolve proxy: ers; nodename nor server name provided, or not known"

I have set the ID from the instagram api.

Any ideas?

hzd's icon

Works again, after upgrading to Yosemite.

QiangPan Chen's icon

For whom want to have more than 20 pictures from Instagram, I figured out how to do that in the original code:

add one line to end of the getPictures() function:

function getPictures()
{
    payload = JSON.parse(ajaxreq.response);
    imageurl = new Array();
    for (i=0;i
        imageurl[i]= payload.data[i].images.standard_resolution.url;
        getImageURL(i);
    }
    api_string = payload.pagination.next_url;
}

Then next time when you using getPictures, it will return you the next 20 pictures from next pagination, and update the api_string to next next one.

Matt Hourigan's icon

getting this error in the console

instagtest.js: Javascript TypeError: payload.data is undefined, line 34

Any ideas how to resolve this?

Screen-Shot-2015-10-08-at-5.12.31-PM.png
png
Matt Hourigan's icon

What is jit.*.mxo? —the path is missing in the project window.
I'm getting an error in the console: instagtest.js: Javascript TypeError: payload.data is undefined, line 34

milkhausen's icon

Thanks everyone for all the troubleshooting help so far - I share some issues with others here and still haven't had any success with this. I'm using MAX 7. There are the following console errors:

When I send the "tagsearch dog" message:

instagtest.js: Javascript TypeError: payload.data is undefined, line 33

When I send the "popular" message:

instagtest.js: Javascript SyntaxError: JSON.parse, line 31

Anytime I switch on the graphics:

jit.movie: unsupported file type

Cheers!

Screen-Shot-2015-12-07-at-02.00.00.png
png
Screen-Shot-2015-12-07-at-02.00.53.png
png
hzd's icon

Anyone know, if it is possible, te extract the caption from a given instagram?

Ryan's icon

to fix the payload undefined error, Instagram now wants you to put your Access_Token instead of your clientID. I created an access token with my Instagram developers account. I then added an AccessToken function to the javascript:

var AccessToken;

function AccessToken(id){
    //you need a valid Instagram access_token to use this example
    //visit http://instagram.com/developer to get one
    AccessToken = id;
}

and changed the tagsearch and popular strings to include the access_token instead of ClientID

function tagsearch(tag){
    api_string = "https://api.instagram.com/v1/tags/"+tag+"/media/recent?access_token="+AccessToken;
    bang();
}

function popular(){
    api_string = "https://api.instagram.com/v1/media/popular?access_token="+AccessToken;
    bang();
}

then I sent the new access_token value from max in a message:
AccessToken mylongtokenNumberprovidedbyInstragram

Dru's icon

Thanks Ryan, that worked. However if you only register a new app instagram, it goes in Sandbox Mode and public content is not available. You have to properly register your app with them and make a submission to go live. Other wise you can still use it but don't get access to public_content.

So if you use an access token gotten through a sandbox app, you'll get this response from any reqest you try to make:

{"pagination":{"deprecation_warning":"next_max_id and min_id are deprecated for this endpoint; use min_tag_id and max_tag_id instead"},"meta":{"code":200},"data":[]}

someone had this issue reported on stack overflow, and somebody replied with a valid access token which I'm still using... hehe

You also need to uncheck the Disable implicit OAuth in the security tab of your instagram client app if you're app client is live but still not working.

Last thing,
the images url from the JSON response have a query sring at the end that looks like this :
4532622_1878004650_n.jpg?ig_cache_key=MTIxODg4OTkyNzI3NDgzNzUxNw%3D%3D.2.l

You need to get rid of it, otherwise it on save on you're desktop. cause you know.. .jpg?ig_cache... is not a file format... (at least it did not work for me on windows)...

So I changed the getImagURL function by adding a second replace to pname... you can surely use a nicer regex that does this without repetition, but I was lazy.

function getImageURL(image){
        var pname = imageurl[image].replace(/^.*(\\|\/|\:)/, '').replace(/(jpg\?.*)/,"jpg");
        var pp = new XMLHttpRequest();
        pp.open("GET",imageurl[image]);
        pp._setRequestKey("filename_out",imagepath+pname);
        pp.onreadystatechange= filewriteCallback;
        pp.send();
        outlet(0,pname);
}

Julien Bayle's icon

(cannot stop notifications on this topic. any ideas?)

C74 Ginger's icon

If you uncheck the "Notify me..." box under the comment section, it should update your preferences.

mattafunk's icon

hi all,

i'm trying to use this patch but doesn't work,

i create a new client inside http://instagram.com/developer (that is in sandbox mode, but i don't understand if is enough to run this example)

i got the access token from Instagram, and changed the js with the Ryan's indication.

but when i send the message "AccessToken", after send "setID" the .js say "no function AccessToken"
even with this code inside

var AccessToken;

function AccessToken(id){
//you need a valid Instagram access_token to use this example
//visit http://instagram.com/developer to get one
AccessToken = id;
}

and naturally when try to use tag search i got the payload error.

fluxosonoro's icon

In my case it dosnt work too, as you can see in the image i have the message js: bad outlet index 1 [instagtest.js]
I put my ID setID 9419a019d1eb45f29fe20e78be6679bd but nothing happen... Any idea to solve this?... Best!

Captura-de-pantalla-2016-05-23-a-las-14.26.31.png
png
fluxosonoro's icon

I have the same problem with jit.*.mxo and with js: bad outlet index 1 [instagtest.js]

Does anyone resolve this please??.. Best!

Captura-de-pantalla-2016-05-23-a-las-14.26.311.png
png
Luca De Rosso's icon

Has anyone experienced maxurl's connection timeouts sort of blocking any future connection? After the above mentioned fixes, this patch works great for the first two hours or so, then I get a connection timeout and the only way to make it work again is to quit Max. Thoughts?

Cleia Dantas's icon

I followed the instructions from Ryan (March 24, 2016)
I still can't get it to work.
Using Max 7.3.4
My Instagram account is on Sandbox

PereVicalet's icon

Hello guys, any progress with it? Does anybody know how to going into insta stories from max with jitter? Thank you very much.