Skip to content

Latest commit

 

History

History
2991 lines (2262 loc) · 133 KB

DOCUMENTATION.md

File metadata and controls

2991 lines (2262 loc) · 133 KB

Documentation

InstaPy is being sponsored by the following partner. Please help to support us by taking a look and signing up to a free trial 😊 GitAds

Table of Contents










Settings

Liking

This method is only needed for the interact_by_... actions.
Posts will be liked by default when using like_by_... actions.

# ~70% of the by InstaPy viewed posts will be liked

session.set_do_like(enabled=True, percentage=70)

Commenting

# enable comments (by default enabled=False) and set commenting probability to 25% so ~ every 4th image will be commented on

session.set_do_comment(enabled=True, percentage=25)
# Configure a simple list of optional comments, one will be selected at random when commenting:
session.set_comments(['Awesome', 'Really Cool', 'I like your stuff'])

Or configure conditional comments to provide a more contextual commenting based on the caption of the image: Conditional comments are created as a list of dictionaries, each one contains a definition of mandatory words and a list of comments. The list of conditional comments is scanned until the first item that satisfies the mandatory words condition is found and then one of the comments associated with that item is selected at random to be used.
This can best be understood with an example:

comments=[
    # either "icecave" OR "ice_cave" will satisfy this:
    {'mandatory_words': ["icecave", "ice_cave"], 'comments': ["Nice shot. Ice caves are amazing", "Cool. Aren't ice caves just amazing?"]},
    
    # either "high_mountain" OR ("high" AND "mountain") will satisfy this:
    {'mandatory_words': ["high_mountain", ["high", "mountain"]], 'comments': ["I just love high mountains"]},

    # Only ("high" AND "tide" together) will satisfy this:
    {'mandatory_words': [["high", "tide"]], 'comments': ["High tides are better than low"]}

    # Only "summer" AND ("lake" OR "occean") will satisfy this:
    {'mandatory_words': [["summer", ["lake", "occean"]], 'comments': ["Summer fun"]}

]
session.set_comments(comments)

You can also set comments for specific media types (Photo / Video)

session.set_comments(['Nice shot!'], media='Photo')
session.set_comments(['Great Video!'], media='Video')

# and you can add the username of the poster to the comment by using

session.set_comments(['Nice shot! @{}'], media='Photo')

Emoji Support

To use an emoji just add an u in front of the opening apostrophe:

session.set_comments([u'This post is 🔥',u'More emojis are always better 💯',u'I love your posts 😍😍😍']);
# or
session.set_comments([u'Emoji text codes are also supported :100: :thumbsup: :thumbs_up: \u2764 💯💯']);

Emoji text codes are implemented using 2 different naming codes. A complete list of emojis codes can be found on the Python Emoji Github, but you can use the alternate shorted naming scheme found for Emoji text codes here. Note: Every Emoji has not been tested. Please report any inconsistencies.

Following

# default enabled=False, follows ~ 10% of the users from the images, times=1
# (only follows a user once (if unfollowed again))

session.set_do_follow(enabled=True, percentage=10, times=2)

Smart Hashtags

# Generate smart hashtags based on https://displaypurposes.com ranking,
# banned and spammy tags are filtered out.
# (limit) defines amount limit of generated hashtags by hashtag
# (sort) sort generated hashtag list 'top' and 'random' are available
# (log_tags) shows generated hashtags before use it
# (use_smart_hashtags) activates like_by_tag to use smart hashtags

session.set_smart_hashtags(['cycling', 'roadbike'], limit=3, sort='top', log_tags=True)
session.like_by_tags(amount=10, use_smart_hashtags=True)

Smart Location Hashtags

Generate smart hashtags based on https://displaypurposes.com/map ranking. Banned and spammy tags are filtered out.

Use_smart_location_hashtags activates like_by_tag to use smart hashtags

session.set_smart_location_hashtags(['204517928/chicago-illinois', '213570652/nagoya-shi-aichi-japan'], radius=20, limit=10)
session.like_by_tags(amount=10, use_smart_location_hashtags=True)

Parameters

radius: Radius around the location in Miles
limit: Defines amount limit of generated hashtags by hashtag
log_tags: Shows generated hashtags before use it (default is True)

Quota Supervisor

Take full control of the actions with the most sophisticated approaches
session.set_quota_supervisor(enabled=True, sleep_after=["likes", "comments_d", "follows", "unfollows", "server_calls_h"], sleepyhead=True, stochastic_flow=True, notify_me=True,
                              peak_likes_hourly=57,
                              peak_likes_daily=585,
                               peak_comments_hourly=21,
                               peak_comments_daily=182,
                                peak_follows_hourly=48,
                                peak_follows_daily=None,
                                 peak_unfollows_hourly=35,
                                 peak_unfollows_daily=402,
                                  peak_server_calls_hourly=None,
                                  peak_server_calls_daily=4700)

Parameters:

enabled: put True to activate or False to deactivate supervising any time

If you don't want to supervise likes at all, simply remove peak_likes parameter OR use peak_likes=(None, None).
Once likes reach peak, it will jump every other like, yet, will do all available actions (e.g. follow or unfollow).

  • Only server calls does not jump, it exits the program once reaches the peak.

Although, you can put server calls to sleep once reaches peak, read sleep_after parameter.

  • Every action will be jumped separately after reaching it's peak, except comments. Cos commenting without a like isn't welcomed that's why as like peak is reached, it will jump comments, too.

sleep_after: is used to put InstaPy to sleep after reaching peak rather than jumping the action (or exiting- for server calls)
Any action can be included ["likes", "comments", "follows", "unfollows", "server_calls"].
As if you want to put sleep only after reaching hourly like peak, put "likes_h" OR put "likes_d" for sleeping only after reaching daily like peak.
such as,

  • sleep_after=['follows_h'] will sleep after reaching hourly follow peak
  • sleep_after=['likes_d', 'follows', 'server_calls_h'] will sleep after reaching daily like peak, follow peaks (hourly and daily) and hourly server call peak.

Notice: there can be either "likes" (for both hourly and daily sleep) OR "likes_h" (for hourly sleep only) OR "likes_d" (for daily sleep only).

Once gone to sleep, it will wake up as new hour/day (according to the interval) arrives AND continue the activity.

sleepyhead: can help to sound more humanly which will wake up a little bit later in a randomly chosen time interval around accurate wake up time.

e.g., if remaining time is 17 minutes, it will sleep 20 minutes instead (random values each time)..

stochastic_flow: can provide smooth peak value generation by your original values.

  • Every ~hour/day it will generate peaks at close range around your original peaks (but below them).

e.g., your peak likes hourly is 45, next hour that peak will be 39, the next 43, etc.

notify_me: sends toast notifications (directly to your OS) about the important states of supervisor- sleep, wake up and exit messages.

Mini-Examples:

  • Claudio has written a new 😊 quickstart script where it mostly put likes and comments. He wants the program to comment safely cos he is afraid of exceeding hourly & daily comment limits,
session.set_quota_supervisor(enabled=True, peak_comments_daily=21, peak_comments_hourly=240)

That's it! When it reaches the comments peak, it will just jump all of the comments and will again continue to put comments when is available [in the next hour/day].

  • Alicia has a 24/7 🕦 working quickstart script and would like to keep server calls in control to AVOID excessive amount of requests to the server in hourly basis, also,
    • wants the program to sleep after reaching hourly server calls peak: adds "server_calls_h" into sleep_after parameter
    • wants the program to wake up a little bit later than real sleep time [once reaches the peaks]: uses sleepyhead=True parameter
session.set_quota_supervisor(enabled=True, peak_server_calls_daily=490, sleep_after=["server_calls_h"], sleepyhead=True)

It will sleep after hourly server calls reaches its peak given - 490 and never allow one more extra request to the server out of the peak and wake up when new hour comes in WHILST daily server calls will not be supervised at all- as Alicia wishes.

  • Sam has a casual 🦆 quickstart script full of follow/unfollow features and he wants to do it safely, also,
    • is gonna run on local computer and wants to receive toast notifications 😋 on supervising states: uses notify_me parameter
    • wants QS to randomize his pre-defined peak values [at close range] each new hour/day: uses stochastic_flow=True parameter
    • wants the program to sleep after reaching hourly follow peak and daily unfollow peak: adds "follows_h" and "unfollows_d"into sleep_after parameter
session.set_quota_supervisor(enabled=True, peak_follows_daily=560, peak_follows_hourly=56, peak_unfollows_hourly=49, peak_unfollows_daily=550, sleep_after=["follows_h", "unfollows_d"], stochastic_flow=True, notify_me=True)

Big Hint: Find your NEED 🤔 and supervise it!

  • EITHER fully configure QS to supervise all of the actions all time
  • OR just supervise the desired action(s) in desired interval(s) [hourly and/or daily] per your need

Restricting Likes

session.set_dont_like(['#exactmatch', '[startswith', ']endswith', 'broadmatch'])

.set_dont_like searches the description and owner comments for hashtags and won't like the image if one of those hashtags are in there

You have 4 options to exclude posts from your InstaPy session:

  • words starting with # will match only exact hashtags (e. g. #cat matches #cat, but not #catpic)
  • words starting with [ will match all hashtags starting with your word (e. g. [cat matches #catpic, #caturday and so on)
  • words starting with ] will match all hashtags ending with your word (e. g. ]cat matches #mycat, #instacat and so on)
  • words without these prefixes will match all hashtags that contain your word regardless if it is placed at the beginning, middle or end of the hashtag (e. g. cat will match #cat, #mycat, #caturday, #rainingcatsanddogs and so on)

Ignoring Restrictions

# will ignore the don't like if the description contains
# one of the given words

session.set_ignore_if_contains(['glutenfree', 'french', 'tasty'])

Ignoring Users

# completely ignore liking images from certain users

session.set_ignore_users(['random_user', 'another_username'])

Excluding friends

# will prevent commenting on and unfollowing your good friends (the images will
# still be liked)

session.set_dont_include(['friend1', 'friend2', 'friend3'])

Mandatory Words

session.set_mandatory_words(['#food', '#instafood'])

.set_mandatory_words searches the description, location and owner comments for words and will like the image if the mandatory words condition is met.
The mandatory words list can be a simple list of words or a nested structure of lists within lists.

  • When using a simple word list the condition between the words is "OR" so if any of the words from the list exists in the image text it will be matched.
  • When using a nested list of lists the top level list condition is "OR" and the condition alternates between "AND" and "OR" with every nesting level.

For example:

     # either "icecave" or "ice_cave" will satisfy this:
     ["icecave", "ice_cave"]
    
    # either "high_mountain" OR ("high" AND "mountain") will satisfy this:
    ["high_mountain", ["high", "mountain"]]

    # Only ("high" AND "tide" together) will satisfy this:
    [["high", "tide"]]

    # Only "summer" AND ("lake" OR "occean") will satisfy this:
    [["summer", ["lake", "occean"]]

Mandatory Language

session.set_mandatory_language(enabled=True, character_set=['LATIN'])
session.set_mandatory_language(enabled=True, character_set=['LATIN', 'CYRILLIC'])

.set_mandatory_language restrict the interactions, liking and following if any character of the description is outside of the character sets you selected (the location is not included and non-alphabetic characters are ignored). For example if you choose LATIN, any character in Cyrillic will flag the post as inappropriate. If you choose 'LATIN' and 'CYRILLIC', any other character sets will flag the post as inappropriate as well.

  • Available character sets: LATIN, GREEK, CYRILLIC, ARABIC, HEBREW, CJK, HANGUL, HIRAGANA, KATAKANA and THAI

Don't unfollow active users

# Prevents unfollow followers who have liked one of your latest 5 posts

session.set_dont_unfollow_active_users(enabled=True, posts=5)

Blacklist Campaign

# Controls your interactions by campaigns.
# ex. this week InstaPy will like and comment interacting by campaign called
# 'soccer', next time InstaPy runs, it will not interact again with users in
# blacklist
# In general, this means that once we turn off the soccer_campaign again, InstaPy
# will have no track of the people it interacted with about soccer.
# This will help you target people only once but several times for different campaigns

session.set_blacklist(enabled=True, campaign='soccer_campaign')
session.set_do_comment(True, percentage=50)
session.set_comments(['Neymar is better than CR7', 'Soccer is cool'])
session.like_by_tags(['soccer', 'cr7', 'neymar'], amount=100, media='Photo')

Simulation

During indirect data retrieval, simulation happens to provide a genuine activity flow triggered by a wise algorithm.

To turn off simulation or to decrease its occurrence frequency, use set_simulation setting:

#use the value of `False` to permanently turn it off
session.set_simulation(enabled=False)

#use a desired occurrence percentage
session.set_simulation(enabled=True, percentage=66)

Skipping user for private account, no profile picture, business account, bio keywords

This is used to skip users with certain condition

session.set_skip_users(skip_private=True,
                       private_percentage=100,
                       skip_no_profile_pic=False,
                       no_profile_pic_percentage=100,
                       skip_business=False,
                       skip_non_business=False,
                       business_percentage=100,
                       skip_business_categories=[],
                       dont_skip_business_categories=[],
                       skip_bio_keyword=[],
                       mandatory_bio_keywords=[])
Skip private account

This is done by default

session.set_skip_users(skip_private=True,
                       private_percentage=100)

Will skip users that have private account, even if are followed by running account. You can set a percentage of skipping: private_percentage= 100 always skip private users private_percentage= 0 never skip private users (so set skip_private=False)

Skip users that don't have profile picture
session.set_skip_users(skip_private=True,
                       skip_no_profile_pic=True,
                       no_profile_pic_percentage=100)

Will skip users that haven't uploaded yet a profile picture You can set a percentage of skipping: no_profile_pic_percentage= 100 always skip users without profile picture no_profile_pic_percentage= 0 never skip users without profile picture (so set skip_no_profile_pic=False)

Skip users that have business account
session.set_skip_users(skip_private=True,
                       skip_no_profile_pic=True,
                       skip_business=True,
                       business_percentage=100)

This will skip all users that have business account activated. You can set a percentage of skipping: business_percentage= 100 always skip business users business_percentage= 0 never skip business users (so set skip_business=False)

N.B.: This business_percentage parameter works only if no skip_business_categories or dont_skip_business_categories are provided!

Skip only users that have certain business account
session.set_skip_users(skip_private=True,
                       skip_no_profile_pic=True,
                       skip_business=True,
                       skip_business_categories=['Creators & Celebrities'])

This will skip all business accounts that have category in given list N.B. In skip_business_categories you can add more than one category

Skip all business accounts, except from list given
session.set_skip_users(skip_private=True,
                       skip_no_profile_pic=True,
                       skip_business=True,
                       dont_skip_business_categories=['Creators & Celebrities'])

This will skip all business accounts except the ones that have a category that matches one item in the list of dont_skip_business_categories N.B. If both dont_skip_business_categories and skip_business_categories, InstaPy will skip only business accounts in the list given from skip_business_categories.

A list of all availlable business categories can be found here

Skip all non business and bussines accounts, except from list given
session.set_skip_users(skip_private=True,
                       skip_no_profile_pic=True,
                       skip_business=True,
                       skip_non_business=True,
                       dont_skip_business_categories=['Creators & Celebrities'])

This will skip all non business and business accounts except categories in dont_skip_business_categories.

Skip based on bio keywords
session.set_skip_users(skip_bio_keyword=["lifestyle"],
                       mandatory_bio_keywords=["art", "photography"])

This will skip users that have "lifestyle" and users that don't have "art" or "photography" in their bio or username. See the Mandatory Words section for details on how to define complex mandatory words conditions.

Liking based on the number of existing likes a post has

This is used to check the number of existing likes a post has and if it either exceed the maximum value set OR does not pass the minimum value set then it will not like that post
session.set_delimit_liking(enabled=True, max_likes=1005, min_likes=20)

Use enabled=True to activate and enabled=False to deactivate it, any time
max is the maximum number of likes to compare
min is the minimum number of likes to compare

You can use both max & min values OR one of them as you desire, just put the value of None to the one you don't want to check for., e.g.,

session.set_delimit_liking(enabled=True, max_likes=242, min_likes=None)

at this configuration above, it will not check number of the existing likes against minimum value

  • Example:
session.set_delimit_liking(enabled=True, max_likes=500, min_likes=7)

Now, if a post has more existing likes than maximum value of 500, then it will not like that post, similarly, if that post has less existing likes than the minimum value of 7, then it will not like that post...

Commenting based on the number of existing comments a post has

This is used to check the number of existing comments a post has and if it either exceed the maximum value set OR does not pass the minimum value set then it will not comment on that post
session.set_delimit_commenting(enabled=True, max_comments=32, min_comments=0)

Use enabled=True to activate and enabled=False to deactivate it, any time
max is the maximum number of comments to compare
min is the minimum number of comments to compare

You can use both max & min values OR one of them as you desire, just leave it out or put it to None to the one you don't want to check for., e.g.,

session.set_delimit_commenting(enabled=True, min_comments=4)
# or
session.set_delimit_commenting(enabled=True, max_comments=None, min_comments=4)

at this configuration above, it will not check number of the existing comments against maximum value

  • Example:
session.set_delimit_commenting(enabled=True, max_comments=70, min_comments=5)

Now, if a post has more comments than the maximum value of 70, then it will not comment on that post, similarly, if that post has less comments than the minimum value of 5, then it will not comment on that post...

Commenting based on mandatory words in the description or first comment

This is used to check the description of the post and the first comment of the post (some users only put tags in the comments instead of the post description) for the occurence of mandatory words before commenting. If none of the mandatory words is present, the post will not be commented.

This feature is helpful when you want to comment only on specific tags.

session.set_delimit_commenting(enabled=True, comments_mandatory_words=['cat', 'dog'])

This will only comment on posts that contain either cat or dog in the post description or first comment. You can also require sets of words. See the Commenting section for detains on how to do that

Interactions based on the number of followers and/or following a user has

This is used to check the number of followers and/or following a user has and if these numbers either exceed the number set OR does not pass the number set OR if their ratio does not reach desired potency ratio then no further interaction happens
session.set_relationship_bounds(enabled=True,
				 potency_ratio=1.34,
				  delimit_by_numbers=True,
				   max_followers=8500,
				    max_following=4490,
				     min_followers=100,
				      min_following=56,
				       min_posts=10,
                max_posts=1000)

Use enabled=True to activate this feature, and enabled=False to deactivate it, any time
delimit_by_numbers is used to activate & deactivate the usage of max & min values
potency_ratio accepts values in 2 formats according to your style: positive & negative

  • potency_ratio with POSITIVE values can be used to route interactions to only potential (real) users WHOSE followers count is higher than following count (e.g., potency_ratio = 1.39)
    find desired potency_ratio with this formula: potency_ratio == followers count / following count (use desired counts)

e.g., target user has 5000 followers & 4000 following and you set potency_ratio=1.35.
Now it will not interact with this user, cos the user's relationship ratio is 5000/4000==1.25 and 1.25 is below desired potency_ratio of 1.35

  • potency_ratio with NEGATIVE values can be used to route interactions to only massive followers WHOSE following count is higher than followers count (e.g., potency_ratio = -1.42)
    find desired potency_ratio with this formula: potency_ratio == following count / followers count (use desired counts)

e.g., target user has 2000 followers & 3000 following and you set potency_ratio = -1.7.
Now it will not interact with this user, cos the user's relationship ratio is 3000/2000==1.5 and 1.5 is below desired potency_ratio of 1.7 (note that, negative - sign is only used to determine your style, nothing more)

There are 3 COMBINATIONS available to use:
  • 1. You can use potency_ratio or not (e.g., potency_ratio=None, delimit_by_numbers=True) - will decide only by your pre-defined max & min values regardless of the potency_ratio
session.set_relationship_bounds(enabled=True, potency_ratio=None, delimit_by_numbers=True, max_followers=22668, max_following=10200, min_followers=400, min_following=240)
  • 2. You can use only potency_ratio (e.g., potency_ratio=-1.5, delimit_by_numbers=False) - will decide per potency_ratio regardless of the pre-defined max & min values
session.set_relationship_bounds(enabled=True, potency_ratio=-1.5, delimit_by_numbers=False, max_followers=400701, max_following=90004, min_followers=963, min_following=2310)

apparently, once delimit_by_numbers gets False value, max & min values do not matter

  • 3. You can use both potency_ratio and pre-defined max & min values together (e.g., potency_ratio=2.35, delimit_by_numbers=True) - will decide per potency_ratio & your pre-defined max & min values
session.set_relationship_bounds(enabled=True, potency_ratio=2.35, delimit_by_numbers=True, max_followers=10005, max_following=24200, min_followers=77, min_following=500)

All of the 4 max & min values are able to freely operate, e.g., you may want to only delimit max_followers and min_following (e.g., max_followers=52639, max_following=None, min_followers=None, min_following=2240)

session.set_relationship_bounds(enabled=True, potency_ratio=-1.44, delimit_by_numbers=True, max_followers=52639, max_following=None, min_followers=None, min_following=2240)

Interactions based on the number of posts a user has

This is used to check number of posts of a user and skip if they aren't in the boundaries provided

session.set_relationship_bounds(min_posts=10,
                                 max_posts=1000)

Users that have more than 1000 posts or less than 10 will be discarded

N.B.: It is up to the user to check that min_posts < max_posts

You can also set only one parameter at a time:

session.set_relationship_bounds(max_posts=1000)

Will skip only users that have more than 1000 posts in their feed

Custom action delays

After doing each action- like, comment, follow, unfollow or story, there is a sleep delay to provide smooth activity flow.
But you can set a custom sleep delay for each action yourself by using the set_action_delays setting!
session.set_action_delays(enabled=True,
                           like=3,
                           comment=5,
                           follow=4.17,
                           unfollow=28,
                           story=10)

Now it will sleep 3 seconds after putting every single like, 5 seconds for every single comment and similarly for the others..

You can also customize the sleep delay of e.g. only the likes:

session.set_action_delays(enabled=True, like=3)
Wanna go smarter? - use random_range_from and random_range_to

By just enabling randomize parameter, you can enjoy having random sleep delays at desired range, e.g.,

session.set_action_delays(enabled=True, like=5.2, randomize=True, random_range_from=70, random_range_to=140)

There, it will have a random sleep delay between 3.64 (70% of 5.2) and 7.28(140% of 5.2) seconds each time after putting a like.

  • You can also put only the max range as- random_range_from=None, random_range_to=200
    Then, the min range will automatically be 100%- the same time delay itself.
    And the random sleep delays will be between 5.2 and 10.4 seconds.
  • If you put only the min range as- random_range_from=70, random_range_to=None
    Then, the max range will automatically be 100%- the same time delay itself.
    And the random sleep delays will be between 3.64 and 5.2 seconds.
  • But if you put None to both min & max ranges as- random_range_from=None, random_range_to=None
    Then no randomization will occur and the sleep delay will always be 5.2 seconds.
  • Heh! You mistakenly put min range instead of max range as- random_range_from=100, random_range_to=70?
    No worries. It will automatically take the smaller number as min and the bigger one as max.
  • Make sure to use the values bigger than 0 for the random_rage percentages.
    E.g. random_range_from=-10, random_range_to=140 is an invalid range and no randomization will happen.
  • You can provide floating point numbers as percentages, too!
    random_range_from=70.7, random_range_to=200.45 will work greatly.
Note: There is a minimum default delay for each action and if you enter a smaller time of delay than the default value, then it will pick the default value. You can turn that behaviour off with safety_match parameter.
session.set_action_delays(enabled=True, like=0.15, safety_match=False)

It has been held due to safety considerations. Cos sleeping a respective time after doing actions- for example ~10 seconds after an unfollow, is very important to avoid possible temporary blocks and if you might enter e.g. 3 seconds for that without realizing the outcome...

Target Lists

This is used to parse text files containing target lists of users, hashtags, comments etc

For example:

# Like posts based on hashtags
hashtags = session.target_list("C:\\Users\\......\\hashtags.txt")
session.like_by_tags(hashtags, amount=10)

# Follow the followers of each given user
users = session.target_list("C:\\Users\\......\\users.txt")
session.follow_user_followers(users, amount=10, randomize=False)

Note that your text file should look like this:

hashtag1
hashtag2
hashtag3

or

user1
user2
user3

Functions you can use target_list with:

story_by_user, story_by_tag, like_by_tags, follow_by_tags, follow_user_followers, follow_user_following, follow_likers, follow_commenters, follow_by_list, set_skip_users, set_ignore_users, set_dont_include, interact_by_users, interact_by_users_tagged_posts, interact_user_followers, interact_user_following, interact_by_comments, set_comments, set_comment_replies, set_mandatory_words, unfollow_users




Actions

Like by Tags

# Like posts based on hashtags
session.like_by_tags(['natgeo', 'world'], amount=10)

Parameters:

tags: The tags that will be searched for and posts will be liked from

amount: The amount of posts that will be liked

skip_top_posts: Determines whether the first 9 top posts should be liked or not (default is True)

use_smart_hashtags: Make use of the smart hashtag feature

use_smart_location_hashtags: Make use of the smart location hashtag feature

interact: Defines whether the users of the given post should also be interacted with (needs set_user_interact to be also set)

randomize: Determines whether the first amount of posts should be liked or a random selection.

media: Determines which media should be liked, Photo or Video (default is None which is all)

Like by Tags and interact with user

# Like posts based on hashtags and like 3 posts of its poster
session.set_user_interact(amount=3, randomize=True, percentage=100, media='Photo')
session.like_by_tags(['natgeo', 'world'], amount=10, interact=True)

Like by Feeds

# This is used to perform likes on your own feeds
# amount=100  specifies how many total likes you want to perform
# randomize=True randomly skips posts to be liked on your feed
# unfollow=True unfollows the author of a post which was considered
# inappropriate interact=True visits the author's profile page of a
# certain post and likes a given number of his pictures, then returns to feed

session.like_by_feed(amount=100, randomize=True, unfollow=True, interact=True)

Like by Locations

session.like_by_locations(['224442573/salton-sea/'], amount=100)
# or
session.like_by_locations(['224442573'], amount=100)
# or include media entities from top posts section

session.like_by_locations(['224442573'], amount=5, skip_top_posts=False)

You can find locations for the like_by_locations function by:

Example:

Comment by Locations

session.comment_by_locations(['224442573/salton-sea/'], amount=100)
# or
session.comment_by_locations(['224442573'], amount=100)
# or include media entities from top posts section

session.comment_by_locations(['224442573'], amount=5, skip_top_posts=False)

This method allows commenting by locations, without liking posts. To get locations follow instructions in 'Like by Locations'

Follow by Tags

# Follow user based on hashtags (without liking the image)

session.follow_by_tags(['tag1', 'tag2'], amount=10)

Parameters:

tags: The tags that will be searched for and authors of the posts will be followed.

amount: The amount of posts that the author of the post will be followed

skip_top_posts: Determines whether the first 9 top users of posts should be followed or not (default is True)

use_smart_hashtags: Make use of the smart hashtag feature

use_smart_location_hashtags: Make use of the smart location hashtag feature

interact: Defines whether the users of the given post should also be interacted with (needs set_user_interact to be also set)

randomize: Determines whether the first amount of post authors should be liked or a random selection.

media: Determines which media should be considered, Photo or Video (default is None which is all)

Follow by Locations

session.follow_by_locations(['224442573/salton-sea/'], amount=100)
# or
session.follow_by_locations(['224442573'], amount=100)
# or include media entities from top posts section

session.follow_by_locations(['224442573'], amount=5, skip_top_posts=False)

This method allows following by locations, without liking or commenting posts. To get locations follow instructions in 'Like by Locations'

Following by a list

This will follow each account from a list of instagram nicknames
follow_by_list(followlist=['samantha3', 'larry_ok'], times=1, sleep_delay=600, interact=False)

only follows a user once (if unfollowed again) would be useful for the precise targeting
sleep_delay is used to define break time after some good following (averagely ~10 follows)
For example, if one needs to get followbacks from followers of a chosen account/group of accounts.

accs = ['therock','natgeo']
session.follow_by_list(accs, times=1, sleep_delay=600, interact=False)
  • You can also interact with the followed users by enabling interact=True which will use the configuration of set_user_interact setting:
session.set_user_interact(amount=4,
				 percentage=50,
                  randomize=True,
                   media='Photo')
session.follow_by_list(followlist=['samantha3', 'larry_ok'], times=2, sleep_delay=600, interact=True)

Follow someone else's followers

# Follows the followers of each given user
# The usernames can be either a list or a string
# The amount is for each account, in this case 30 users will be followed
# If randomize is false it will pick in a top-down fashion

session.follow_user_followers(['friend1', 'friend2', 'friend3'], amount=10, randomize=False)

# default sleep_delay=600 (10min) for every 10 user following, in this case
# sleep for 60 seconds

session.follow_user_followers(['friend1', 'friend2', 'friend3'], amount=10, randomize=False, sleep_delay=60)

Note: simulation takes place while running this feature.

Follow users that someone else is following

# Follows the people that a given users are following
# The usernames can be either a list or a string
# The amount is for each account, in this case 30 users will be followed
# If randomize is false it will pick in a top-down fashion

session.follow_user_following(['friend1', 'friend2', 'friend3'], amount=10, randomize=False)

# default sleep_delay=600 (10min) for every 10 user following, in this case
# sleep for 60 seconds

session.follow_user_following(['friend1', 'friend2', 'friend3'], amount=10, randomize=False, sleep_delay=60)

Note: simulation takes place while running this feature.

Follow and interact someone else's followers/following

# For 50% of the 30 newly followed, move to their profile
# and randomly choose 5 pictures to be liked.
# Take into account the other set options like the comment rate
# and the filtering for inappropriate words or users

session.set_user_interact(amount=5, randomize=True, percentage=50, media='Photo')
session.follow_user_followers(['friend1', 'friend2', 'friend3'], amount=10, randomize=False, interact=True)

Follow the likers of photos of users

This will follow the people those liked photos of given list of users
session.follow_likers(['user1' , 'user2'], photos_grab_amount = 2, follow_likers_per_photo = 3, randomize=True, sleep_delay=600, interact=False)

in this case 2 random photos from each given user will be analyzed and 3 people who liked them will be followed, so 6 follows in total
The usernames can be any list
The photos_grab_amount is how many photos will I grat from users profile and analyze who liked it
The follow_likers_per_photo is how many people to follow per each photo
randomize=False will take photos from newes, true will take random from first 12
sleep_delay is used to define break time after some good following (averagely ~10 follows)

  • You can also interact with the followed users by enabling interact=True which will use the configuration of set_user_interact setting:
session.set_user_interact(amount=2,
				 percentage=70,
                  randomize=True,
                   media='Photo')
session.follow_likers(['user1' , 'user2'], photos_grab_amount = 2, follow_likers_per_photo = 3, randomize=True, sleep_delay=600, interact=True)

Follow the commenters of photos of users

This will follow the people those commented on photos of given list of users
session.follow_commenters(['user1', 'user2', 'user3'], amount=100, daysold=365, max_pic = 100, sleep_delay=600, interact=False)

in this case (max 100 newest photos & maximum 365 days old) from each given user will be analyzed and 100 people who commented the most will be followed
The usernames can be any list
The amount is how many people to follow
The daysold will only take commenters from photos no older than daysold days
The max_pic will limit number of photos to analyze
sleep_delay is used to define break time after some good following (averagely ~10 follows)

  • You can also interact with the followed users by enabling interact=True which will use the configuration of set_user_interact setting:
session.set_user_interact(amount=3,
				 percentage=32,
                  randomize=True,
                   media='Video')
session.follow_commenters(['user1', 'user2', 'user3'], amount=100, daysold=365, max_pic = 100, sleep_delay=600, interact=True)

Unfollowing

Unfollows the accounts you're following

It will unfollow ~10 accounts and sleep for ~10 minutes and then will continue to unfollow...

There are 4 Unfollow methods available to use:

|> customList |> InstapyFollowed |> nonFollowers |> allFollowing

1 - Unfollow specific users from a CUSTOM list (has 2 tracks- "all" and "nonfollowers"):
when track is "all", it will unfollow all of the users in a given list;

custom_list = ["user_1", "user_2", "user_49", "user332", "user50921", "user_n"]
session.unfollow_users(amount=84, custom_list_enabled=True, custom_list=custom_list, custom_list_param="all", style="RANDOM", unfollow_after=55*60*60, sleep_delay=600)

if track is "nonfollowers", it will unfollow all of the users in a given list WHO are not following you back;

custom_list = ["user_1", "user_2", "user_49", "user332", "user50921", "user_n"]
session.unfollow_users(amount=84, custom_list_enabled=True, custom_list=custom_list, custom_list_param="nonfollowers", style="RANDOM", unfollow_after=55*60*60, sleep_delay=600)
  • PRO: customList method can take any kind of iterable container, such as list, tuple or set.

2 - Unfollow the users WHO was followed by InstaPy (has 2 tracks- "all" and "nonfollowers"):
again, if you like to unfollow all of the users followed by InstaPy, use the track- "all";

session.unfollow_users(amount=60, instapy_followed_enabled=True, instapy_followed_param="all", style="FIFO", unfollow_after=90*60*60, sleep_delay=501)

but if you like you unfollow only the users followed by InstaPy WHO do not follow you back, use the track- "nonfollowers";

session.unfollow_users(amount=60, instapy_followed_enabled=True, instapy_followed_param="nonfollowers", style="FIFO", unfollow_after=90*60*60, sleep_delay=501)

3 - Unfollow the users WHO do not follow you back:

session.unfollow_users(amount=126, nonFollowers=True, style="RANDOM", unfollow_after=42*60*60, sleep_delay=655)

4 - Just unfollow, regardless of a user follows you or not:

session.unfollow_users(amount=40, allFollowing=True, style="LIFO", unfollow_after=3*60*60, sleep_delay=450)

Parameters (all of these parameters apply to all of the 4 methods available):

style
You can choose unfollow style as "FIFO" (First-Input-First-Output) OR "LIFO" (Last-Input-First-Output) OR "RANDOM".

  • with "FIFO", it will unfollow users in the exact order they are loaded ("FIFO" is the default style unless you change it);
  • with "LIFO" it will unfollow users in the reverse order they were loaded;
  • with "RANDOM" it will unfollow users in the shuffled order;

unfollow_after
By using this, you can unfollow users only after following them certain amount of time.
it will help to provide seamless unfollow activity without the notice of the target user
To use it, just add unfollow_after parameter with the desired time interval, e.g.,

session.unfollow_users(amount=94, instapy_followed_enabled=True, instapy_followed_param="all", style="RANDOM", unfollow_after=48*60*60, sleep_delay=600)

will unfollow users only after following them 48 hours (2 days).

  • Since unfollow_afters value is in seconds, you can simply give it unfollow_after=3600 to unfollow after 3600 seconds.
    Yeah, values kind of 1*60*60- which is also equal to 1 hour or 3600 seconds, is much more easier to use.

Sure if you like to not use it, give the value of None- unfollow_after=None.

sleep_delay
Sleep delay sets the time it will sleep after every ~10 unfollows (default delay is ~10 minutes).

NOTE: You should know that, in one RUN, unfollow_users feature can take only one method from all 4 above.
That's why, it is best to disable other 3 methods while using a one:

session.unfollow_users(amount=200, custom_list_enabled=True, custom_list=["user1", "user2", "user88", "user200"], instapy_followed_enabled=False, nonFollowers=False, allFollowing=False, style="FIFO", unfollow_after=22*60*60, sleep_delay=600)

here the unfollow method- customList is used
OR just keep the method you want to use and remove other 3 methods from the feature

session.unfollow_users(amount=200, allFollowing=True, style="FIFO", unfollow_after=22*60*60, sleep_delay=600)

here the unfollow method- alFollowing is used

Interact on posts at given URLs

Like, comment, follow on the post in the links provided, also can interact the owner of the post
session.interact_by_URL(urls=["some/URL/1", "some/URL/2" "other/URL"], randomize=True, interact=True)

To use, define all of the interaction settings and start the feature right away!

#define interaction settings
session.set_do_like(enabled=True, percentage=94)
session.set_do_comment(enabled=True, percentage=24)
session.set_comments(["Masterful shot", "Chilling!", "Unbelievably great..."])
session.set_do_follow(enabled=True, percentage=44)
session.set_user_interact(amount=6, randomize=True, percentage=72, media='Photo')

#start the feature
session.interact_by_URL(urls=["Fv0J4AJ3Y7r/?taken-at=628416252", "Vb0D4bJgY7r" "Dj0J4VJgY7r"], randomize=True, interact=True)
Parameters:

urls:
Contains the URLs of the posts to be interacted.

  • You can provide URLs in these formats:
    full: "https://www.IG.com/p/Aj0J4bJDY7r/?taken-at=128316221"
    just post link: "https://www.IG.com/p/Aj0J4bJDY7r/"
    just post handle: "Aj0J4bJDY7r/?taken-at=128316221"
    just post ID: "Aj0J4bJDY7r"

randomize:
Shuffles the order of the URLs in the given list before starts to interact.

interact:
Use it if you like to also interact the post owner after doing interactions on the post itself.

Interact with specific users

# Interact with specific users
# set_do_like, set_do_comment, set_do_follow are applicable

session.set_do_follow(enabled=False, percentage=50)
session.set_comments(["Cool", "Super!"])
session.set_do_comment(enabled=True, percentage=80)
session.set_do_like(True, percentage=70)
session.interact_by_users(['user1', 'user2', 'user3'], amount=5, randomize=True, media='Photo')

Interact with specific users' tagged posts

# Interact with specific users' tagged posts
# set_do_like, set_do_comment, set_do_follow are applicable

session.set_do_follow(enabled=False, percentage=50)
session.set_comments(["Cool", "Super!"])
session.set_do_comment(enabled=True, percentage=80)
session.set_do_like(True, percentage=70)
session.interact_by_users_tagged_posts(['user1', 'user2', 'user3'], amount=5, randomize=True, media='Photo')

Interact with someone else's followers

# Interact with the people that a given user is followed by
# set_do_comment, set_do_follow and set_do_like are applicable

session.set_user_interact(amount=5, randomize=True, percentage=50, media='Photo')
session.set_do_follow(enabled=False, percentage=70)
session.set_do_like(enabled=False, percentage=70)
session.set_comments(["Cool", "Super!"])
session.set_do_comment(enabled=True, percentage=80)
session.interact_user_followers(['natgeo'], amount=10, randomize=True)

Note: simulation takes place while running this feature.

Interact with users that someone else is following

# Interact with the people that a given user is following
# set_do_comment, set_do_follow and set_do_like are applicable

session.set_user_interact(amount=5, randomize=True, percentage=50, media='Photo')
session.set_do_follow(enabled=False, percentage=70)
session.set_do_like(enabled=False, percentage=70)
session.set_comments(["Cool", "Super!"])
session.set_do_comment(enabled=True, percentage=80)
session.interact_user_following(['natgeo'], amount=10, randomize=True)

Note: simulation takes place while running this feature.

Interact by Comments

Like comments on posts, reply to them and then interact by the users whose comment was liked on the post
session.interact_by_comments(usernames=["somebody", "other buddy"],
                             posts_amount=10,
                             comments_per_post=5,
                             reply=True,
                             interact=True,
                             randomize=True,
                             media="Photo")

Parameters

usernames : A list containing the usernames of users on WHOSE posts' comments will be interacted;

posts_amount : Number of the posts to get from each user for interacting by comments;

comments_per_post : Choose how many comments to interact (like and then reply) on each post;

reply : Choose if it should reply to comments;

interact : Use if you also like to interact the commenters after finishing liking (and then replying to) comments on the post;

randomize : Shuffles the order of the posts from users' feed and comments in the given post;

media : Choose the type of media to be interacted - "Photo" for photos, "Video" for videos, None for any media;

Usage

To use, set replying and interaction configuration(s)

session.set_do_reply_to_comments(enabled=True, percentage=14)
session.set_comment_replies(replies=[u"😎😎😎", u"😁😁😁😁😁😁😁💪🏼", u"😋🎉", "😀🍬", u"😂😂😂👈🏼👏🏼👏🏼", u"🙂🙋🏼‍♂️🚀🎊🎊🎊", u"😁😁😁", u"😂",  u"🎉",  u"😎", u"🤓🤓🤓🤓🤓", u"👏🏼😉"],
                            media="Photo")

session.set_user_interact(amount=2, percentage=70, randomize=False, media="Photo")
# also configure [at least] liking to be used while interacting with the commenters ...
session.set_do_like(enabled=True, percentage=94)

# start the feature
session.interact_by_comments(usernames=["somebody", "other.buddy"], posts_amount=10, comments_per_post=5, reply=True, interact=True, randomize=True, media="Photo")

Note: To be able to reply to comments, you have to turn on text analytics- Yandex & MeaningCloud.
So that they will analyze the content of comments and if it is appropriate, will send a reply to the comment.
To configure those text analytics, see the usage in their sections.

There are 3 COMBINATIONS available to use regarding text analysis:
a-) ONLY Sentiment Analysis;
MeaningCloud must be turned on and Yandex must be enabled with a valid API key,

session.set_use_meaningcloud(enabled=True, license_key='', polarity="P")
session.set_use_yandex(enabled=True, API_key='')

b-) ONLY Language Match; Yandex must be turned on,

session.set_use_yandex(enabled=True, API_key='', match_language=False, language_code="en")

c-) BOTH Sentiment Analysis and Language Match; MeaningCloud and Yandex must be turned on,

session.set_use_meaningcloud(enabled=True, license_key='', polarity="P")
session.set_use_yandex(enabled=True, API_key='', match_language=True, language_code="en")

If you have followed any of those 3 text analysis combinations:
It will first analyze comments' content and if it is appropriate, then it will first like, then will reply to it.
All those inappropriate comments will neither be liked, nor replied to.

If you have not followed any of those 3 text analysis combinations OR misconfigured them:
Comments' content will not be able to be analyzed and that's why no any comments will be replied.
Yet, it will like all of the comments that are available.

In conclusion, the whole block SHOULD look like this,

session.set_use_meaningcloud(enabled=True, license_key='', polarity="P")
session.set_use_yandex(enabled=True, API_key='', match_language=True, language_code="en")

session.set_do_comment(enabled=True, percentage=14)
session.set_comment_replies(replies=[u"😎😎😎", u"😁😁😁😁😁😁😁💪🏼"], media="Photo")

session.set_user_interact(amount=2, percentage=70, randomize=False, media="Photo")
session.set_do_like(enabled=True, percentage=100)

session.interact_by_comments(usernames=["somebody", "other.buddy"], posts_amount=10, comments_per_post=5, reply=True, interact=True, randomize=True, media="Photo")

Extras

  • comments from the poster are ignored (those comments are mostly poster's replies);
  • owner's (logged in user) comments are also ignored;
  • if the commenter is in blacklist or ignored_users list, that comment will also be ignored;
  • it will take only one comment from each unique commenter;
  • as if there are any usable comments, it will first like the post itself before interacting by comments cos liking comments and replying to them without liking the post can look spammy;
  • it will reply to a comment only after liking it;
  • it will not send the same reply again on overall posts per each username in the list provided by you;

PROs

  • you can use this feature to auto-like comments, auto-reply to them on your own posts;
  • else than interacting by the comments in your own posts, you can use this feature to like lots of comments from other users' posts, reply to some of them and interact by those users just after liking & replying to their comments;

CONs

  • liking a comment doesn't fill up your like quota, but replying to a comment does it to the comment quota. Try to compensate it in your style and do not overuse;
  • using auto-reply capability of this feature can result in unwanted miscommunication between you and the commenter IN CASE OF you do not make an efficient use of text analytics;

Accept pending follow requests

session.accept_follow_requests(amount=100, sleep_delay=1)

amount
The maximum amount of follow requests that will be accepted.

sleep_delay
Sleep delay sets the time it will sleep after every accepted request (_default delay is ~ 1 second).

Remove outgoing follow requests

# Remove outgoing unapproved follow requests from private accounts

session.remove_follow_requests(amount=200, sleep_delay=600)

InstaPy Pods

In case you are unfamiliar with the concept do read a little. Here's a blog to learn more about Pods

photo_comments = ['Nice shot! @{}',
                 'I love your profile! @{}',
             'Your feed is an inspiration :thumbsup:',
             'Just incredible :open_mouth:',
             'What camera did you use @{}?',
             'Love your posts @{}',
             'Looks awesome @{}',
             'Getting inspired by you @{}',
             ':raised_hands: Yes!',
             'I can feel your passion @{} :muscle:']

session = InstaPy()

with smart_run(session):
   session.set_comments(photo_comments, media='Photo')
   session.join_pods()

Parameters:

topic:
Topic of the posts to be interacted with. general by default.

Note : Topics allowed are {'general', 'fashion', 'food', 'travel', 'sports', 'entertainment'}.

engagement_mode: Desided engagement mode for your posts. There are four levels of engagement modes 'no_comments', 'light', 'normal' and 'heavy'(normal by default). Setting engagement_mode to 'no_comments' makes you receive zero comments on your posts from pod members, 'light' encourages approximately 10% of pod members to comment on your post, similarly it's around 30% and 90% for 'normal' and 'heavy' modes respectively. Note: Liking, following or any other kind of engagements doesn't follow these modes.

Instapy Stories

Watching Stories with interact

Will add story watching while interacting with users

session.set_do_story(enabled = True, percentage = 70, simulate = True)

simulate: If set to True InstaPy will simulate watching the stories (you won't see it in the browser), we just send commands to Instagram saying we have watched the stories. If set to False Instapy will perform the exact same action as a human user (clicking on stories, waiting until watching finishes, etc...)

Please note: simulate = False is the safest settings as it fully disables all additional, simulated interactions

Watch stories by Tags

Will watch up to 20 stories published with specified tags.

session.story_by_tags(['tag1', 'tag2'])

Watch stories from users

Take a list of users and watch their stories.

session.story_by_users(['user1', 'user2'])



Third Party Features

Clarifai ImageAPI

Note: Head over to https://developer.clarifai.com/signup/ and create a free account, once you're logged in go to https://developer.clarifai.com/account/applications/ and create a new application. You can find the client ID and Secret there. You get 5000 API-calls free/month.

If you want the script to get your CLARIFAI_API_KEY for your environment, you can do:

export CLARIFAI_API_KEY="<API KEY>"

Example with Imagecontent handling

session.set_do_comment(True, percentage=10)
session.set_comments(['Cool!', 'Awesome!', 'Nice!'])
session.set_use_clarifai(enabled=True)
session.clarifai_check_img_for(['nsfw'])
session.clarifai_check_img_for(['food', 'lunch', 'dinner'], comment=True, comments=['Tasty!', 'Nice!', 'Yum!'])

session.end()

Enabling Imagechecking

# default enabled=False , enables the checking with the Clarifai API (image
# tagging) if secret and proj_id are not set, it will get the environment
# variables 'CLARIFAI_API_KEY'.

session.set_use_clarifai(enabled=True, api_key='xxx')

Using Clarifai Public Models and Custom Models

If not specified by setting the models=['model_name1'] in session.set_use_clarifai, models will be set to general by default.

If you wish to check against a specific model or multiple models (see Support for Compound Model Queries below), you can specify the models to be checked as shown below.

To get a better understanding of the models and their associated concepts, see the Clarifai Model Gallery and Developer Guide

NOTE ON MODEL SUPPORT: At this time, the support for theFocus, Face Detection, Face Embedding, and General Embedding has not been added.

# Check image using the NSFW model
session.set_use_clarifai(enabled=True, api_key='xxx', models=['nsfw'])

# Check image using the Apparel model
session.set_use_clarifai(enabled=True, api_key='xxx', models=['apparel'])

# Check image using the Celebrity model
session.set_use_clarifai(enabled=True, api_key='xxx', models=['celebrity'])

# Check image using the Color model
session.set_use_clarifai(enabled=True, api_key=xxx’, models=[‘model’])

# Check image using the Demographics model
session.set_use_clarifai(enabled=True, api_key=xxx’, models=[‘demographics’])

# Check image using the Food model
session.set_use_clarifai(enabled=True, api_key='xxx', models=['food'])

# Check image using the Landscape Quality model
session.set_use_clarifai(enabled=True, api_key='xxx', models=['landscape quality'])

# Check image using the Logo model
session.set_use_clarifai(enabled=True, api_key='xxx', models=['logo'])

# Check image using the Moderation model
session.set_use_clarifai(enabled=True, api_key='xxx', models=['moderation'])

# Check image using the Portrait Quality model
session.set_use_clarifai(enabled=True, api_key='xxx', models=['portrait quality'])

# Check image using the Textures and Patterns model
session.set_use_clarifai(enabled=True, api_key='xxx', models=['textures'])

# Check image using the Travel model
session.set_use_clarifai(enabled=True, api_key='xxx', models=['travel'])

# Chaeck image using the Weddings model
session.set_use_clarifai(enabled=True, api_key='xxx', models=['weddings'])

# Check image using a custom model where model_name is name of your choosing (see Clarifai documentation for using custom models)
session.set_use_clarifai(enabled=True, api_key='xxx', models=['your-model-name'])

Filtering Inappropriate Images

# uses the clarifai api to check if the image contains nsfw content
# by checking against Clarifai's NSFW model
# -> won't comment if image is nsfw

session.set_use_clarifai(enabled=True, api_key='xxx', models=['nsfw'])
session.clarifai_check_img_for(['nsfw'])
# uses the clarifai api to check if the image contains inappropriate content
# by checking against Clarifai's Moderation model
# -> won't comment if image is suggestive or explicit

session.set_use_clarifai(enabled=True, api_key='xxx', models=['moderation'])
session.clarifai_check_img_for(['suggestive', 'explicit'])

# To adjust the threshold for accepted concept predictions and their
# respective score (degree of confidence) you can set the default probability
# parameter for Clarifai (default 50%). For example, you could set probability to 15%.
# -> any image with a nsfw score of 0.15 of higher will not be commented on

session.set_use_clarifai(enabled=True, api_key='xxx', probability= 0.15, models=['nsfw'])
session.clarifai_check_img_for(['nsfw'])

Filtering by Keyword

# uses the clarifai api to check if the image concepts contain the keyword(s)
# -> won't comment if image contains the keyword

session.clarifai_check_img_for(['building'])

Specialized Comments for Images with Specific Content

# checks the image for keywords food and lunch. To check for both, set full_match in
# in session.set_use_clarifia to True, and if both keywords are found,
# InstaPy will comment with the given comments. If full_match is False (default), it only
# requires a single tag to match Clarifai results.

session.set_use_clarifai(enabled=True, api_key='xxx', full_match=True)
session.clarifai_check_img_for(['food', 'lunch'], comment=True, comments=['Tasty!', 'Yum!'])

# If you only want to accept results with a high degree of confidence, you could
# set a probability to a higher value, like 90%.

session.set_use_clarifai(enabled=True, api_key='xxx', probability=0.90, full_match=True)
session.clarifai_check_img_for(['food', 'lunch'], comment=True, comments=['Tasty!', 'Yum!'])

Querying Multiple Models with Workflow (Single API Call)

You can query multiple Clarifai models with a single API call by setting up a custom workflow. Using a workflow is the recommended way to query multiple models. Alternatively, it is possible to query multiple models separately (see Querying Multiple Models (Multiple API Calls) below).

To setup a workflow, see the Workflow Documentation.

NOTE :As mentioned above, the Focus, Face Detection, Face Embedding, and General Embedding models are not current supported.

Once you have a workflow setup, you can use InstaPy to check images with the Clarifai Image API by setting the workflow parameter in session.set_use_clarifai to the name of your custom workflow.

Let's say you want to comment 'Great shot!' on images of men or women with the hashtag #selfie, but you want to make sure not to comment on images which might contain inappropriate content. To get general concepts, e.g. woman, you would setup your workflow using General and to check the image for the concepts nsfw and explicit you would also want to add NSFW and Moderation models to your workflow.

For example:

session.set_use_clarifai(enabled=True, api_key='xxx', workflow=['your-workflow'], proxy='123.123.123.123:5555')
session.clarifai_check_img_for(['woman', 'man'], ['nsfw', 'explicit', 'suggestive'], comment=True, comments=['Great shot!'])

If Clarifai's response includes the concepts of either woman or man but also includes at least nsfw, explicit, or suggestive, InstaPy will not comment. On the other hand, if Clarifai's response includes the concepts of either woman or man but does not include any of the concepts nsfw, explicit, or suggestive, InstaPy will add the comment Great shot!

Querying Multiple Models (Multiple API Calls)

In the event that you do not want to set up a workflow, you can also query multiple models using multiple API calls.

WARNING: If you are using a free account with Clarifiai, be mindful that the using compound API queries could greatly increase your chances of exceeding your allotment of free 5000 operations per month. The number of Clarifai billable operations per image check equals the number of models selected. For example, if you check 100 images against models=['general', 'nsfw', 'moderation'], the total number of billable operations will be 300.

Following the example above, to get general concepts, e.g. woman, you would use the model general and to check the image for the concepts nsfw and explicit you would also want to check the image against the NSFW and Moderation models.

For example:

session.set_use_clarifai(enabled=True, api_key='xxx', models=['general', 'nsfw', 'moderation'], proxy=None)
session.clarifai_check_img_for(['woman', 'man'], ['nsfw', 'explicit', 'suggestive'], comment=True, comments=['Great shot!'])

Using proxy to access clarifai: We have 3 options:

  1. ip:port
  2. user:pass@ip:port
  3. None

Checking Video

WARNING: Clarifai checks one frame of video for content for every second of video. That is, in a 60 second video, 60 billable operations would be run for every model that the video is being checked against. Running checks on video should only be used if you have special needs and are prepared to use a large number of billable operations.

To have Clarifai run a predict on video posts, you can set the check_video argument in session.set_use_clarifai to True. By default, this argument is set to False. Even if you do not choose to check the entire video, Clarifai will still check the video's keyframe for content.

For example:

session.set_use_clarifai(enabled=True, api_key='xxx', check_video=True)

With video inputs, Clarifai's Predict API response will return a list of concepts at a rate of one frame for every second of a video.

Be aware that you cannot check video using a workflow and that only a select number of public models are currently supported. Models currently supported are: Apparel, Food, General, NSFW, Travel, and Wedding. In the event that the models being used do not support video inputs or you are using a workflow, the video's keyframe will still be checked for content.

Check out https://clarifai.com/demo to see some of the available tags.

Text Analytics

Yandex Translate API

Offers excellent language detection and synchronized translation for over 95 languages 😎 worldwide

This service currently is supported only by the Interact by Comments feature.

Usage

Go sign up on translate.yandex.com and get a free API_key;
Then configure its usage at your quickstart script,

session.set_use_yandex(enabled=True,
                       API_key='',
                       match_language=True,
                       language_code="en")
Parameters

enabled : Put True to activate or False to deactivate the service usage;

API_key : The key which is required to authenticate HTTP requests to the API;

match_language : Enable if you would like to match the language of the text;

language_code : Set your desired language's code to match language (if it's enabled);

You can get the list of all supported languages and their codes at tech.yandex.com.

Rate Limits

In its free plan, the daily request limit is 1,000,000 characters and the monthly limit is 10,000,000 characters.

To increase the request limit, you can switch to the fee-based version of the service ($15/million chars)..

Examples

1-) Matching language;

session.set_use_yandex(enabled=True, API_key='', match_language=True, language_code="az")

Target text : "your technique encourages📸 me"

Now that text is gonna be labeled inappropriate COS its language is english rather than the desired azerbaijani..

2-) Enabling the Yandex service but NOT matching language; Since Yandex Translate is being used [internally] by the MeaningCloud service, you can just provide the API key of Yandex and enable it without enabling the match_language parameter what will be sufficient for the MeaningCloud to work..

session.set_use_yandex(enabled=True, API_key='', match_language=False)

And yes, you can enable Yandex service to make it be available for MeaningCloud and then also match language if you like, in the same setup just by turning the match_language parameter on..

Legal Notice

Powered by Yandex.Translate

MeaningCloud Sentiment Analysis API

Offers a detailed, multilingual analysis of all kind of unstructured content determining its sentiment ⚖

This service currently is supported only by the Interact by Comments feature.

Determines if text displays positive, negative, or neutral sentiment - or is not possible to detect.
Phrases are identified with the relationship between them evaluated which identifies a global polarity value of the text.

Usage

1-) Go sign up (offers sign in with 😎 Github) on meaningcloud.com and get a free license_key;
Then configure its usage at your quickstart script,

session.set_use_meaningcloud(enabled=True,
                             license_key='',
                             polarity="P",
                             agreement="AGREEMENT",
                             subjectivity="SUBJECTIVE",
                             confidence=94)

2-) Install its package for python by pip;

pip install MeaningCloud-python

3-) Turn on Yandex Translate service which is a requirement for the language detection & translation at request;
To have it configured, read its documentation.

Parameters

enabled : Put True to activate or False to deactivate the service usage;

license_key : The license key is required to do calls to the API;

polarity : It indicates the polarity found (or not found) in the text and applies to the global polarity of the text;
It's a graduated polarity - rates from very negative to very positive.

score_tag definition
"P+" match if text is strong positive
"P" match if text is positive or above
"NEU" match if text is neutral or above
"N" match if text is negative or above
"N+" match if text is strong negative or above
None do not match per polarity found, at all

By "or above" it means- e.g., if you set polarity to "P", and text is "P+" then it'll also be appropriate (as it always leans towards positivity) ..

agreement : Identifies opposing opinions - contradictory, ambiguous;
It marks the agreement between the sentiments detected in the text, the sentence or the segment it refers to.

agreement definition
"AGREEMENT" match if the different elements have the same polarity
"DISAGREEMENT" match if there is disagreement between the different elements' polarity
None do not match per agreement found, at all

subjectivity : Identification of opinions and facts - distinguishes between objective and subjective;
It marks the subjectivity of the text.

subjectivity definition
"SUBJECTIVE" match if text that has subjective marks
"OBJECTIVE" match if text that does not have any subjectivity marks
None do not match per subjectivity found, at all

confidence : It represents the confidence associated with the sentiment analysis performed on the text and takes an integer number in the range of (0, 100];

If you don't want to match per confidence found, at all, use the value of None.

Rate Limits

It gives you 20 000 single API calls per each month (starting from the date you have signed up).
It has no daily limit but if you hit the limit set for number of requests can be carried out concurrently (per second) it'll return with error code of 104 rather than the result 😉

Language Support

MeaningCloud currently supports a generic sentiment model (called general) in these languages: english, spanish, french, italian, catalan, and portuguese.

You can define your own sentiment models using the user sentiment models console and work with them in the same way as with the sentiment models it provides.

But no need to worry IF your language or target audience's language is NONE of those officially supported.
Cos, to increase the coverage and support all other languages, as well, Yandex Translate service comes to rescue!
It detects the text's langugage before passing it to MeaningCloud, and, if its language is not supported by MeaningCloud, it translates it into english and only then passes it to MeaningCloud Sentiment Analysis..

Examples

a -) Match ONLY per polarity and agreement

session.set_use_meaningcloud(enabled=True, license_key='', polarity="P", agreement="AGREEMENT")

Target text : "I appreciate your innovative thinking that results, brilliant images"

Sentiment Analysis results for the text:

score_tag agreement subjectivity confidence
"P+" "AGREEMENT" "SUBJECTIVE" 100

Now that text is gonna be labeled appropriate COS its polarity is "P+" which is more positive than "P" and agreement values also do match..

b -) Match FULLY

session.set_use_meaningcloud(enabled=True, license_key='', polarity="P+", agreement="AGREEMENT", subjectivity="SUBJECTIVE", confidence=98)

Target text : "truly fantastic but it looks sad!"

Sentiment Analysis results for the text:

score_tag agreement subjectivity confidence
"P" "DISAGREEMENT" "SUBJECTIVE" 92

Now that text is gonna be labeled inappropriate COS its polarity is "P" which is less positive than "P+" and also, agreement values also do NOT match, and lastly, confidence is below user-defined 98..

Legal Notice

This project uses MeaningCloud™ (http://www.meaningcloud.com) for Text Analytics.


Telegram Integration

This feature allows to connect your InstaPy session with a Telegram bot and send commands to the InstaPy session

Prerequisites

You will need to create a token, for this go into your Telegram App and talk with @fatherbot. You will also need to set your username as it is checked to ensure that you are authorized to access the InstaPy session, to do so go to Settings -> Profile -> Username.

Supported actions

There are 3 supported actions:

  • /start : will start the interaction between the bot and instapy. Please note: that the telegram bot cannot send you messages until you first send it a /start message. The bot will store the chat_id in the logs folder file telegram_chat_id.txt to be reused in further sessions (so you have to actually do /start just one time)
  • /report : will gather and show the current session statistics
  • /stop: will set the aborting flag to True

Examples

from instapy.plugins import InstaPyTelegramBot

        session = InstaPy(username=insta_username,
                          password=insta_password,
                          bypass_with_mobile=True)
                          
        telegram = InstaPyTelegramBot(token='insert_real_token_here', telegram_username='my_username', instapy_session=session)

        # if you want to receive the information when the session ends
        # just add the following before your session.end()
        telegram.end()
        session.end()

Additional parameters:

  • debug=True if you want low level telegram debug information
  • proxy if you need one, here is the structure that needs to be passed
    example_proxy = {
         'proxy_url': 'http://PROXY_HOST:PROXY_PORT/',
         # Optional, if you need authentication:
         'username': 'PROXY_USER',
         'password': 'PROXY_PASS',
     }
     telegram = InstaPytelegramBot(... , proxy=example_proxy)

Additional functionality

you can use

telegram.send_message(text="this is a message")

So you are able to send additional message inside your script if needed. Remember that the telegram bot is not able to send messages as long as you haven't done at least one /start



Instance Settings

Running on a Headless Browser

Use headless_browser parameter to run the bot via the CLI. Works great if running the scripts locally, or to deploy on a server. No GUI, less CPU intensive. Example

Warning: Some users discourage the use of this feature as Instagram could detect this headless mode!

session = InstaPy(username='test', password='test', headless_browser=True)

(Alternative) If the web driver you're using doesn't support headless mode (or the headless mode becomes very detectable), you can use the nogui parameter which displays the window out of view. Keep in mind, this parameter lacks support and ease of use, only supporting Linux based operating systems (or those that have Xvfb, Xephyr and Xvnc display software).

session = InstaPy(username='test', password='test', nogui=True)

Bypass Suspicious Login Attempt

InstaPy detects automatically if the Security Code Challenge is active, if yes, it will ask you for the Security Code on the terminal.

The Security Code is send to your Email or SMS by Instagram, Email is the defaul option, but you can choose SMS also with:

bypass_security_challenge_using='sms' or bypass_security_challenge_using='email'

InstaPy(username=insta_username,
        password=insta_password,
        bypass_security_challenge_using='sms')

Use a proxy

You can use InstaPy behind a proxy by specifying server address, port and/or proxy authentication credentials. It works with and without headless_browser option.

Simple proxy setup example:

session = InstaPy(username=insta_username, 
                  password=insta_password,
		  proxy_address='8.8.8.8', 
		  proxy_port=8080)

Proxy setup with authentication example:

session = InstaPy(username=insta_username,
                  password=insta_password,
                  proxy_username='',
                  proxy_password='',
                  proxy_address='8.8.8.8',
                  proxy_port=4444)

Running internet connection checks

InstaPy can perform a few checks online, including you connection and the availability of Instagram servers. These checks sometimes fail because Instapy uses third party services to perform these checks. If this should be the case. you can override these checks with this variable: want_check_browser.

want_check_browser default is False, you can set it to True at session start. Recommend to do this if you want to add additional checks for the connection to the web and Instagram.

example:

session = InstaPy(username=insta_username,
                  password=insta_password,
                  want_check_browser=True)

Running in threads

If you're running InstaPy in threads and get exception ValueError: signal only works in main thread , you have to properly close the session. There is two ways to do it:

Closing session in smart_run context:

session = InstaPy()
with smart_run(session, threaded=True):
    """ Activity flow """
    # some activity here ...

Closing session with end() method

session = InstaPy()
session.login()
# some activity here ...
session.end(threaded_session=True)

Choose the browser version

If you have more than one Firefox version on your system or if you are using a portable version you can instruct InstaPy to use that version using the browser_executable_path argument in the class initializer.

Specifying the Firefox executable path can also help you if you are getting the following error message:

selenium.common.exceptions.SessionNotCreatedException: Message: Unable to find a matching set of capabilities

example on a Windows machine (with the right path also works on Linux and MAC)

session = InstaPy(username=insta_username,
                  password=insta_password,
                  browser_executable_path=r"D:\Program Files\Mozilla Firefox\firefox.exe")



Relationship tools

Grab Followers of a user

Gets and returns followers of the given user in desired amount, also can save locally
popeye_followers = session.grab_followers(username="Popeye", amount="full", live_match=True, store_locally=True)
##now, `popeye_followers` variable which is a list- holds the `Followers` data of "Popeye" at requested time

Parameters:

username:
A desired username to grab its followers

  • It can be your own username OR a username of some non-private account.

amount:
Defines the desired amount of usernames to grab from the given account

  • amount="full":
    • Grabs followers entirely
  • amount=3089:
    • Grabs 3089 usernames if exist, if not, grabs available amount

live_match:
Defines the method of grabbing Followers data

Knowledge Base:
Every time you grab Followers data in "full" range of any user, it is also gonna be stored in some corner of InstaPy for that session.

  • live_match=False:
    • If the user already do have a Followers data loaded earlier in the same session, it will run a smart data-matching algorithm.
      And there, it will load only the new data from the server and then return a compact result of current data.
      The algorithm works like: load the usernames until hits the ones from the previous query at certain amount.
    • Also if the live_match is False and the user has no any sessional Followers data, then it will load live data at requested range.
    • As a result, live_match=False saves lots of precious time and server requests.
  • live_match=True:
    • It will always load live data from the server at requested range.

store_locally:
Gives the option to save the loaded Followers data in a local storage
The files will be saved into your logs folder, ~/InstaPy/logs/YourOwnUsername/relationship_data/Popeye/followers/ directory.
Sample filename 14-06-2018~full~6874.json:

  • 14-06-2018 means the time of the data acquisition.
  • "full" means the range of the data acquisition;
    If the data is requested at the range else than "full", it will write that range.
  • 6874 means the count of the usernames retrieved.
  • json is the filetype and the data is stored as a list in it.

There are several use cases of this tool for various purposes.
E.g., inside your quickstart script, you can do something like this:

#get followers of "Popeye" and "Cinderella"
popeye_followers = session.grab_followers(username="Popeye", amount="full", live_match=True, store_locally=True)
sleep(600)
cinderella_followers = session.grab_followers(username="Cinderella", amount="full", live_match=True, store_locally=True)

#find the users following "Popeye" WHO also follow "Cinderella" :D
popeye_cinderella_followers = [follower for follower in popeye_followers if follower in cinderella_followers]

PROs

You can use this tool to take a backup of your or any other user's current followers.

Grab Following of a user

Gets and returns following of the given user in desired amount, also can save locally
lazySmurf_following = session.grab_following(username="lazy.smurf", amount="full", live_match=True, store_locally=True)
##now, `lazySmurf_following` variable which is a list- holds the `Following` data of "lazy.smurf" at requested time

Parameters:

username:
A desired username to grab its following

  • It can be your own username OR a username of some non-private account.

amount:
Defines the desired amount of usernames to grab from the given account

  • amount="full":
    • Grabs following entirely
  • amount=3089:
    • Grabs 3089 usernames if exist, if not, grabs available amount

live_match:
Defines the method of grabbing Following data

Knowledge Base:
Every time you grab Following data in "full" range of any user, it is also gonna be stored in some corner of InstaPy for that session.

  • live_match=False:
    • If the user already do have a Following data loaded earlier in the same session, it will run a smart data-matching algorithm.
      And there, it will load only the new data from the server and then return a compact result of current data. The algorithm works like: load the usernames until hits the ones from the previous query at certain amount.
    • Also if the live_match is False and the user has no any sessional Following data, then it will load live data at requested range.
    • As a result, live_match=False saves lots of precious time and server requests.
  • live_match=True:
    • It will always load live data from the server at requested range.

store_locally:
Gives the option to save the loaded Following data in a local storage
The files will be saved into your logs folder, ~/InstaPy/logs/YourOwnUsername/relationship_data/lazy.smurf/following/ directory.
Sample filename 15-06-2018~full~2409.json:

  • 15-06-2018 means the time of the data acquisition.
  • "full" means the range of the data acquisition;
    If the data is requested at the range else than "full", it will write that range.
  • 2409 means the count of the usernames retrieved.
  • json is the filetype and the data is stored as a list in it.

There are several use cases of this tool for various purposes.
E.g., inside your quickstart script, you can do something like this:

##as we know that all lazy Smurf care is to take some good rest, so by mistake, he can follow somebody WHOM Gargamel also follow!
#so let's find it out to save Smurfs from troubles! :D

#get following of "lazy.smurf" and "Gargamel"
lazySmurf_following = session.grab_following(username="lazy.smurf", amount="full", live_match=True, store_locally=True)
sleep(600)
gargamel_following = session.grab_following(username="Gargamel", amount="full", live_match=True, store_locally=True)

#find the users "lazy.smurf" is following WHOM "Gargamel" also follow :D
lazySmurf_gargamel_following = [following for following in lazySmurf_following if following in gargamel_following]

PROs

You can use this tool to take a backup of your or any other user's current following.

Pick Unfollowers of a user

Compares the followers stored in a local storage against current followers and returns absent followers
all_unfollowers, active_unfollowers = session.pick_unfollowers(username="Bernard_bear", compare_by="month", compare_track="first", live_match=True, store_locally=True, print_out=True)
##now, `all_unfollowers` and `all_unfollowers` variables which are lists- hold the `Unfollowers` data of "Bernard_bear" at requested time
#`all_unfollowers` holds all of the unfollowers WHILST `active_unfollowers` holds the unfollowers WHOM "Bernard_bear" is still following

Parameters:

username:
A desired username to pick its unfollowers

  • It can be your own username OR a username of some non-private account.

compare_by: Defines the compare point to pick unfollowers

  • Available values are:

    • "latest" chooses the very latest record from the existing records in the local folder
    • "earliest" chooses the very earliest record from the existing records in the local folder

    The compare points below needs a compare track defined, too:

    • "day" chooses from the existing records of today in the local folder
    • "month" chooses from the existing records of this month in the local folder
    • "year" chooses from the existing records of this year in the local folder

compare_track: Defines the track to choose a file to compare for "day", "month" and "year" compare points

  • Available values are:
    • "first" selects the first record from the given day, month or year
    • "median" selects the median (the one in the middle) record from the given day, month or year
    • "last" selects the last record from the given day, month or year

live_match:
Defines the method of grabbing new Followers data to compare with existing data

Knowledge Base:
Every time you grab Followers data in "full" range of any user, it is also gonna be stored in some corner of InstaPy for that session.

  • live_match=False:
    • If the user already do have a Followers data loaded earlier in the same session, it will run a smart data-matching algorithm.
      And there, it will load only the new data from the server and then return a compact result of current data.
      The algorithm works like: load the usernames until hits the ones from the previous query at certain amount.
    • Also if the live_match is False and the user has no any sessional Followers data, then it will load live data at requested range.
    • As a result, live_match=False saves lots of precious time and server requests.
  • live_match=True:
    • It will always load live data from the server at requested range.

store_locally:
Gives the option to save the loaded Unfollowers data in a local storage
There will be 2 files saved in their own directory:

  • all_unfollowers:
    • Will store all of the unfollowers in there
    • Its files will be saved at logs folder, ~/InstaPy/logs/YourOwnUsername/relationship_data/Bernard_bear/unfollowers/all_unfollowers/ directory.
  • active_unfollowers:
    • Will store only the unfollowers WHOM you are currently following.
    • Its files will be saved at logs folder, ~/InstaPy/logs/YourOwnUsername/relationship_data/Bernard_bear/unfollowers/active_unfollowers/ directory.

Sample filename 03-06-2018~all~75.json:

  • 03-06-2018 means the time of the data acquisition.
  • "all" means that it is all of the unfollowers data;
    *"active" unfollowers files will have "active" written in there.
  • 75 means the count of the unfollowers retrieved.
  • json is the filetype and the data is stored as a list in it.

print_out:
Use this parameter if you would like the see those unfollowers printed into the console output right after finding them.

There are several use cases of this tool for various purposes.

  • You can the get the unfollowers you have had from the start of the year, or from the middle of the year or from the start of the month, etc.
    And then, e.g. do some useful analysis with that generated unfollowers data.
  • And you can also find the unfollowers to block them all.
  • Also, you can unfollow back those active unfollowers right away:
#find all of the active unfollowers of Bernard bear
all_unfollowers, active_unfollowers = session.pick_unfollowers(username="Bernard_bear", compare_by="earliest", compare_track="first", live_match=True, store_locally=True, print_out=True)
sleep(200)
#let's unfollow them immediately cos Bernard will be angry if heards about those unfollowers! :D
session.unfollow_users(amount=len(active_unfollowers), customList=(True, active_unfollowers, "all"), style="RANDOM", unfollow_after=None, sleep_delay=600)

Pick Nonfollowers of a user

Compares the Followers data against Following data of a user and returns the Nonfollowers data
scoobyDoo_nonfollowers = session.pick_nonfollowers(username="ScoobyDoo", live_match=True, store_locally=True)
#now, `scoobyDoo_nonfollowers` variable which is a list- holds the `Nonfollowers` data of "ScoobyDoo" at requested time

Parameters:

username:
A desired username to pick its nonfollowers

  • It can be your own username OR a username of some non-private account.

live_match:
Defines the method of grabbing Followers and Following data to compare with each other to find nonfollowers

Knowledge Base:
Every time you grab Followers and/or Following data in "full" range of any user, it is also gonna be stored in some corner of InstaPy for that session.

  • live_match=False:
    • If the user already do have a Followers and/or Following data loaded earlier in the same session, it will run a smart data-matching algorithm.
      And there, it will load only the new data from the server and then return a compact result of current data.
      The algorithm works like: load the usernames until hits the ones from the previous query at certain amount.
    • Also if the live_match is False and the user has no any sessional Followers and/or Following data, then it will load live data at requested range.
    • As a result, live_match=False saves lots of precious time and server requests.
  • live_match=True:
    • It will always load live data from the server at requested range.

store_locally:
Gives the option to save the loaded Nonfollowers data in a local storage
The files will be saved into your logs folder, ~/InstaPy/logs/YourOwnUsername/relationship_data/ScoobyDoo/nonfollowers/ directory.
Sample filename 01-06-2018~[5886-3575]~2465.json:

  • 01-06-2018 means the time of the data acquisition.
  • 5886 means the count of the followers retrieved.
  • 3575 means the count of the following retrieved.
  • 2465 means the count of the nonfollowers picked.
  • json is the filetype and the data is stored as a list in it.

There are several use cases of this tool for various purposes.

  • You can get the nonfollowers of several users and then do analysis.
    • e.g., in this example Scooby Do used it like this:
    ##Scooby Doo always wonders a lot and this time he wonders if there are people Shaggy is following WHO do not follow him back...
    shaggy_nonfollowers = session.pick_nonfollowers(username="Shaggy", live_match=True, store_locally=True)
    
    #now Scooby Doo will tell his friend Shaggy about this, who knows, maybe Shaggy will unfollow them all or even add to block :D

Pick Fans of a user

Returns Fans data- all of the accounts who do follow the user WHOM user itself do not follow back
smurfette_fans = session.pick_fans(username="Smurfette", live_match=True, store_locally=True)
#now, `smurfette_fans` variable which is a list- holds the `Fans` data of "Smurfette" at requested time

Parameters:

username:
A desired username to pick its fans

  • It can be your own username OR a username of some non-private account.

live_match:
Defines the method of grabbing Followers and Following data to compare with each other to find fans

Knowledge Base:
Every time you grab Followers and/or Following data in "full" range of any user, it is also gonna be stored in some corner of InstaPy for that session.

  • live_match=False:
    • If the user already do have a Followers and/or Following data loaded earlier in the same session, it will run a smart data-matching algorithm.
      And there, it will load only the new data from the server and then return a compact result of current data.
      The algorithm works like: load the usernames until hits the ones from the previous query at certain amount.
    • Also if the live_match is False and the user has no any sessional Followers and/or Following data, then it will load live data at requested range.
    • As a result, live_match=False saves lots of precious time and server requests.
  • live_match=True:
    • It will always load live data from the server at requested range.

store_locally:
Gives the option to save the loaded Fans data in a local storage
The files will be saved into your logs folder, ~/InstaPy/logs/YourOwnUsername/relationship_data/Smurfette/fans/ directory.
Sample filename 05-06-2018~[4591-2575]~3477.json:

  • 05-06-2018 means the time of the data acquisition.
  • 4591 means the count of the followers retrieved.
  • 2575 means the count of the following retrieved.
  • 3477 means the count of the fans picked.
  • json is the filetype and the data is stored as a list in it.

There are several use cases of this tool for various purposes.

  • You can get the fans of several users and then do analysis.
    • e.g., in this example Smurfette used it like this:
    ##Smurfette is so famous in the place and she wonders which smurfs is following her WHOM she doesn't even know of :D
    smurfette_fans = session.pick_fans(username="Smurfette", live_match=True, store_locally=True)
    #and now, maybe she will follow back some of the smurfs whom she may know :P

Pick Mutual Following of a user

Returns Mutual Following data- all of the accounts who do follow the user WHOM user itself also do follow back
Winnie_mutualFollowing = session.pick_mutual_following(username="WinnieThePooh", live_match=True, store_locally=True)
#now, `Winnie_mutualFollowing` variable which is a list- holds the `Mutual Following` data of "WinnieThePooh" at requested time

Parameters:

username:
A desired username to pick its mutual following

  • It can be your own username OR a username of some non-private account.

live_match:
Defines the method of grabbing Followers and Following data to compare with each other to find mutual following

Knowledge Base:
Every time you grab Followers and/or Following data in "full" range of any user, it is also gonna be stored in some corner of InstaPy for that session.

  • live_match=False:
    • If the user already do have a Followers and/or Following data loaded earlier in the same session, it will run a smart data-matching algorithm.
      And there, it will load only the new data from the server and then return a compact result of current data.
      The algorithm works like: load the usernames until hits the ones from the previous query at certain amount.
    • Also if the live_match is False and the user has no any sessional Followers and/or Following data, then it will load live data at requested range.
    • As a result, live_match=False saves lots of precious time and server requests.
  • live_match=True:
    • It will always load live data from the server at requested range.

store_locally:
Gives the option to save the loaded Mutual Following data in a local storage
The files will be saved into your logs folder, ~/InstaPy/logs/YourOwnUsername/relationship_data/WinnieThePooh/mutual_following/ directory.
Sample filename 11-06-2018~[3872-2571]~1120.json:

  • 11-06-2018 means the time of the data acquisition.
  • 3872 means the count of the followers retrieved.
  • 2571 means the count of the following retrieved.
  • 1120 means the count of the mutual following picked.
  • json is the filetype and the data is stored as a list in it.

There are several use cases of this tool for various purposes.

  • You can get the mutual following of several users and then do analysis.
    • e.g., in this example Winnie The Pooh used it like this:
    #Winnie The Pooh is a very friendly guy and almost everybody follows him back, but he wants to be sure about it :D
    Winnie_mutual_following = session.pick_mutual_following(username="WinnieThePooh", live_match=True, store_locally=True)
    ##now, he will write a message to his mutual followers to help him get a new honey pot :>



Automate InstaPy

You can use Window's built in Task Scheduler to automate InstaPy, using a variety of trigger types: time, login, computer idles, etc. To schedule a simple daily run of an Instapy script follow the below directions

  1. Open Windows Task Scheduler
  2. Select "Create Basic Task"
  3. Fill out "Name" and "Description" as desired, click "Next"
  4. On "Trigger" screen select how frequently to run, click "Next" (Frequency can be modified later)
  5. On "Daily" screen, hit "Next"
  6. "Action Screen" select "Start a program" and then click "Next"
  7. "Program/script" enter the path, or browse to select the path to python. (How to find python path on Windows)
  8. "Add arguments" input the InstaPy script path you wish to run. (Example: C:\Users\USER_NAME\Documents\GitHub\InstaPy\craigquick.py)
  9. "Start in" input Instapy install location (Example: C:\Users\USER_NAME\Documents\GitHub\InstaPy). Click "Next"
  10. To finish the process, hit "Finish"

cron

You can add InstaPy to your crontab, so that the script will be executed regularly. This is especially useful for servers, but be sure not to break Instagrams follow and like limits.

# Edit or create a crontab
crontab -e
# Add information to execute your InstaPy regularly.
# With cd you navigate to your InstaPy folder, with the part after &&
# you execute your quickstart.py with python. Make sure that those paths match
# your environment.
45 */4 * * * cd /home/user/InstaPy && /usr/bin/python ./quickstart.py

Schedule is an in-process scheduler for periodic jobs that uses the builder pattern for configuration. Schedule lets you run Python functions periodically at pre-determined intervals using a simple, human-friendly syntax.

pip install schedule
from instapy import InstaPy
from instapy import smart_run
from instapy import set_workspace
import schedule
import time

#your login credentials
insta_username=''
insta_password=''

#path to your workspace
set_workspace(path=None)

def job():
  session = InstaPy(username=insta_username, password=insta_password)
  with smart_run(session):
    session.set_do_comment(enabled=True, percentage=20)
    session.set_comments(['Well done!'])
    session.set_do_follow(enabled=True, percentage=5, times=2)
    session.like_by_tags(['love'], amount=100, media='Photo')


schedule.every().day.at("6:35").do(job)
schedule.every().day.at("16:22").do(job)

while True:
  schedule.run_pending()
  time.sleep(10)



Additional Information

Advanced Installation

🛠 Install or update to the unreleased version

For example, there is a bug and its fix is merged to the repo but a newer version of InstaPy [containing that fix] is not yet released to PyPI to be able to be installed or updated by pip.

Then, you can do this to install the actual state of the repo 😋

pip install -I https://github.com/timgrossmann/InstaPy/zipball/master

Worths to note that, this installation option does not require Git to be installed, too.
-I flag in there is used to ignore the installed packages and reinstall them instead.

Learn why -I flag is required 🔎

Since InstaPy's version is not yet being incremented which is the reason you're installing it from a zipball, then if you don't use the -I flag, pip will complain saying,

  • "Hey, I have already installed the x.y.z version! Skipping installation..."

But obviously, even though the version is the same, zipball has the current state of the repository.
That's why you will be able to install the actual state of the repo using the -I flag.


PRO Tip:
Read the section - How to avoid python & pip confusion 😄


⚗ Install manually and manage using advanced git commands

For those who want to tweak or enhance InstaPy.

1. Clone InstaPy repository into your computer

git clone https://github.com/timgrossmann/InstaPy.git

2. Navigate to the InstaPy project root directory

cd InstaPy

3. Install the local instapy package

pip install -e .
Learn why -e flag is required 🔎

Since you're gonna install the local version of InstaPy you'll probably change its code per your need which is the reason you do an advanced installation from a Git source, then if you don't use the -e flag, you'll have to install that local package by pip every time after making a change.

But fortunately, -e flag comes to help;
-e means editable install, so that after editing files you don't need to re-install the package again since it will always refer to the edited files cos with the editable install, it just links the project's location to pip's install location rather than adding them to pip location separately..

or
python setup.py install

⛑ Install into a Virtual Environment

The best way to install InstaPy is to create a virtual environment and install InstaPy there, then, run it from a separate file.
Guide for Pythons >= 3.6 🔎
Mac/Linux

1. Clone InstaPy repository into your computer

git clone https://github.com/timgrossmann/InstaPy.git

2. Navigate to the InstaPy project root directory

cd InstaPy

3. Make a virtual environment

python3 -m venv venv

4. Activate the virtual environment

source venv/bin/activate

5. Install the local instapy package

pip install -e .
Windows

1. Clone InstaPy repository into your computer

git clone https://github.com/timgrossmann/InstaPy.git

2. Navigate to the InstaPy project root directory

cd InstaPy

3. Make a virtual environment

python3 -m venv venv

4. Activate the virtual environment

venv\Scripts\activate.bat

5. Install the local instapy package

pip install -e .

If you're not familiar with venv, please read about it here and use it to your advantage;

  • Running source venv/bin/activate will activate the correct python to run InstaPy. To exit an activated venv run deactivate.
  • Now, copy & paste the quickstart.py python code below and then run your first InstaPy script.
    Remember to run it with python from the venv.
  • To make sure which python is used, run which python which will tell you the active version of python.
  • Whenever you run the script, the virtual environment must be active.
Guide for Pythons < 3.6 🔎

1. Make a virtual environment

virtualenv venv

2. Activate the virtual environment

source venv/bin/activate

3. Install the instapy package from Git by using pip

pip install git+https://github.com/timgrossmann/InstaPy.git

If you're not familiar with virtualenv, please read about it here and use it to your advantage;

In essence,

  • This is be the only python library you should install as root (e.g., with sudo).
  • All other python libraries should be inside a virtualenv.
  • Running source venv/bin/activate will activate the correct python to run InstaPy.
    And to exit an activated virtualenv run deactivate.
  • Now, copy & paste the quickstart.py python code below and run your first InstaPy script.
    Remember to run it with python from the virtualenv, so from venv/bin/python.
  • To make sure which python is used, run which python which would tell you the active version of python.

Install a specific version

pip install instapy==0.1.1

Uninstall

pip uninstall instapy

Workspace folders

Migrating your data to the workspace folder

After installing InstaPy with pip, you have to run it once by calling python quickstart.py. Once the web browser opens, you can abort the session by closing the browser or your terminal.

You will now find an InstaPy folder located at the above mentioned home folder. Simply copy and paste the content of your logs folder into that workspace folder in order to assure that all your data is migrated.

Please note that you only have to do this once. After that, you can get rid of your old, downloaded version of this repository since the InstaPy folder in your home folder will now be the default location for your data.

InstaPy stores user's data files inside the workspace folder.

By default, it is gonna be the InstaPy folder at your home folder.
Such as, if your username is Cherry, let's show where your InstaPy folder would be,

OS home folder InstaPy workspace folder
Windows C:\\Users\\Cherry\\ C:\\Users\\Cherry\\InstaPy\\
Mac /Users/Cherry/ /Users/Cherry/InstaPy/
Linux /home/Cherry/ /home/Cherry/InstaPy/

Note that, at the start of each run, it shows you the workspace folder in use.


What will be stored at the workspace folder? 🔍

Anything that is user's data file will be stored in there.
Such as,

  • logs folder - log and other storage files
  • assets folder - e.g. user chosen chromedriver executable(s)
  • db folder - databases
  • etc.

Set a custom workspace folder

You can use set_workspace() function to set a custom workspace folder,

from instapy import InstaPy
from instapy import set_workspace

set_workspace("C:\\My\\Custom\\Path\\InstaPy\\")

session = InstaPy(...)
Rules 🔎

1-) You have to set your custom workspace folder before instantiates InstaPy.
2-) Your custom workspace folder must have InstaPy (*case sensitive) word in its name.

  • If your path does not have it,
    set_workspace("C:\\Other\\Path\\InstaPie\\")
    then your workspace folder will be named and made as,
    "C:\\Other\\Path\\InstaPie\\InstaPy\\"
    👆🏼 InstaPy directory will be added as a new subdirectory in there, and be your workspace folder.

  • If your custom workspace folder name has a case-insensitive default name in it- Instapy, instapy, instaPY, etc.,
    set_workspace("C:\\Other\\Path\\instapy2\\")
    then your workspace folder will be,
    "C:\\Other\\Path\\InstaPy2\\"
    as you can see, it normalizes name and sets the workspace folder.

Why naming is so important?
  • It will help to easily adapt to the flexible InstaPy usage with that default formal name.

Set a custom workspace folder permanently with ease

If you want to set your custom workspace folder permanently and more easily, add a new environmental variable named INSTAPY_WORKSPACE with the value of the path of the desired workspace folder to your operating system.
Then that will be the default workspace folder in all sessions [unless you change it using set_workspace() or so].

Get the location of the workspace folder in use

If you ever want to get the location of your workspace folder, you can use the get_workspace() function,

from instapy import InstaPy
from instapy import smart_run
from instapy import set_workspace
from instapy import get_workspace

set_workspace(path="C:\\Custom\\Path\\InstaPy_super\\")

session = InstaPy(username="abc", password="123")

with smart_run(session):
    # lots of code
    workspace_in_use = get_workspace()
    print(workspace_in_use["path"])
    # code code

Note that, get_workspace() is a function used internally and makes a workspace folder [by default at home folder] if not exists.
It means, you must use only the set_workspace() feature to set a custom workspace folder and not try to use get_workspace() for that purpose..

Set a custom location

You can set any of the custom locations you like, any time!
E.g. setting the location of the database file,

from instapy import InstaPy
from instapy import set_workspace
from instapy import Settings


set_workspace(...)   # if you will set a custom workspace, set it before anything
Settings.db_location = "C:\\New\\Place\\DB\\instapy.db"

session = InstaPy(...)
# code code
Restrictions 🔎

a-) You cannot set a custom workspace folder after InstaPy has been instantiated;
E.g. while instantiating InstaPy, you make a logger at that given location and trying to change the log_location really needs to restart the LOGGER adapter and make another logger instance, but it can be achieved in future.

b-) If you set a custom workspace once and then set it again then your data locations will still use the previous locations:

from instapy import InstaPy
from instapy import set_workspace
from instapy import Settings

# first time settings custom workspace folder
set_workspace("C:\\Users\\MMega\\Desktop\\My_InstaPy\\")
# second time settings custom workspace folder
set_workspace("C:\\Users\\MMega\\Documents\\My_InstaPy\\")

# locations of data files, e.g. chromedriver executable, logfolder, db will use first custom workspace locations.
# if you still want to change their location to second one, then do this one by one:
Settings.log_location = "C:\\Users\\MMega\\Documents\\My_InstaPy\\logs\\"
Settings.database_location = "C:\\Users\\MMega\\Documents\\My_InstaPy\\db\\instapy.db"
Settings.chromedriver_location = "C:\\Users\\MMega\\Documents\\My_InstaPy\\logs\\chromedriver.exe"

As you can see, you have to use set_workspace() only once.
Why it is so difficult in those 👆🏼 regards?

  • It's to preserve custom location assignments alive (Settings.*) cos otherwise setting another workspace would override any previously manually assigned location(s).

Pass arguments by CLI

It is recommended to pass your credentials from command line interface rather than storing them inside quickstart scripts.

Note that, arguments passed from the CLI has higher priorities than the arguments inside a quickstart script.
E.g., let's assume you have,

# inside quickstart script

session = InstaPy(username="abc")

and you start that quickstart script as,

python quickstart.py -u abcdef -p 12345678

Then, your username will be set as abcdef rather than abc.
And obviously, if you don't pass the flag, it'll try to get that argument from the quickstart script [if any].

Currently these flags are supported:

🚩 -u abc, --username abc

  • Sets your username.

🚩 -p 123, --password 123

  • Sets your password.

🚩 -pd 25, --page-delay 25

  • Sets the implicit wait.

🚩 -pa 192.168.1.1, --proxy-address 192.168.1.1

  • Sets the proxy address.

🚩 -pp 8080, --proxy-port 8080

  • Sets the proxy port.

🚩 -hb, --headless-browser

  • Enables headless mode.

🚩 -dil, --disable-image-load

  • Disables image load.

🚩 -bsa, --bypass-suspicious-attempt

  • Bypasses suspicious attempt.

🚩 -bwm, --bypass-with-mobile

  • Bypasses with mobile phone.

To get the list of available commands, you can type,

python quickstart.py -h
# or
python quickstart.py --help

Examples

⚽ Let's quickly set your username and password right by CLI,

python quickstart.py -u Toto.Lin8  -p 4X27_Tibor
# or
python quickstart.py --username Toto.Lin8  --password 4X27_Tibor
# or
python quickstart.py -u "Toto.Lin8"  -p "4X27_Tibor"
Advanced 🔎

You can pass and then parse the custom CLI arguments you like right inside the quickstart script.
To do it, open up your quickstart script and add these lines,

# inside quickstart script

import argparse

my_parser = argparse.ArgumentParser()
# add the arguments as you like WHICH you will pass
# e.g., here is the simplest example you can see,
my_parser.add_argument("--my-data-files-name")
args, args_unknown = my_parser.parse_known_args()

filename = args.my_data_files_name

# now you can print it
print(filename)

# or open that file
with open(filename, 'r') as f:
    my_data = f.read()

After adding your custom arguments to the quickstart script, you can now pass them by CLI, comfortably,

python quickstart.py --my-data-files-name "C:\\Users\\Anita\\Desktop\\data_file.txt"

NOTE:
Use dash in flag and parse them with underscores;
E.g., we have used the flag as --my-data-files-name and parsed it as args.my_data_files_name ...

PRO: See parse_cli_args() function [used internally] inside the util.py file to write & parse more advanced flags.
You can also import that function into your quickstart script and parse the formal flags into there to be used, as well.

# inside quickstart script

from instapy.util import parse_cli_args


cli_args = parse_cli_args()
username = cli_args.username

print(username)

👆🏼👉🏼 as you will pass the username like,

python quickstart.py -u abc

Extensions

1. Session scheduling with Telegram

Custom geckodriver

By default, InstaPy downloads the latest version of the geckodriver. Unless you need a specific version of the geckodriver, you're ready to go.

You can manually download the geckodriver binary and put the path as an argument to the InstaPy contructor:

session = InstaPy(..., geckodriver_path = '/path/to/binary', ...)

Using one of the templates

If you're interested in what other users setup looks like, feel free to check out the quickstart_templates folder which includes several working setups with different features.

In order to use them, just copy the desired file and put it next to the quickstart.py file in the, what is called root, directory.

Finally simply adjust the username and any tags or firend lists before executing it. That's it.

How not to be banned

Built-in delays prevent your account from getting banned. However, excessive use of this tool may result in action blocks or permanent bans. Use the Quota Supervisor feature to set some fixed limits for the bot for maximum safety.

Disable Image Loading

If you want to save some bandwidth, you can simply disable the image/video loading. This will lead to, if you watch InstaPy running, not downloading and displaying any more images and videos.

Note: This can save a tremendous amount of data. This is turned off by default (False).

To do this simply pass the disable_image_load=True parameter in the InstaPy constructor like so:

session = InstaPy(username=insta_username,
                  password=insta_password,
                  headless_browser=False,
		  disable_image_load=True,
                  multi_logs=True)

Changing DB or location

If you want to change the location/path of the DB, simply head into the instapy/settings.py file and change the following lines. Set these in instapy/settings.py if you're locating the library in the /usr/lib/pythonX.X/ directory.

Settings.database_location = '/path/to/instapy.db'

Split SQLite by Username

If you experience issue with multiple accounts Instapy.db lockup. You can add the following flag

-sdb when running in Command line

or

To do this simply pass the split_db=True parameter in the InstaPy constructor like so:

session = InstaPy(username=insta_username,
                  password=insta_password,
                  headless_browser=False,
		  split_db=True,
                  multi_logs=True)

How to avoid python & pip confusion

Sometimes you have multiple python installations in your system.
Then you'll obviously have crazy aliases linked to python and pip commands.

For example, let's assume you have python 2.7 & python 3.7 installed in your system,

python version python alias pip alias
2.7 py2 pip
3.7 python pip3

And once you install a package by the pip command and try to run it with python command, it will confuse you.

Why? - cos,

  • pip command is for python 2.7
  • python command is for python 3.7

To solve that confusion, use this style to install packages by pip,

# install "instapy" package into python 3.7
python -m pip install instapy

# install "instapy" package into python 2.7
py2 -m pip install instapy

As you can see, it is,
python -m pip ...
rather than,
pip ...

Other pip commands can be accomplished the same way, too.
Such as,

# update "instapy" package
python -m pip install instapy -U

# uninstall "instapy" package
python -m pip uninstall instapy

# show details of the "instapy" package installed by pip
python -m pip show instapy

Using this style, you will never have to worry about what is the correct alias of the pip for you specific python installation and all you have to know is just the python's alias you use.

Dealing with Selenium Common Exception Issues

selenium.common.exceptions.WebDriverException: Message: unknown error: Cannot read property 'entry_data' of undefined

This error could also caused by unstable Internet connection or Instagram's web changed their data-structure.

TL;DR - Make sure your chromedriver version is compatible with your Google Chrome version.

Occasionally Instapy will stop working because one of the issues below has been thrown.

_Traceback (most recent call last): ....// File list with the exception trace selenium.common.exceptions.WebDriverException: Message: unknown error: Cannot read property 'entry_data' of undefined (Session info: headless chrome=75.0.3770.80) (Driver info: chromedriver=2.36.540469 (1881fd7f8641508feb5166b7cae561d87723cfa8),platform=Mac OS X 10.14.5 x86_64)

_Traceback (most recent call last): ....// File list with the exception traceselenium.common.exceptions.WebDriverException: Message: unknown error: unknown sessionId (Session info: headless chrome=75.0.3770.80) (Driver info: chromedriver=2.36.540469 (1881fd7f8641508feb5166b7cae561d87723cfa8),platform=Mac OS X 10.14.5 x86_64)

Notice that chrome version is 75 and the chromedriver version is 2.36.

According to the release notes for chromedriver, version 2.36 only supports Chrome versions 63-65.

Which means, there is a mismatch in chromedriver and Chrome that installed on my machine.

There several steps to this fix.

  1. Completely uninstall Google Chrome.
  2. Download an older version.
  3. Prevent Google Chrome from auto-updating.

MAC FIX

Since Instapy seems to work well, in my experience on my Mac, with chromedriver version 2.36, I will downgrade my Google Chrome. I do not use Google Chrome, so this isn't an issue.

  1. Uninstall Google Chrome I used an app called App Cleaner to remove Chrome. After you install App Cleaner, simply drag Google Chrome, from the Applications folder to App Cleaner and Remove All

  2. Download Chrome 65 (Read this step completely before proceeding)

    • Find and install Chrome 65 from sllimjet.com

    • After you have installed Chrome 65, open and click the Apple Security Ok button that alerts you to the fact this was downloaded from the internet.

    • THEN, immediately close Google Chrome completely by holding CMD+Q. This is extremely important! Google Chrome will being its auto-update function. So it must be completely closed, not just the window. We need Chrome to run first and put all its files where it needs them.

  3. Prevent Google Chrome from updating

    • Open Terminal and type sudo chmod -R 000 ~/Library/Google

    • You will be asked for your computer password, enter it.

    • Next run the command sudo rm -rf /Library/Google/

    Google Chrome should not be able to auto-update now.

If for some reason Chrome is still updating, or you're unable to run the command in step 3, you can edit your /etc/hosts file to include the following line: 0.0.0.0 tools.google.com

Windows Fix

Coming soon

Raspberry Pi Fix

Coming Soon


Have Fun & Feel Free to report any issues