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/
@aclemmensen
Copy link

I've implemented a C# version of what you have here, and while all the bits work (login, upload, configure) I'm seeing some issues with hashtags. The photos are tagged alright, but I can only see the photo when I'm logged in as myself and browsing the tag. If I'm logged in as somebody else the photo doesn't show up. The photos are visible on the 1st user's profile, though. Have you experienced anything similar?

@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