Building an Instagram Bot with Python and Selenium to Gain More Followers
By: Mody Ari
Tags: Selenium, Chatbots, Bots, Python, Instagram

Let’s build an Instagram bot to gain more followers! — I know, I know. That doesn’t sound very ethical, does it? But it’s all justified for educational purposes.

Coding is a super power — we can all agree. That’s why I’ll leave it up to you to not abuse this power. And I trust you’re here to learn how it works. Otherwise, you’d be on GitHub cloning one of the countless Instagram bots there, right?

You’re convinced? — Alright, now let’s go back to unethical practices.

The Plan

So here’s the deal, we want to build a bot in Python and Selenium that goes on the hashtags we specify, likes random posts, then follows the posters. It does that enough — we get follow backs. Simple as that.

Here’s a pretty twisted detail though: we want to keep track of the users we follow so the bot can unfollow them after the number of days we specify.

Top 4 Bot Tutorials

I know, this will certainly come up when you go for your next confession. But we just want to spice things up for educational purposes.

Setup

So first things first, I want to use a database to keep track of the username and the date added. You might as well save/load from/to a file, but we want this to be ready for more features in case we felt inspired in the future.

So make sure you create a database (I named mine instabot — but you can name it anything you like) and create a table called followed_users within the database with two fields (username, date_added)

Next — we’ll be installing ChromeDriver so our bot can control the browser.

Remember the installation path. You’ll need it.

You’ll also need the following python packages:

selenium

mysql-connector

Getting down to it

Alright, so first thing we’ll be doing is creating settings.json. Simply a .json file that will hold all of our settings so we don’t have to dive into the code every time we want to change something.

Settings

settings.json:

{

"db": {

"host": "localhost",

"user": "root",

"pass": "",

"database": "instabot"

},

"instagram": {

"user": "",

"pass": ""

},

"config": {

"days_to_unfollow": 1,

"likes_over": 150,

"check_followers_every": 3600,

"hashtags": []

}

}

As you can see, under “db”, we specify the database information. As I mentioned, I used “instabot”, but feel free to use whatever name you want.

You’ll also need to fill Instagram info under “instagram” so the bot can login into your account.

“config” is for our bot’s settings. Here’s what the fields mean:

days_to_unfollow: number of days before unfollowing users

likes_over: ignore posts if the number of likes is above this number

check_followers_every: number of seconds before checking if it’s time to unfollow any of the users

hashtags: a list of strings with the hashtag names the bot should be active on

Constants

Now, we want to take these settings and have them inside our code as constants.

Create Constants.py:

import json

INST_USER= INST_PASS= USER= PASS= HOST= DATABASE= POST_COMMENTS= ''

LIKES_LIMIT= DAYS_TO_UNFOLLOW= CHECK_FOLLOWERS_EVERY= 0

HASHTAGS= []



def init():

global INST_USER, INST_PASS, USER, PASS, HOST, DATABASE, LIKES_LIMIT, DAYS_TO_UNFOLLOW, CHECK_FOLLOWERS_EVERY, HASHTAGS

# read file

data = None

with open('settings.json', 'r') as myfile:

data = myfile.read()

obj = json.loads(data)

INST_USER = obj['instagram']['user']

INST_PASS = obj['instagram']['pass']

USER = obj['db']['user']

HOST = obj['db']['host']

PASS = obj['db']['pass']

DATABASE = obj['db']['database']

LIKES_LIMIT = obj['config']['likes_over']

CHECK_FOLLOWERS_EVERY = obj['config']['check_followers_every']

HASHTAGS = obj['config']['hashtags']

DAYS_TO_UNFOLLOW = obj['config']['days_to_unfollow']

the init() function we created reads the data from settings.json and feeds them into the constants we declared.

Engine

Alright, time for some architecture. Our bot will mainly operate from a python script with an init and update methods. Create BotEngine.py:



import Constants





def init(webdriver):

return





def update(webdriver):

return

We’ll be back later to put the logic here, but for now, we need an entry point.

Entry Point

Create our entry point, InstaBot.py:

from selenium import webdriver

import BotEngine



chromedriver_path = 'YOUR CHROMEDRIVER PATH'

webdriver = webdriver.Chrome(executable_path=chromedriver_path)



BotEngine.init(webdriver)

BotEngine.update(webdriver)



webdriver.close()

Of course, you’ll need to swap “YOUR CHROMEDRIVER PATH” with your actual ChromeDriver path.

Time Helper

We need to create a helper script that will help us calculate elapsed days since a certain date (so we know if we should unfollow user)

Create TimeHelper.py:

import datetime





def days_since_date(n):

diff = datetime.datetime.now().date() - n

return diff.days

Database

Create DBHandler.py. It’ll contain a class that handles connecting to the Database for us.

import mysql.connector

import Constants

class DBHandler:

def __init__(self):

DBHandler.HOST = Constants.HOST

DBHandler.USER = Constants.USER

DBHandler.DBNAME = Constants.DATABASE

DBHandler.PASSWORD = Constants.PASS

HOST = Constants.HOST

USER = Constants.USER

DBNAME = Constants.DATABASE

PASSWORD = Constants.PASS

@staticmethod

def get_mydb():

if DBHandler.DBNAME == '':

Constants.init()

db = DBHandler()

mydb = db.connect()

return mydb



def connect(self):

mydb = mysql.connector.connect(

host=DBHandler.HOST,

user=DBHandler.USER,

passwd=DBHandler.PASSWORD,

database = DBHandler.DBNAME

)

return mydb

As you can see, we’re using the constants we defined.

The class contains a static method get_mydb() that returns a database connection we can use.

Now, let’s define a DB user script that contains the DB operations we need to perform on the user.

Create DBUsers.py:

import datetime, TimeHelper

from DBHandler import *

import Constants



#delete user by username

def delete_user(username):

mydb = DBHandler.get_mydb()

cursor = mydb.cursor()

sql = "DELETE FROM followed_users WHERE username = '{0}'".format(username)

cursor.execute(sql)

mydb.commit()





#add new username

def add_user(username):

mydb = DBHandler.get_mydb()

cursor = mydb.cursor()

now = datetime.datetime.now().date()

cursor.execute("INSERT INTO followed_users(username, date_added) VALUES(%s,%s)",(username, now))

mydb.commit()





#check if any user qualifies to be unfollowed

def check_unfollow_list():

mydb = DBHandler.get_mydb()

cursor = mydb.cursor()

cursor.execute("SELECT * FROM followed_users")

results = cursor.fetchall()

users_to_unfollow = []

for r in results:

d = TimeHelper.days_since_date(r[1])

if d > Constants.DAYS_TO_UNFOLLOW:

users_to_unfollow.append(r[0])

return users_to_unfollow





#get all followed users

def get_followed_users():

users = []

mydb = DBHandler.get_mydb()

cursor = mydb.cursor()

cursor.execute("SELECT * FROM followed_users")

results = cursor.fetchall()

for r in results:

users.append(r[0])



return users

Account Agent

Alright, we’re about to start our bot. We’re creating a script called AccountAgent.py that will contain the agent behavior.

Import some modules, some of which we need for later and write a login function that will make use of our webdriver.

Notice that we have to keep calling the sleep function between actions. If we send too many requests quickly, the Instagram servers will be alarmed and will deny any requests you send.

Also note how we’re getting elements with their xpath. To do so, right click on the element, click “Inspect”, then right click on the element again inside the inspector, and choose Copy->Copy XPath.

Another important thing to be aware of is that element hierarchy change with the page’s layout when you resize or stretch the window. That’s why we’re checking for two different xpaths for the login button.

Now go back to BotEngine.py, we’re ready to login.

Add more imports that we’ll need later and fill in the init function

import AccountAgent, DBUsers

import Constants

import datetime





def init(webdriver):

Constants.init()

AccountAgent.login(webdriver)





def update(webdriver):

return

If you run our entry script now (InstaBot.py) you’ll see the bot logging in.

Perfect, now let’s add a method that will allow us to follow people to AccountAgent.py:

It’s pretty long, but generally here’s the steps of the algorithm:

For every hashtag in the hashtag constant list:

Visit the hashtag link

Open the first thumbnail

Now, execute the following code 200 times (first 200 posts in the hashtag)

Get poster’s username, check if not already following, follow, like the post, then click next

If already following just click next quickly

Now we might as well implement the unfollow method, hopefully the engine will be feeding us the usernames to unfollow in a list:

Now we can finally go back and finish the bot by implementing the rest of BotEngine.py:

Conclusion

And that’s it — now you have yourself a fully functional Instagram bot built with Python and Selenium. There are many possibilities for you to explore now, so make sure you’re using this newly gained skill to solve real life problems!

You can get the source code for the whole project from this GitHub repository.

Don’t forget to give us your 👏 !