How to auto publish post on Instagram Page with PHP/cURL and without using Instagram API (1)

Instagram is one of the most difficult apps for developers to schedule auto posting without using API. Instagram is specifically designed to support uploads from mobile phones only. Instagram team only gives whitelist access to limited  third-party apps for automatic posting on a case by case basis. Another reason is Instagram team want to fight spam and low quality photos.

I was looking for a way to auto posting from website to Instagram page using PHP/cURL without using API since last two years. Lately I found two websites that are discussing about this topic.

Posting a Photo to Instagram Without a Phone

instagram-photo-upload-batuhanorg.php

Initially I was not able to make the coding working immediately after download the source files due to several issues such as PHP 5.5 vs 5.6 issue as well as new signature key from instagram app. In this tutorial, I will show you a working draft to auto post single photo to Instagram page using PHP/cURL. I am take no responsibility if your account banned by Instagram. :)

Note: Check out the code sample at bottom of this article.

There are three files in this tutorial.

1. simpleimage.class.php

This is the image library discussed at Download and Save Images with PHP/cURL Web Scraper Script.

I use the image class to resize photo to meet the specification required by Instagram. You can use your own preferred image library if you wish. 

2. instagram.class.php

This is the draft instagram class to login and post photo and caption. You need to improve error handling, rewrite class method and customize the code for your own use. 

Class Instagram
{
private $username;
private $password;
private $guid;
private $userAgent = 'Instagram 6.21.2 Android (19/4.4.2; 480dpi; 1152x1920; Meizu; MX4; mx4; mt6595; en_US)';
private $instaSignature ='25eace5393646842f0d0c3fb2ac7d3cfa15c052436ee86b5406a8433f54d24a5';
private $instagramUrl = 'https://i.instagram.com/api/v1/';

 

First, we set private variables of Class Instagram. I use a fix $userAgent as I intend to auto post one single photo every 4 hours on a single account.

We need to have Instagram signature key to sign requests to their private API. This key is currently working well for me. You can refer to on how to extract new sginature key in future. 

EXTRACTING INSTAGRAM SIGNATURE KEY

EXTRACTING INSTAGRAM SIGNATURE KEY II

We also define Instagram URLs for API. 

private function Request($url, $post, $post_data, $cookies) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $this->instagramUrl . $url);
    curl_setopt($ch, CURLOPT_USERAGENT, $this->userAgent);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);

    if($post) {
        curl_setopt($ch, CURLOPT_POST, 1);
		if ((version_compare(PHP_VERSION, '5.5') >= 0)) {
			curl_setopt($ch, CURLOPT_SAFE_UPLOAD, 1);
		} 		
        curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
    }
	
    if($cookies) {
        curl_setopt($ch, CURLOPT_COOKIEFILE,   dirname(__FILE__). '/cookies.txt');            
    } else {
        curl_setopt($ch, CURLOPT_COOKIEJAR,  dirname(__FILE__). '/cookies.txt');
    }
    $response = curl_exec($ch);
    $http = curl_getinfo($ch, CURLINFO_HTTP_CODE);    
    curl_close($ch);    
    return array($http, $response);
}

This is the cURL function for sending request to Instagram. Note that $this->instagramUrl . $url is the final url.
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $this->instagramUrl . $url);
    curl_setopt($ch, CURLOPT_USERAGENT, $this->userAgent);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);

The PHP version for XMAPP and live server are different. So this will take care of the CURLOPT_SAFE_UPLOAD setup issue for both.
	    if($post) {
        curl_setopt($ch, CURLOPT_POST, 1);
		if ((version_compare(PHP_VERSION, '5.5') >= 0)) {
			curl_setopt($ch, CURLOPT_SAFE_UPLOAD, 1);
		} 		
        curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
    }

The method will return $http code status and $response from Instagram.

    return array($http, $response);

 

This method return randomly generated globally unique identifier (GUID). 

private 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));
}

 

Instagram requires signature described in hex representation of a RFC 2104-compliant HMAC with the SHA256 hash algorithm. $data is request data that will be sent to Instagram. $this->instaSignature is the signature key.

private function GenerateSignature($data) {
    return hash_hmac('sha256', $data, $this->instaSignature); 
}

 

This is used to setup time stamp and photo (with complete directory path). For PHP 5.5 and above, use CURLFile, else "@".

 

private function GetPostData($path)  {

	$post_data = array('device_timestamp' => time());

		if ((version_compare(PHP_VERSION, '5.5') >= 0)) {

				$post_data['photo'] = new CURLFile(realpath($path));

		} else {

                $post_data['photo'] = "@".realpath($path);

        }

    return $post_data;

}

This method login to Instagram before posting photo. It returns http code status and response from Instagram.

public function Login($username, $password) {
    $this->username = $username;
    $this->password = $password;	
	$this->guid = $this->GenerateGuid();
	$device_id = "android-" . $this->guid;	
	$data = '{"device_id":"'.$device_id.'","guid":"'.$this->guid.'","username":"'. $this->username.'","password":"'.$this->password.'","Content-Type":"application/x-www-form-urlencoded; charset=UTF-8"}';
	$sig = $this->GenerateSignature($data);
	$data = 'signed_body='.$sig.'.'.urlencode($data).'&ig_sig_key_version=6';	
	return $this->Request('accounts/login/', true, $data, false);	
}

 

This method send request to post photo and return http code status and response from Instagram.

private function PostImage($photo) {
    $data = $this->GetPostData($photo);
    return $this->Request('media/upload/', true, $data, true); 	
}

This method send request to post caption of the photo and return http code status and response from Instagram.

private function PostCaption($caption, $media_id) {
    $caption = preg_replace("/\r|\n/", "", $caption);
    $device_id = "android-".$this->guid;
    $data = '{"device_id":"'.$device_id.'","guid":"'. $this->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 = $this->GenerateSignature($data);
    $new_data = 'signed_body='.$sig.'.'.urlencode($data).'&ig_sig_key_version=6';
	return $this->Request('media/configure/', true, $new_data, true);		
}

This method calls PostImage and PostCaption method.

public function Post($photo, $caption){
	$response = $this->PostImage($photo);
	if(empty($response[1])) {
		echo "Empty response received from the server while trying to post the image";
		exit();	
	}

	$obj = @json_decode($response[1], true);
	$status = $obj['status'];
	if($status == 'ok') {
		$media_id = $obj['media_id'];		
		$response = $this->PostCaption($caption, $media_id);	
	}		
}

 

Let's look at our main file instagram_autopost.php

<?php

include 'simpleimage.class.php';
include 'instagram.class.php';

$username = 'xxxx';   // your username
$password = 'yyyy';   // your password
$filename = 'zzzz.jpg';   // your sample photo
$caption = " #tag1 #tag2 # tag3 .....";   // your caption

$product_image= getcwd() .'\\uploads\\' . $filename;     // path to your original photo file
$square = getcwd().'\\square\\' . $filename;             // path to your resized photo file
$image = new SimpleImage(); 
$image->load($product_image); 
$image->resize(480,600); 						
$image->save($square, IMAGETYPE_JPEG);  
unset($image);

$insta = new instagram();
$response = $insta->Login($username, $password);

if(strpos($response[1], "Sorry")) {
    echo "Request failed, there's a chance that this proxy/ip is blocked";
	print_r($response);
	exit();
}         
if(empty($response[1])) {
    echo "Empty response received from the server while trying to login";
	print_r($response);	
	exit();	
}

$insta->Post($square, $caption);
?>

First, include image and instagram class file.

 

include 'simpleimage.class.php';
include 'instagram.class.php';

Your username, password, image fila name and caption

$username = 'xxxx';   // your username
$password = 'yyyy';   // your password
$filename = 'zzzz.jpg';   // your sample photo
$caption = " #tag1 #tag2 # tag3 .....";   // your caption

At present, Instagram accepts photo sizes below

Square : 1080x1080px, 600x600px

Landscape (horizontal) : 600x450px, 1350x1080px

Portrait (vertical) : 480×600px, 920×1200px for retina display, 1080×1350px.

Resize the original image to fit Instagram requirements. 

$product_image= getcwd() .'\\uploads\\' . $filename;     // path to your original photo file
$square = getcwd().'\\square\\' . $filename;             // path to your resized photo file
$image = new SimpleImage(); 
$image->load($product_image); 
$image->resize(600,600); 						
$image->save($square, IMAGETYPE_JPEG);  
unset($image);

If no problem on login, then proceed to post photo and caption.

$insta = new instagram();
$response = $insta->Login($username, $password);

if(strpos($response[1], "Sorry")) {
    echo "Request failed, there's a chance that this proxy/ip is blocked";
	print_r($response);
	exit();
}         
if(empty($response[1])) {
    echo "Empty response received from the server while trying to login";
	print_r($response);	
	exit();	
}

$insta->Post($square, $caption);

This is the sample auto post: 

 

 

 Code: 

1. simpleimage.class.php

<?php

class SimpleImage {   
	var $image; 
	var $image_type;   

function load($filename) {   
	$image_info = getimagesize($filename); 
	$this->image_type = $image_info[2]; 
	if( $this->image_type == IMAGETYPE_JPEG ) {   
		$this->image = imagecreatefromjpeg($filename); 
	} elseif( $this->image_type == IMAGETYPE_GIF ) {  
		$this->image = imagecreatefromgif($filename); 
	} elseif( $this->image_type == IMAGETYPE_PNG ) {  
		$this->image = imagecreatefrompng($filename); 
	} 
	unset($image_info);	
} 

function save($filename, $image_type=IMAGETYPE_JPEG, $compression=75, $permissions=null) {   
	if( $image_type == IMAGETYPE_JPEG ) { 
		imagejpeg($this->image,$filename,$compression); 
	} elseif ( $image_type == IMAGETYPE_GIF ) {   
		imagegif($this->image,$filename); 
	} elseif ( $image_type == IMAGETYPE_PNG ) {   
		imagepng($this->image,$filename); 
	} 
	if( $permissions != null) {   
		chmod($filename,$permissions); } 
	} 
	
function output($image_type=IMAGETYPE_JPEG) {   
	if( $image_type == IMAGETYPE_JPEG ) { 
		imagejpeg($this->image); 
	} elseif ( $image_type == IMAGETYPE_GIF ) {   
		imagegif($this->image); 
	} elseif ( $image_type == IMAGETYPE_PNG ) {   
		imagepng($this->image); 
	} 
} 

function getWidth() {   
	return imagesx($this->image); 
} 

function getHeight() {   
	return imagesy($this->image); 
} 

function resizeToHeight($height) {   
	$ratio = $height / $this->getHeight(); 
	$width = $this->getWidth() * $ratio; 
	$this->resize($width,$height); 
}   

function resizeToWidth($width) { 
	$ratio = $width / $this->getWidth(); 
	$height = $this->getheight() * $ratio; $this->resize($width,$height); 
}   

function scale($scale) { 
	$width = $this->getWidth() * $scale/100; 
	$height = $this->getheight() * $scale/100; 
	$this->resize($width,$height); 
}   

function resize($width,$height) { 
	$new_image = imagecreatetruecolor($width, $height); 
	imagecopyresampled($new_image, $this->image, 0, 0, 0, 0, $width, $height, $this->getWidth(), $this->getHeight()); $this->image = $new_image; 
}   

}
?>

 

2. instagram.class.php

<?php

Class Instagram
{
public $username;
public $password;
private $guid;
private $userAgent = 'Instagram 6.21.2 Android (19/4.4.2; 480dpi; 1152x1920; Meizu; MX4; mx4; mt6595; en_US)';
private $instaSignature ='25eace5393646842f0d0c3fb2ac7d3cfa15c052436ee86b5406a8433f54d24a5';
private $instagramUrl = 'https://i.instagram.com/api/v1/';

function __construct()	{	
    if (!extension_loaded('curl')) trigger_error('php_curl extension is not loaded', E_USER_ERROR);	
}

function __destruct()	{

}	
	
private function Request($url, $post, $post_data, $cookies) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $this->instagramUrl . $url);
    curl_setopt($ch, CURLOPT_USERAGENT, $this->userAgent);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);

    if($post) {
        curl_setopt($ch, CURLOPT_POST, 1);
		if ((version_compare(PHP_VERSION, '5.5') >= 0)) {
			curl_setopt($ch, CURLOPT_SAFE_UPLOAD, 1);
		} 		
        curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
    }
	
    if($cookies) {
        curl_setopt($ch, CURLOPT_COOKIEFILE,   dirname(__FILE__). '/cookies.txt');            
    } else {
        curl_setopt($ch, CURLOPT_COOKIEJAR,  dirname(__FILE__). '/cookies.txt');
    }
    $response = curl_exec($ch);
    $http = curl_getinfo($ch, CURLINFO_HTTP_CODE);    
    curl_close($ch);    
    return array($http, $response);
}

private 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));
}

private function GenerateSignature($data) {
    return hash_hmac('sha256', $data, $this->instaSignature); 
}


private function GetPostData($path)  {
	$post_data = array('device_timestamp' => time());
		if ((version_compare(PHP_VERSION, '5.5') >= 0)) {
				$post_data['photo'] = new CURLFile(realpath($path));
		} else {
                $post_data['photo'] = "@".realpath($path);
        }
    return $post_data;
}

public function Login($username, $password) {
    $this->username = $username;
    $this->password = $password;	
	$this->guid = $this->GenerateGuid();
	$device_id = "android-" . $this->guid;	
	$data = '{"device_id":"'.$device_id.'","guid":"'.$this->guid.'","username":"'. $this->username.'","password":"'.$this->password.'","Content-Type":"application/x-www-form-urlencoded; charset=UTF-8"}';
	$sig = $this->GenerateSignature($data);
	$data = 'signed_body='.$sig.'.'.urlencode($data).'&ig_sig_key_version=6';	
	return $this->Request('accounts/login/', true, $data, false);	
}

private function PostImage($photo) {
    $data = $this->GetPostData($photo);
    return $this->Request('media/upload/', true, $data, true); 	
}

private function PostCaption($caption, $media_id) {
    $caption = preg_replace("/\r|\n/", "", $caption);
    $device_id = "android-".$this->guid;
    $data = '{"device_id":"'.$device_id.'","guid":"'. $this->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 = $this->GenerateSignature($data);
    $new_data = 'signed_body='.$sig.'.'.urlencode($data).'&ig_sig_key_version=6';
	return $this->Request('media/configure/', true, $new_data, true);		
}



public function Post($photo, $caption){
	$response = $this->PostImage($photo);
	if(empty($response[1])) {
		echo "Empty response received from the server while trying to post the image";
		exit();	
	}

	$obj = @json_decode($response[1], true);
	$status = $obj['status'];
	if($status == 'ok') {
        // Remove and line breaks from the caption
		$media_id = $obj['media_id'];		
		$response = $this->PostCaption($caption, $media_id);	
	}		
}
}
?>

 

3. instagram_autopost.php

<?php

include 'simpleimage.class.php';
include 'instagram.class.php';

$username = 'xxxx';   // your username
$password = 'yyyy';   // your password
$filename = 'zzzz.jpg';   // your sample photo
$caption = " #tag1 #tag2 # tag3 .....";   // your caption

$product_image= getcwd() .'/original/' . $filename;
$square = getcwd().'/resize/' . $filename;
$image = new SimpleImage(); 
$image->load($product_image); 
$image->resize(480,600); 						
$image->save($square, IMAGETYPE_JPEG);  
unset($image);

$insta = new instagram();
$response = $insta->Login($username, $password);

if(strpos($response[1], "Sorry")) {
    echo "Request failed, there's a chance that this proxy/ip is blocked";
	print_r($response);
	exit();
}         
if(empty($response[1])) {
    echo "Empty response received from the server while trying to login";
	print_r($response);	
	exit();	
}

$insta->Post($square, $caption);
?>

 

 

 

 

 

 

Last modified on Tuesday, 29 December 2020 06:49
Rate this item
(2 votes)
back to top