Skip to content

Instantly share code, notes, and snippets.

@afilhodaniel
Last active November 12, 2020 10:20
Show Gist options
  • Save afilhodaniel/09a1df8eafeabe1584c6 to your computer and use it in GitHub Desktop.
Save afilhodaniel/09a1df8eafeabe1584c6 to your computer and use it in GitHub Desktop.
Upload photos to Instagram via private API with Ruby
class InstagramPrivateController < ApplicationController
def initialize(username, password, photo, caption)
@username = username
@password = password
@photo = photo
@caption = caption
@cookiepath = Tempfile.new('cookies').path
@user_agent = generate_user_agent()
@guid = generate_guid()
@device_id = generate_device_id(@guid)
end
def send
login = login()
if login['status'] == 'ok'
media = upload()
if media['status'] == 'ok'
configure = configure(media['media_id'])
return configure
end
return media
end
return login
end
def generate_user_agent
resolution = ['720x1280', '320x480', '480x800', '1024x768', '1280x720', '768x1024', '480x320'].sample
version = ['GT-N7000', 'SM-N9000', 'GT-I9220', 'GT-I9100'].sample
dpi = ['120', '160', '320', '240'].sample
return 'Instagram 4.' + rand(1..2).to_s + '.' + rand(0..2).to_s + ' Android (' + rand(10..11).to_s + '/' + rand(1..3).to_s + '.' + rand(3..5).to_s + '.' + rand(0..5).to_s + '; #{dpi}; #{resolution}; samsung; #{version }; #{version}; smdkc210; en_US)'
end
def generate_guid
guid = sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
rand(0..65535),
rand(0..65535),
rand(0..65535),
rand(16384..20479),
rand(32768..49151),
rand(0..65535),
rand(0..65535),
rand(0..65535))
return guid
end
def generate_device_id(guid)
return 'android-#{guid}'
end
def generate_signature(data)
return OpenSSL::HMAC.hexdigest('sha256', 'b4a23f5e39b5929e0666ac5de94c89d1618a2916', data)
end
def request(url, data, upload, cookies)
http = Curl::Easy.new(url)
http.headers["User-Agent"] = @user_agent
http.multipart_form_post = upload
http.verbose = true
http.follow_location = true
http.enable_cookies = true
if cookies
http.cookiefile = @cookiepath
else
http.cookiejar = @cookiepath
end
if data.kind_of?(Array)
http.send('post', *data)
else
http.send('post', data)
end
response = JSON.parse(http.body)
http.close
return response
end
def login
url = 'https://instagram.com/api/v1/accounts/login/'
data = "{'username':'#{@username}','password':'#{@password}','guid':'#{@guid}','device_id':'#{@device_id}','Content-Type':'application/x-www-form-urlencoded; charset=UTF-8'}".gsub("'", '"')
signature = generate_signature(data)
body = 'ig_sig_key_version=4&signed_body=' + signature + '.' + URI::encode(data, /\W/)
response = request(url, body, false, false)
return response
end
def upload
url = 'https://instagram.com/api/v1/media/upload/'
device_timestamp = Time.now.to_i.to_s
data = [
Curl::PostField.file('photo', @photo),
Curl::PostField.content('device_timestamp', device_timestamp)
]
response = request(url, data, true, true)
return response
end
def configure(media_id)
url = 'https://instagram.com/api/v1/media/configure/'
device_timestamp = Time.now.to_i.to_s
data = "{'guid':'#{@guid}','device_id':'#{@device_id}','device_timestamp':'#{device_timestamp}','media_id':'#{media_id}','caption':'#{@caption}','source_type':'5','filter_type':'0','extra':'{}','Content-Type':'application/x-www-form-urlencoded; charset=UTF-8'}".gsub("'", '"')
signature = generate_signature(data)
body = 'ig_sig_key_version=4&signed_body=' + signature + '.' + URI::encode(data, /\W/)
response = request(url, body, false, true)
return response
end
end
Fonts:
http://lancenewman.me/posting-a-photo-to-instagram-without-a-phone/
http://mokhdzanifaeq.github.io/reverse-engineering-instagram-private-api/
@newstler
Copy link

Your version of Instagram is out of date. Please upgrade your app to log in to Instagram.

@rdetert
Copy link

rdetert commented Apr 2, 2015

This should be a model, not a controller

@lastbench
Copy link

@aclemmensen have you migrated the ruby code to c# or did you use a different algorithm?can you share it if you don't mind?

@aclemmensen
Copy link

@lastbench I made my C# implementation based on the original PHP implementation by Lance Newman. I was suspecting that this was a flaw in my implementation, but I just tested the original code and it shows the same behavior. I've been spending quite a few hours in Fiddler trying to figure out why my phone can post images just fine and my application can't.

I haven't tested this particular Ruby implementation. I was just wondering if the author had experienced the same issue.

@aclemmensen
Copy link

And if you ask me this shouldn't be a model or a controller. Instead it should be a separate service that you can inject into your controller.

@dene-
Copy link

dene- commented Apr 5, 2015

@aclemmensen I would like to see your C# version. I wonder how you worked with the http requests.

@bin-aa
Copy link

bin-aa commented Apr 30, 2015

// Your version of Instagram is out of date. Please upgrade your app to log in to Instagram.
@newstler How do you fix this?

@QNester
Copy link

QNester commented Jan 24, 2016

Hi. Nice code! Thanks! But i have one problem with uploading video to instagram. Tell me pls, how i can fix this error:

configure response: {"status"=>"ok", "media"=>{"upload_id"=>"1453635345"}, "message"=>"media_needs_reupload", "error_title"=>"staged_position_not_found"}

@sezgin-zz
Copy link

success but SUCCESS: {
"error_title" = "staged_position_not_found";
media = {
"upload_id" = 1453825279;
};
message = "media_needs_reupload";
status = ok;
}

@oratiostuff
Copy link

I want the script to video, can anyone?

@EXECUTOR-brandon
Copy link

mgp25 has a similar script that I use yet I also encounter the same media_needs_reupload / staged_position_not_found when I upload videos. I been posting on mgp25's GitHub trying to find a solution yet to find a solution. Some people suggest downgrade to 5.5.3 but that did not fix fyi.
mgp25/Instagram-API#191
mgp25/Instagram-API#185

@ThallesLazaro
Copy link

Nada ainda né? :( 12/12/2018 e ainda nenhuma resolução do problema.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment