├── README.md └── api.py /README.md: -------------------------------------------------------------------------------- 1 | ### Python's lib for using Instagram's private API 2 | ================================================== 3 | 4 | #### List of abilities 5 | - Upload photo with captions 6 | - Get info about a user 7 | - Get list of user's medias (with pagination) 8 | - Get list of user's followers 9 | - Get list of user's followings 10 | - Follow/unfollow users 11 | 12 | #### Example 13 | ```python 14 | from api import privateAPI 15 | 16 | api = privateAPI(username = "username", password = "password") 17 | 18 | # Basic info about user 19 | response = api.userInfo(user_id = "427553890") 20 | info = response.json() 21 | 22 | print ("USERNAME: ", info["user"]["username"]) 23 | # USERNAME: leomessi 24 | 25 | # Upload image. !!! Image must be square and have JPG format !!! 26 | api.upload("path_to_image/image.jpg", "Description for image \n #hot #hacker #wow") 27 | 28 | # Follow/unfollow user 29 | api.follow(user_id = "427553890") 30 | api.unfollow(user_id = "427553890") 31 | 32 | # List of followers without max_id parameter (necessary for pagination) 33 | response = api.listFollower(user_id = "427553890") 34 | list_followers = response.json() 35 | 36 | # List of followings with pagination 37 | response = api.listFollowing(user_id = "427553890") # First page 38 | list_followings = response.json() 39 | next_max_id = list_followings["next_max_id"] 40 | 41 | response = api.listFollowing(user_id = "427553890", max_id = next_max_id) # Second page 42 | 43 | # List of user's media with pagination 44 | response = api.userMedia(user_id = "427553890") # First page 45 | next_max_id = response.json()["items"][-1]["next_max_id"] 46 | 47 | response = api.userMedia(user_id = "427553890", max_id = next_max_id) # Second page 48 | media_list = response.json() 49 | ``` 50 | -------------------------------------------------------------------------------- /api.py: -------------------------------------------------------------------------------- 1 | import requests, hmac, uuid, urllib.request, json, hashlib, time 2 | 3 | class privateAPI(): 4 | """List of abilities: auth (in __init__), upload, follow, unfollow, 5 | list of followers, list of followed by, 6 | set description to media 7 | In future: write a comment, set like, direct messages""" 8 | 9 | followURL = "https://i.instagram.com/api/v1/friendships/create/{}/" 10 | unfollowURL = "https://i.instagram.com/api/v1/friendships/destroy/{}/" 11 | loginURL = "https://i.instagram.com/api/v1/accounts/login/" 12 | uploadURL = "https://i.instagram.com/api/v1/media/upload/" 13 | configureURL = "https://i.instagram.com/api/v1/media/configure/" 14 | followerListURL = "https://i.instagram.com/api/v1/friendships/{}/followers/" 15 | followingListURL = "https://i.instagram.com/api/v1/friendships/{}/following/" 16 | userMediaURL = "https://i.instagram.com/api/v1/feed/user/{}/" 17 | userInfoURL = "https://i.instagram.com/api/v1/users/{}/info/" 18 | 19 | def __init__(self, username, password): 20 | self.password = password 21 | self.username = username 22 | 23 | # INITIAL CONFIG 24 | self.user_agent = 'Instagram 4.1.1 Android (11/1.5.0; 285; 800x1280; samsung; GT-N7000; GT-N7000; smdkc210; en_US)' 25 | self.guid = str(uuid.uuid1()) 26 | self.device_id = 'android-{}'.format(self.guid) 27 | self.session = requests.Session() 28 | self.session.headers.update({'User-Agent': self.user_agent}) 29 | 30 | # LOGIN 31 | self.data = json.dumps({ 32 | "device_id": self.device_id, 33 | "guid": self.guid, 34 | "username": self.username, 35 | "password": self.password, 36 | "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8" 37 | }) 38 | 39 | self.sig = hmac.new('b4a23f5e39b5929e0666ac5de94c89d1618a2916'.encode('utf-8'), self.data.encode('utf-8'), hashlib.sha256).hexdigest() 40 | self.payload = 'signed_body={}.{}&ig_sig_key_version=4'.format( 41 | self.sig, 42 | urllib.request.quote(self.data) 43 | ) 44 | 45 | self.loginResponse = self.session.post(self.loginURL, self.payload) 46 | # print "LOGGED IN: ", self.loginResponse.json() 47 | 48 | def upload(self, filename, description): 49 | # UPLOAD MEDIA 50 | self.data = { 51 | "device_timestamp": time.time(), 52 | } 53 | self.files = { 54 | "photo": open(filename, 'rb'), 55 | } 56 | 57 | self.uploadResponse = self.session.post(self.uploadURL, self.data, files = self.files) 58 | # print "UPLOAD RESPONSE: ", self.uploadResponse.json() 59 | 60 | self.media_id = self.uploadResponse.json().get("media_id") 61 | # print "MEDIA ID: ", self.media_id 62 | 63 | # CONFIGURE MEDIA 64 | self.data = json.dumps({ 65 | "device_id": self.device_id, 66 | "guid": self.guid, 67 | "media_id": self.media_id, 68 | "caption": description or "", 69 | "device_timestamp": time.time(), 70 | "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8" 71 | }) 72 | 73 | self.sig = hmac.new('b4a23f5e39b5929e0666ac5de94c89d1618a2916'.encode('utf-8'), self.data.encode('utf-8'), hashlib.sha256).hexdigest() 74 | self.payload = 'signed_body={}.{}&ig_sig_key_version=4'.format( 75 | self.sig, 76 | urllib.request.quote(self.data) 77 | ) 78 | 79 | return self.session.post(self.configureURL, self.payload) 80 | 81 | def follow(self, user_id): 82 | self.data = json.dumps({ 83 | "user_id" : user_id, 84 | "_uid": self.loginResponse.json()["logged_in_user"]["pk"] 85 | }) 86 | 87 | self.sig = hmac.new('b4a23f5e39b5929e0666ac5de94c89d1618a2916'.encode('utf-8'), self.data.encode('utf-8'), hashlib.sha256).hexdigest() 88 | self.payload = 'signed_body={}.{}&ig_sig_key_version=4'.format( 89 | self.sig, 90 | urllib.request.quote(self.data) 91 | ) 92 | 93 | return self.session.post(self.followURL.format(user_id), self.payload) 94 | 95 | def unfollow(self, user_id): 96 | self.data = json.dumps({ 97 | "user_id" : user_id, 98 | "_uid": self.loginResponse.json()["logged_in_user"]["pk"] 99 | }) 100 | 101 | self.sig = hmac.new('b4a23f5e39b5929e0666ac5de94c89d1618a2916'.encode('utf-8'), self.data.encode('utf-8'), hashlib.sha256).hexdigest() 102 | self.payload = 'signed_body={}.{}&ig_sig_key_version=4'.format( 103 | self.sig, 104 | urllib.request.quote(self.data) 105 | ) 106 | 107 | return self.session.post(self.unfollowURL.format(user_id), self.payload) 108 | 109 | def currentUser(self): 110 | return self.loginResponse.json() 111 | 112 | def listFollower(self, user_id, max_id = ""): 113 | if not max_id: 114 | return self.session.get(self.followerListURL.format(user_id)) 115 | else: 116 | return self.session.get(self.followerListURL.format(user_id), params = {"max_id" : max_id}) 117 | 118 | def listFollowing(self, user_id, max_id = ""): 119 | if not max_id: 120 | return self.session.get(self.followingListURL.format(user_id)) 121 | else: 122 | return self.session.get(self.followingListURL.format(user_id), params = {"max_id" : max_id}) 123 | 124 | def userMedia(self, user_id, max_id = ""): 125 | if not max_id: 126 | return self.session.get(self.userMediaURL.format(user_id)) 127 | else: 128 | return self.session.get(self.userMediaURL.format(user_id), params = {"max_id" : max_id}) 129 | 130 | def userInfo(self, user_id): 131 | return self.session.get(self.userInfoURL.format(user_id)) 132 | 133 | --------------------------------------------------------------------------------