Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
August 28 2014 - InstaRss
{
"require": {
"php": "^7.0.0"
}
}
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"content-hash": "ba93918fe5641d588ab528e4bba94046",
"packages": [],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": "^7.0.0"
},
"platform-dev": []
}

Instarss

I was looking around for a way to get a user's public Instagram feed as an RSS feed without using the Instagram API when I came across this question on Stack Overflow.

Probably the best way to do this, would be to use the Instagram API. However, I had no desire to sign up for an Instagram account.

Initially, this answer on Stack Overflow suited my needs quite well. However, as fate would have it, Instagram changed its HTML output and the page's JSON data structure changed. Since the idea is quite simple (we're just screen scrapping here) I decided to write my own script. If this works well for you, consider upvoting my answer on Stack Overflow: http://stackoverflow.com/a/25559442/1171790

EDIT August 2017: I no longer support this scipt. The Instagram HTML output of any given user page changes often and it's been a fun game of cat and mouse but I no longer have a need for an Instagram user RSS. If someone else wants to submit a pull request to this Gist that supports the current Instagram output, I'd be happy to merge your changes. Thanks!

EDIT Septemeber 2017: I decided to continue supporting this script, for now. I got a couple emailed requests for support. I added changes and instructions to help people set it up on Heroku.

EDIT March 2018: This script will not be supported anymore but you get the idea - we are scraping the JSON object off of the page with PHP.

Example usage

Upload the script to your own server with PHP installed and then call the script via curl or in your web browser.

Getting a user's Instagram feed as an RSS feed: instarss.php?user=username

Getting an RSS feed of Instagram tags (aka hashtags): instarss.php?hashtag=carshow

Gotchas

Since your RSS reader will be checking for new content on some sort of interval and since Instagram provides the latest 20 photos/videos on a user's homepage, there is a potential for some content to be overlooked. In the event that more than 20 posts have been posted since the script last checked for new content, some content could be missed. Setting your RSS reader to check the instarss.php script often, will work around this. Alternatively, you can checkout this script which probably handles pagination.

Deploy Instarss on Heroku

If you'd like to use this script, it's probably easiest to set it up on a Heroku instance.

  1. First, clone this repository: git clone https://gist.github.com/48c46d9fc2913fba3292.git and then cd into the project directory.

  2. Login to Heroku and create a new app.

  3. And then login to Heroku via the command line: heroku login

  4. Then add Heroku as a remote: heroku git:remote -a your-projects-name

  5. git push heroku master

You can then access Instarss at a URL like: https://your-projects-name.herokuapp.com/instarss.php?user=snoopdogg

<?php
if (!isset($_GET['user'])) {
if (!isset($_GET['hashtag'])) {
exit('Not a valid RSS feed. You didn\'nt provide an Instagram user or hashtag. Send one via a GET variable. Example: mysite.com/instarss.php?user=snoopdogg');
}
}
if (isset($_GET['user']) && isset($_GET['hashtag'])) {
exit('Don\'t request both user and hashtag. Request one or the other.');
}
if (isset($_GET['user'])) {
$html = file_get_contents('http://instagram.com/'.$_GET['user'].'/');
}
if (isset($_GET['hashtag'])) {
$html = file_get_contents('http://instagram.com/explore/tags/'.$_GET['hashtag'].'/');
}
$html = strstr($html, '"entry_data');
$html = strstr($html, '</script>', true);
$html = substr($html, 0, -1);
$html = '{'.$html;
// For debugging... (like when Instagram changes its HTML page output).
// echo $html;
$data = json_decode($html);
// More debugging...
// print_r($data->entry_data->ProfilePage[0]->user->media->nodes);
// exit();
if (isset($_GET['user'])) {
if ($data->entry_data->ProfilePage[0]->user->media->nodes) {
$nodes = $data->entry_data->ProfilePage[0]->user->media->nodes;
} else {
exit('Looks like this Instagram account is set to private or doesn\'t exist. We can\'t do much about that now, can we?');
}
}
if (isset($_GET['hashtag'])) {
$nodes = $data->entry_data->TagPage[0]->tag->media->nodes;
}
header('Content-Type: text/xml; charset=utf-8');
$rss_feed = '<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel>';
if (isset($_GET['user'])) {
$rss_feed .= '<title>'.$_GET['user'].'\'s Instagram Feed</title><atom:link href="http://'.$_SERVER['HTTP_HOST'].$_SERVER["REQUEST_URI"].'" rel="self" type="application/rss+xml" /><link>http://instagram.com/'.$_GET['user'].'</link><description>'.$_GET['user'].'\'s Instagram Feed</description>';
}
if (isset($_GET['hashtag'])) {
$rss_feed .= '<title>Photos tagged with: '.$_GET['hashtag'].' on Instagram</title><atom:link href="http://'.$_SERVER['HTTP_HOST'].$_SERVER["REQUEST_URI"].'" rel="self" type="application/rss+xml" /><link>http://instagram.com/explore/tags/'.$_GET['hashtag'].'</link><description>Photos tagged with: '.$_GET['hashtag'].' on Instagram</description>';
}
foreach($nodes as $node) {
$rss_feed .= '<item><title>';
if (isset($node->caption) && $node->caption != '') {
$rss_feed .= htmlspecialchars($node->caption, ENT_QUOTES);
} else {
$rss_feed .= 'photo';
}
// <pubDate> format could also be: "D, d M Y H:i:s T"
$rss_feed .= '</title><link>https://instagram.com/p/'.$node->code.'/</link><pubDate>'.date("r", $node->date).'</pubDate>';
if (isset($_GET['user'])) {
$rss_feed .= '<dc:creator><![CDATA['.$_GET['user'].']]></dc:creator>';
}
$rss_feed .= '<description><![CDATA[<img src="'.$node->display_src.'" />]]></description><guid>https://instagram.com/p/'.$node->code.'/</guid></item>';
} // foreach "node" (aka photo)
$rss_feed .= '</channel></rss>';
echo $rss_feed;
web: vendor/bin/heroku-php-apache2
@jonathanbell

This comment has been minimized.

Copy link
Owner Author

jonathanbell commented Aug 29, 2014

Works now (August 2014) until Instagram changes up its json format (again).
Usage: http://yourserver.com/instarss.php?user=snoopdogg

@mscreenie

This comment has been minimized.

Copy link

mscreenie commented Apr 15, 2015

Interesting. Will test and see if this works. I'll try if not looks like I'll have to sign up to Instagram and get their API.

@jonathanbell

This comment has been minimized.

Copy link
Owner Author

jonathanbell commented Jun 29, 2015

Updated as the output from instagram was changed (naturally...).

@adarwash

This comment has been minimized.

Copy link

adarwash commented Jul 9, 2015

This is really handy, thanks :)

@adarwash

This comment has been minimized.

Copy link

adarwash commented Jul 18, 2015

Not working now :(

@adarwash

This comment has been minimized.

Copy link

adarwash commented Jul 19, 2015

it works with any other users but not with emzstuff

@jonathanbell

This comment has been minimized.

Copy link
Owner Author

jonathanbell commented Oct 22, 2015

@kamaleao Updated. The Instagram JSON object changed a little. Should work now. Check gist revision history for changes. Cheers!

@mateussouzaweb

This comment has been minimized.

Copy link

mateussouzaweb commented Oct 26, 2015

@kamaleao To make compatible with PHP 5.2, just replace line 28 with:

$rss_feed .= htmlspecialchars($node->caption, ENT_QUOTES);
@mxwright

This comment has been minimized.

Copy link

mxwright commented Dec 15, 2015

@kamaleao try replacing line 10

$html = strstr($html, '{"qs');

with this:

$html = strstr($html, '{"country_code');
@jonathanbell

This comment has been minimized.

Copy link
Owner Author

jonathanbell commented Dec 30, 2015

@mxwright, thanks for the fix! This is starting to become a bit of a moving target with Instagram updating the output of their pages more often than we'd like. I'm starting to get tired of maintaining this. You guys get the idea though, we are basically screen scraping a JSON object on the page into PHP and making the RSS (XML) feed.

Kinda annoying how GitHub Gists don't notify me about comments. Anybody know about that?

I made the suggested changes to the code above. Thanks all.

If people don't stop hotlinking to the demo, I'm going to have to take it down. Please don't do that! Host the file on your own server, please.

@xdmedia

This comment has been minimized.

Copy link

xdmedia commented Feb 5, 2016

Is it outdated again? My file doesn't work anymore since yesterday, but your hosted demo file does.

@jonathanbell

This comment has been minimized.

Copy link
Owner Author

jonathanbell commented Mar 2, 2016

@xdmedia Make sure your host didn't change your version of PHP?? And make sure that the Instagram user's account is not private.

@BCwhoLikesPHP

This comment has been minimized.

Copy link

BCwhoLikesPHP commented Mar 9, 2016

Awesome work on this Jonathan, thanks so much! Might it possible to make this script work for #hashtags too? Like

https://www.instagram.com/explore/tags/carshow/

@jonathanbell

This comment has been minimized.

Copy link
Owner Author

jonathanbell commented Mar 31, 2016

@BCwhoLikesPHP See my recent edit. I think that'll work for ya.
http://yourserver.com/instarss/instarss.php?hashtag=carshow

@mboveiri

This comment has been minimized.

Copy link

mboveiri commented Jul 17, 2016

Hi.
how to remove "?ig_cache_key=*" from the source pics.?
thanks.

@mboveiri

This comment has been minimized.

Copy link

mboveiri commented Jul 19, 2016

Hi.
how to remove "?ig_cache_key=*" from the source pics.?
thanks.

thanks to blitterobject reddit user for resolve this problem.

@jonathanbell

This comment has been minimized.

Copy link
Owner Author

jonathanbell commented Sep 7, 2016

@mboveiri just curious, why did you want to remove that param?

@hobailey

This comment has been minimized.

Copy link

hobailey commented Sep 9, 2016

@jonathanbell - because it's untidy, and not actually necessary?
@mboveiri - I'm doing it with a simple strstr($i["display_src"], "?ig_cache_key=", true)

@jonathanbell

This comment has been minimized.

Copy link
Owner Author

jonathanbell commented Sep 15, 2016

@hobailey Interesting, when I first wrote the script, I couldn't view/call the images in browser without it. You're right though, it seems to work just fine now without the token.

@pAyDaAr

This comment has been minimized.

Copy link

pAyDaAr commented Nov 25, 2016

@jonathanbell hi there
does it support videos?

@jonathanbell

This comment has been minimized.

Copy link
Owner Author

jonathanbell commented Dec 6, 2016

@paydar currently it will send the thumbnail of the video but not the video itself.

@svenliefting

This comment has been minimized.

Copy link

svenliefting commented Dec 8, 2016

Did Instagram change something? It doesn't work anymore

@mxwright

This comment has been minimized.

Copy link

mxwright commented Dec 16, 2016

I don't have a copy of the previous Instagram JSON, and I'm no JSON expert, but it seems like they've removed a parent element necessary for this script. I get around this now by restricting the array to just the more or less static elements and adding a parent open tag:

$html = strstr($html, '"entry_data');
$html = strstr($html, '</script>', true);

$html = substr($html, 0, -1);
$html = '{' . $html;

@jonathanbell

This comment has been minimized.

Copy link
Owner Author

jonathanbell commented Dec 18, 2016

I'm tired of chasing Instagram. I won't be making changes to this Gist any longer. If your fork of this Gist works with Instagram's updated JSON output, copy/paste a link to your fork here.

@mxwright

This comment has been minimized.

Copy link

mxwright commented Dec 20, 2016

I agree, this a problematic moving target, but I've got a client that requires me to keep it going. Here's a fork that should work for now:
https://gist.github.com/mxwright/54af2703f19ae6f83949969c7b0b752c

I don't use the Gist in the same way as written, but the changes (noted above) should keep it working.

@jonathanbell

This comment has been minimized.

Copy link
Owner Author

jonathanbell commented Dec 21, 2016

@mxwright Thanks! I added your fork as an upstream branch and merged your changes into this Gist.

@mimi89999

This comment has been minimized.

Copy link

mimi89999 commented Feb 7, 2017

@jonathanbell Under what license is that php code? Is it public domain?

@BMRG14

This comment has been minimized.

Copy link

BMRG14 commented Feb 16, 2017

Dude, you are one great person!
I hate how Instagram changes everything and makes them worse day by day!
Thank you very much for this code

@jonathanbell

This comment has been minimized.

Copy link
Owner Author

jonathanbell commented Feb 23, 2017

@mimi89999 Licence = WTFPL (http://www.wtfpl.net/)

@pAyDaAr

This comment has been minimized.

Copy link

pAyDaAr commented Mar 1, 2017

hi @jonathanbell
again it doesnt show image URL.

@jonathanbell

This comment has been minimized.

Copy link
Owner Author

jonathanbell commented Mar 7, 2017

More than likely, Instagram has changed their output again. If you'd like to make edits to a fork, I will pull them into this gist.

@sandeepkgupta

This comment has been minimized.

Copy link

sandeepkgupta commented Mar 7, 2017

Yes, pattern match in line 72 ?ig_cache_key= no longer there in img src. So image path not matched and not picked up.

@mimi89999

This comment has been minimized.

Copy link

mimi89999 commented Mar 10, 2017

@jonathanbell

More than likely, Instagram has changed their output again. If you'd like to make edits to a fork, I will pull them into this gist.

You only need to revert the last commit.

@jonathanbell

This comment has been minimized.

Copy link
Owner Author

jonathanbell commented Apr 10, 2017

@mimi89999 It's been almost 3 years since we started chasing the Instagram output. I appreciate your comment but I think I will stop updating this Gist. Hopefully, people can reason about the code and work it into their own project(s).

@jonathanbell

This comment has been minimized.

Copy link
Owner Author

jonathanbell commented Sep 15, 2017

Lots of interest expressed over email so this gist is working again. See installation instructions if you'd like to install on Heroku.

@mxwright

This comment has been minimized.

Copy link

mxwright commented Mar 14, 2018

oh man they really jacked it up this time

@mxwright

This comment has been minimized.

Copy link

mxwright commented Mar 14, 2018

gotta use something like:
$data->entry_data->ProfilePage[0]->graphql->user->edge_owner_to_timeline_media->edges as $e

@jonathanbell

This comment has been minimized.

Copy link
Owner Author

jonathanbell commented Mar 18, 2018

I'm so tired! 😢

@kissuidotnet

This comment has been minimized.

Copy link

kissuidotnet commented Sep 5, 2019

i was trying to get this to work..
instagram now has instgram.com/{user}/?__a=1
but it looks like you need to send headers and allow to set cookies.. and i dont think you can do this with file_get_contents

@jonathanbell

This comment has been minimized.

Copy link
Owner Author

jonathanbell commented Sep 5, 2019

@kissuidonet If instagram now has ?__a=1 and that serves up json it's trivial to get that and convert it to a PHP array which we can then use to create the XML RSS feed like we were doing before.

@kamaleao

This comment has been minimized.

Copy link

kamaleao commented Dec 3, 2019

Can anyone get this code works with /? __ a =? https://browse-tutorials.com/snippet/php-instagram-rss-feed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.