130

I am building a php application which needs to post the user uploaded picture directly to Instagram, but after a quick search i found that there is no such function in the API :( and it feels weird... because they should provide one. I am not sure if there is any other way (except the apps for android and iOS) to upload picture using php. Kindly give me any sort of idea if there is any possibility.

I also read this ,

How do I share a link and photo with Instagram using PHP

Braiam
  • 1
  • 11
  • 47
  • 78
Altaf Hussain
  • 5,166
  • 4
  • 30
  • 47
  • 2
    It isn't possible to post pictures to Instagram via the API. – Amal Murali Sep 17 '13 at 08:18
  • 3
    I wonder how they - http://blog.hootsuite.com/schedule-instagram-posts-in-hootsuite/ - do it... (blog announcement was posted 8 hours ago) – Mars Robertson Aug 05 '15 at 21:45
  • 1
    @MichalStefanow I thought it a good question as well. That blog announcement also has a comment from Hootsuite (in the comments section below the article) that there is no actual direct posting to Instagram due to API limits and the final posting does have to be done in Instagram. – thecommonthread Jan 05 '16 at 23:47
  • 1
    What about mid of 2019? Are there any changes? – userlond Jul 08 '19 at 02:19
  • 1
    How about 2021, is this still not possible? – user Apr 18 '21 at 23:34

8 Answers8

108

Update:

Instagram are now banning accounts and removing the images based on this method. Please use with caution.


It seems that everyone who has answered this question with something along the lines of it can't be done is somewhat correct. Officially, you cannot post a photo to Instagram with their API. However, if you reverse engineer the API, you can.

function SendRequest($url, $post, $post_data, $user_agent, $cookies) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, 'https://i.instagram.com/api/v1/'.$url);
    curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);

    if($post) {
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
    }

    if($cookies) {
        curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookies.txt');            
    } else {
        curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookies.txt');
    }

    $response = curl_exec($ch);
    $http = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

   return array($http, $response);
}

function GenerateGuid() {
     return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', 
            mt_rand(0, 65535), 
            mt_rand(0, 65535), 
            mt_rand(0, 65535), 
            mt_rand(16384, 20479), 
            mt_rand(32768, 49151), 
            mt_rand(0, 65535), 
            mt_rand(0, 65535), 
            mt_rand(0, 65535));
}

function GenerateUserAgent() {  
     $resolutions = array('720x1280', '320x480', '480x800', '1024x768', '1280x720', '768x1024', '480x320');
     $versions = array('GT-N7000', 'SM-N9000', 'GT-I9220', 'GT-I9100');
     $dpis = array('120', '160', '320', '240');

     $ver = $versions[array_rand($versions)];
     $dpi = $dpis[array_rand($dpis)];
     $res = $resolutions[array_rand($resolutions)];

     return 'Instagram 4.'.mt_rand(1,2).'.'.mt_rand(0,2).' Android ('.mt_rand(10,11).'/'.mt_rand(1,3).'.'.mt_rand(3,5).'.'.mt_rand(0,5).'; '.$dpi.'; '.$res.'; samsung; '.$ver.'; '.$ver.'; smdkc210; en_US)';
 }

function GenerateSignature($data) {
     return hash_hmac('sha256', $data, 'b4a23f5e39b5929e0666ac5de94c89d1618a2916');
}

function GetPostData($filename) {
    if(!$filename) {
        echo "The image doesn't exist ".$filename;
    } else {
        $post_data = array('device_timestamp' => time(), 
                        'photo' => '@'.$filename);
        return $post_data;
    }
}


// Set the username and password of the account that you wish to post a photo to
$username = 'ig_username';
$password = 'ig_password';

// Set the path to the file that you wish to post.
// This must be jpeg format and it must be a perfect square
$filename = 'pictures/test.jpg';

// Set the caption for the photo
$caption = "Test caption";

// Define the user agent
$agent = GenerateUserAgent();

// Define the GuID
$guid = GenerateGuid();

// Set the devide ID
$device_id = "android-".$guid;

/* LOG IN */
// You must be logged in to the account that you wish to post a photo too
// Set all of the parameters in the string, and then sign it with their API key using SHA-256
$data ='{"device_id":"'.$device_id.'","guid":"'.$guid.'","username":"'.$username.'","password":"'.$password.'","Content-Type":"application/x-www-form-urlencoded; charset=UTF-8"}';
$sig = GenerateSignature($data);
$data = 'signed_body='.$sig.'.'.urlencode($data).'&ig_sig_key_version=4';
$login = SendRequest('accounts/login/', true, $data, $agent, false);

if(strpos($login[1], "Sorry, an error occurred while processing this request.")) {
    echo "Request failed, there's a chance that this proxy/ip is blocked";
} else {            
    if(empty($login[1])) {
        echo "Empty response received from the server while trying to login";
    } else {            
        // Decode the array that is returned
        $obj = @json_decode($login[1], true);

        if(empty($obj)) {
            echo "Could not decode the response: ".$body;
        } else {
            // Post the picture
            $data = GetPostData($filename);
            $post = SendRequest('media/upload/', true, $data, $agent, true);    

            if(empty($post[1])) {
                 echo "Empty response received from the server while trying to post the image";
            } else {
                // Decode the response 
                $obj = @json_decode($post[1], true);

                if(empty($obj)) {
                    echo "Could not decode the response";
                } else {
                    $status = $obj['status'];

                    if($status == 'ok') {
                        // Remove and line breaks from the caption
                        $caption = preg_replace("/\r|\n/", "", $caption);

                        $media_id = $obj['media_id'];
                        $device_id = "android-".$guid;
                        $data = '{"device_id":"'.$device_id.'","guid":"'.$guid.'","media_id":"'.$media_id.'","caption":"'.trim($caption).'","device_timestamp":"'.time().'","source_type":"5","filter_type":"0","extra":"{}","Content-Type":"application/x-www-form-urlencoded; charset=UTF-8"}';   
                        $sig = GenerateSignature($data);
                        $new_data = 'signed_body='.$sig.'.'.urlencode($data).'&ig_sig_key_version=4';

                       // Now, configure the photo
                       $conf = SendRequest('media/configure/', true, $new_data, $agent, true);

                       if(empty($conf[1])) {
                           echo "Empty response received from the server while trying to configure the image";
                       } else {
                           if(strpos($conf[1], "login_required")) {
                                echo "You are not logged in. There's a chance that the account is banned";
                            } else {
                                $obj = @json_decode($conf[1], true);
                                $status = $obj['status'];

                                if($status != 'fail') {
                                    echo "Success";
                                } else {
                                    echo 'Fail';
                                }
                            }
                        }
                    } else {
                        echo "Status isn't okay";
                    }
                }
            }
        }
    }
}

Just copy and paste the code above in your text editor, change the few variables accordingly and VOILA! I wrote an article about this and I've done it many times. See a demo here.

Albzi
  • 15,431
  • 6
  • 46
  • 63
Lance
  • 4,736
  • 16
  • 53
  • 90
  • 1
    Unable to login using above code without using phone. I just used in localhost using PC and I just got Error message as like **** Empty response received from the server while trying to login *** how to solve that error – Rabesh Lal Shrestha Mar 24 '15 at 12:22
  • 1
    Is there already a working .net variant made of this code? I can't work with PHP and a .NET version of this code would be really usefull! – Yosoyke Apr 22 '15 at 19:11
  • No chance! "Status isn't okay" appears every time. I tried all settings and options. Maybe they closed this leak? – Sebastian Jul 27 '15 at 13:39
  • i'm getting this error message "Empty response received from the server while trying to login"! – rakibtg Jul 27 '15 at 18:25
  • 1
    I was able to run the script successfully on a new Instagram account. – loretoparisi Sep 16 '15 at 12:17
  • @sergey.tyan just one type as-it-is. Now it gives back ```array(2) { [0]=> int(400) [1]=> string(174) "{"status":"fail","lock":false,"message":"checkpoint_required","checkpoint_url":"https:\/\/instagram.com\/integrity\/checkpoint\/?next=instagram%3A%2F%2Fcheckpoint%2Fdismiss"}" }``` – loretoparisi Dec 15 '15 at 09:52
  • I've been looking everywhere for something, does this still for work anyone? I'm going to have a go at it regardless, and comment back my result – Hector Jan 08 '16 at 05:13
  • I finally got this script to work but you will need to change out the domain to this `curl_setopt($ch, CURLOPT_URL, 'https://i.instagram.com/api/v1/'.$url);` – Hector Jan 11 '16 at 17:10
  • @Lance there's any chance Instagram to ban me if I use this solution? Did you use for a long time? – – Lucas Brito Mar 15 '16 at 11:35
  • 2
    If you're getting `status isnt okay`, make sure CURL has permissions to make a cookies.txt file. `chmod 777 /directory` will do this (be careful). I am getting a success message from your script, but the post is not showing on instagram. Does this still work? – kmoney12 Apr 09 '16 at 09:27
  • Follow up: If you get a success message, but no photo is posted, you are probably on php 5.6. Try using php 5.5 or lower. – kmoney12 Apr 09 '16 at 09:51
  • 1
    After using it I got "Please update your Instagram app to continue posting photos" in the $obj["status"] . Any help? – Pablo Sep 05 '16 at 11:43
  • 1
    I may be wrong, but...isn't it illegal (against the rules/terms, at least) to make undocumented calls or reverse-engineer the API? – Joe Oct 29 '16 at 20:27
  • Has anyone reverse engineered whatever this new update is? the "API out-of-date" thing? all of the current reverse-engineered clients seem to have this problem. @Joe you are allowed to make HTTP requests using your computer without going to jail (afaik not a lawyer) – quinn Nov 15 '16 at 14:37
  • 1
    for php version 5.6 use this: 'photo'=> new CURLFile($filename) – Ahmad Azizov Nov 20 '16 at 05:20
  • i'm with joe here. it may be cool and may work. but it's sure not the best idea to use this in a public app since it clearly violates the TOS – David Seek Dec 17 '16 at 06:43
  • How to remove the error `Empty response received from the server while trying to login`? Please clarify it. – A J Jan 17 '17 at 04:32
  • 10
    Code works fine but the guid and deviceid changes everytime and instagram BANNED my account after a single successful post. the photo has been removed also. – Alp Altunel Apr 14 '17 at 13:15
  • In order to post anything to Instagram you need an account, which requires you to accept their terms and conditions. This is a legally binding agreement which states clearly: "10. You must not access Instagram's private API by means other than those permitted by Instagram" – etan Oct 25 '17 at 10:06
  • скрипт пишет `Success` ,но не чего не загружает. – newProgrammer Oct 26 '17 at 16:17
  • I was trying to post an image via your demo but it didn't work. It just keeps displaying the posted image. It doesn't seem to work. What should I do? –  Oct 27 '17 at 13:37
  • 1
    This method is banning accounts. I wouldn't use it. – Albzi Dec 08 '17 at 11:45
  • That’s because spammers abuse it – Lance Mar 13 '18 at 01:10
  • Do accounts still banned with this method? – Suncatcher Feb 07 '19 at 21:01
  • Is there still no legitimate way to handle this in 2021? – DaveTheMinion Mar 05 '21 at 05:30
101

If you read the link you shared, the accepted answer is:

You cannot post pictures to Instagram via the API.

Instagram has now said:

Now you can post your content using Instagram's APIs (New) effects from 26th Jan 2021!

https://developers.facebook.com/blog/post/2021/01/26/introducing-instagram-content-publishing-api/

Community
  • 1
  • 1
Albzi
  • 15,431
  • 6
  • 46
  • 63
  • 65
    Well if there is NO way of doing it, then I don't suppose there is 'another' way. – Albzi Sep 17 '13 at 09:08
  • @Ritu Posts.so doesn't do Instagram. – bart Jan 02 '15 at 05:51
  • 1
    @bart at the time of @Ritu posting, it did do instagram and was `posts.so` not `postso.com` – Albzi Jan 05 '15 at 08:34
  • Bluestacks is an emulator which lets you run android apps on your PC/Mac etc. What is this?? – Vishal Patoliya ツ Aug 05 '16 at 10:18
  • Hi does instagram provide this features now...? – Muhammad Usama Mashkoor Jul 02 '17 at 13:15
  • 2
    @usama unfortunately not officially but I've heard rumours that if you go on to their website and scale it down to mobile view you can. Not tried it myself though – Albzi Jul 02 '17 at 13:16
  • Thanks @Albzi for quick response :) – Muhammad Usama Mashkoor Jul 02 '17 at 17:48
  • 2
    @Albzi If you use Google Chrome; got to the Instagram website and right click and use the "Inspect" it will resize and change the header to a mobile browser signature allowing. You may have to refresh the Instagram page once in "Inspect" but it will allow you to use the website as a mobile and can post photos and what not. However; this doesn't help with the API question. I'd love to be able to post a photo from PHP to Instagram showing our teams final score. – Dawson Irvine Jan 20 '19 at 03:35
  • I've seen this, it's probably the best bet for now as still no official API support that won't get you banned! @DawsonIrvine – Albzi Jan 21 '19 at 11:00
  • Actually, there always can be "other way". We are developers guys... come one... One of the possible ways is: In the backend, open a browser with puppeteer, open instagram in the browser, resize the page, click on upload always using puppeteer), chose the image and upload it. Hard to implement, but possible. Don't forget that instagram.com allows to upload photos from the browser. So, you just need a dedicated server, or puppeteer and simulate to be an user. It's ilegal, and hard to implement, but there always be "another way" – Broda Noel Feb 25 '19 at 18:51
  • 1
    Fair point. @BrodaNoel, maybe I should change that to no 'official' way. – Albzi Feb 27 '19 at 05:43
14

Instagram now allows businesses to schedule their posts, using the new Content Publishing Beta endpoints.

https://developers.facebook.com/blog/post/2018/01/30/instagram-graph-api-updates/

However, this blog post - https://business.instagram.com/blog/instagram-api-features-updates - makes it clear that they are only opening that API to their Facebook Marketing Partners or Instagram Partners.

To get started with scheduling posts, please work with one of our Facebook Marketing Partners or Instagram Partners.

This link from Facebook - https://developers.facebook.com/docs/instagram-api/content-publishing - lists it as a closed beta.

The Content Publishing API is in closed beta with Facebook Marketing Partners and Instagram Partners only. We are not accepting new applicants at this time.

But this is how you would do it:

You have a photo at...

https://www.example.com/images/bronz-fonz.jpg

You want to publish it with the hashtag "#BronzFonz".

You could use the /user/media edge to create the container like this:

POST graph.facebook.com 
  /17841400008460056/media?
    image_url=https%3A%2F%2Fwww.example.com%2Fimages%2Fbronz-fonz.jpg&
    caption=%23BronzFonz

This would return a container ID (let's say 17889455560051444), which you would then publish using the /user/media_publish edge, like this:

POST graph.facebook.com
  /17841405822304914/media_publish
    ?creation_id=17889455560051444

This example from the docs.

Joshua Dance
  • 8,847
  • 4
  • 67
  • 72
  • Thanks but where i can create the app for this like we can create app for facebook in facebook developer area. – Muhammad Usama Mashkoor Nov 13 '18 at 19:22
  • This code gives an error - "Application does not have the capability to make this API call."? This is utter non-sense from these tech companies. How can they ask use to come via some preferred partners and not make our own App. – Amit Khare Mar 23 '20 at 16:59
11

I tried using IFTTT and many other services but all were doing things or post from Instagram to another platform not to Instagram. I read more to found Instagram does not provide any such API as of now.

Using blue stack is again involving heavy installation and doing things manually only.

However, you can use your Google Chrome on the desktop version to make a post on Instagram. It needs a bit tweak.

  1. Open your chrome and browse Instagram.com
  2. Go to inspect element by right clicking on chrome.
  3. From top right corener menu drop down on developer tools, select more tool.
  4. Further select network conditions.
  5. In the network selection section, see the second section there named user agent.
  6. Uncheck select automatically, and select chrome for Android from the list of given user agent.
  7. Refresh your Instagram.com page.

You will notice a change in UI and the option to make a post on Instagram. Your life is now easy. Let me know an easier way if you can find any.

enter image description here

I wrote on https://www.inteligentcomp.com/2018/11/how-to-upload-to-instagram-from-pc-mac.html about it.

Working Screenshot

enter image description here

Dheeraj Thedijje
  • 1,053
  • 12
  • 19
6

For anyone who is searching for a solution about posting to Instagram using AWS lambda and puppeteer (chrome-aws-lambda). Noted that this solution allow you to post 1 photo for each post only. If you are not using lambda, just replace chrome-aws-lambda with puppeteer.

For the first launch of lambda, it is normal that will not work because instagram detects “Suspicious login attempt”. Just goto instagram page using your PC and approve it, everything should be fine.

Here's my code, feel free to optimize it:

// instagram.js
const chromium = require('chrome-aws-lambda');

const username = process.env.IG_USERNAME;
const password = process.env.IG_PASSWORD;

module.exports.post = async function(fileToUpload, caption){
    const browser = await chromium.puppeteer.launch({
        args: [...chromium.args, '--window-size=520,700'],
        defaultViewport: chromium.defaultViewport,
        executablePath: await chromium.executablePath,
        headless: false,
        ignoreHTTPSErrors: true,
    });
    const page = await browser.newPage();
    await page.setUserAgent('Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_2 like Mac OS X) AppleWebKit/603.2.4 (KHTML, like Gecko) FxiOS/7.5b3349 Mobile/14F89 Safari/603.2.4');
    await page.goto('https://www.instagram.com/', {waitUntil: 'networkidle2'});
    
    const [buttonLogIn] = await page.$x("//button[contains(., 'Log In')]");
    if (buttonLogIn) {
        await buttonLogIn.click();
    }

    await page.waitFor('input[name="username"]');
    await page.type('input[name="username"]', username)
    await page.type('input[name="password"]', password)
    await page.click('form button[type="submit"]');

    await page.waitFor(3000);
    const [buttonSaveInfo] = await page.$x("//button[contains(., 'Not Now')]");
    if (buttonSaveInfo) {
        await buttonSaveInfo.click();
    }

    await page.waitFor(3000);
    const [buttonNotificationNotNow] = await page.$x("//button[contains(., 'Not Now')]");
    const [buttonNotificationCancel] = await page.$x("//button[contains(., 'Cancel')]");
    if (buttonNotificationNotNow) {
        await buttonNotificationNotNow.click();
    } else if (buttonNotificationCancel) {
        await buttonNotificationCancel.click(); 
    }

    await page.waitFor('form[enctype="multipart/form-data"]');
    const inputUploadHandle = await page.$('form[enctype="multipart/form-data"] input[type=file]');

    await page.waitFor(5000);
    const [buttonPopUpNotNow] = await page.$x("//button[contains(., 'Not Now')]");
    const [buttonPopUpCancel] = await page.$x("//button[contains(., 'Cancel')]");
    if (buttonPopUpNotNow) {
        await buttonPopUpNotNow.click();
    } else if (buttonPopUpCancel) {
        await buttonPopUpCancel.click(); 
    }

    await page.click('[data-testid="new-post-button"]')
    await inputUploadHandle.uploadFile(fileToUpload);

    await page.waitFor(3000);
    const [buttonNext] = await page.$x("//button[contains(., 'Next')]");
    await buttonNext.click();

    await page.waitFor(3000);
    await page.type('textarea', caption);

    const [buttonShare] = await page.$x("//button[contains(., 'Share')]");
    await buttonShare.click();
    await page.waitFor(3000);

    return true;
};
// handler.js

await instagram.post('/tmp/image.png', '#text');

it must be local file path, if it is url, download it to /tmp folder first.

Updated:

Instagram is blocking all suspicious login attempt now unless you approve it manually every time it executed. To solve that, better to save your cookies as json and import it to puppeteer.

Allen Wong
  • 1,162
  • 1
  • 10
  • 15
5

For users who find this question, you can pass photos to the instagram sharing flow (from your app to the filters screen) on iPhone using iPhone hooks: http://help.instagram.com/355896521173347 Other than that, there is currently no way in version 1 of the api.

Amru E.
  • 2,008
  • 3
  • 17
  • 23
  • 1
    @Ritu interesting. It must be possible then, but it doesn't seem like the API allows it. Thanks for sharing, I want to look into it. – Amru E. Dec 11 '13 at 17:44
  • 1
    i was also wondering how they are doing it , please share if you'll get something relevant. – Ritu Dec 12 '13 at 05:39
  • 2
    It seems that most unauthorized clients are reverse engineering the API by decrypting and monitoring SSL traffic from the app to the server. This is the case for Snapchat, at least. Could be the same here. – Amru E. Nov 25 '14 at 09:28
  • Flume App for Mac also posts to your feed – Joshua - Pendo Jan 04 '17 at 14:06
1

If it has a UI, it has an "API". Let's use the following example: I want to publish the pic I use in any new blog post I create. Let's assume is Wordpress.

  1. Create a service that is constantly monitoring your blog via RSS.
  2. When a new blog post is posted, download the picture.
  3. (Optional) Use a third party API to apply some overlays and whatnot to your pic.
  4. Place the photo in a well-known location on your PC or server.
  5. Configure Chrome (read above) so that you can use the browser as a mobile.
  6. Using Selenium (or any other of those libraries), simulate the entire process of posting on Instagram.
  7. Done. You should have it.
Pepito Fernandez
  • 2,352
  • 6
  • 32
  • 47
-1

There is no API to post photo to instagram using API , But there is a simple way is that install google extension " User Agent " it will covert your browser to android mobile chrome version . Here is the extension link https://chrome.google.com/webstore/detail/user-agent-switcher/clddifkhlkcojbojppdojfeeikdkgiae?utm_source=chrome-ntp-icon

just click on extension icon and choose chrome for android and open Instagram.com

Waheed Sabir
  • 159
  • 2
  • 4