Beginner

Twitter Bots can be super useful to help automate some of the interactions on social media in order to build and grow engagement but also automate some tasks. There has been many changes on the twitter developer account and sometimes it’s uncertain how to even create a tweet bot. This article will walk through step bey step on how to create a twitter bot with the latest Twitter API v2 and also provide some code you can copy and paste in your next project. We also end with how to create a more useful bot that can post some articles about python automatically.

In a nutshell, how a twitter bot works is that you will need to run your code for a twitter bot in your own compute that can be triggered from a Twitter webhook (not covered) which is called by twitter based on a given event, or by having your program run periodically to read and send tweets (covered in this article). Either way, there are some commonalities and in this article we will walk through how to read tweets, and then to send tweets which are from google news related to python!

Step 1: Sign up for Developer program

If you haven’t already you will need to either sign in or sign up for a twitter account through twitter.com. Make sure your twitter account has an email address allocated to it (if you’re not aware, you can create a twitter account with just your mobile phone number)

Next go to developer.twitter.com and sign up for the developer program (yes, you need to sign up for a second time). This enables you to create applications.

First you’ll need to answer some questions on purpose of the developer account. You can chose “Make a Bot”

Next you will need to agree to the terms and conditions, and then a verification email will be sent to your email address from your twitter account.

When you click on the email to verify your account, you can then enter your app name. This is an internal name and something that will make it easy for you to reference.

Once you click on keys, you will then be given a set of security token keys like below. Please copy them in a safe place as your python code will need to use them to access your specific bot. If you do lose your keys, or someone gets access to them for some reason, you can generate new keys from your developer.twitter.com console.

There are two keys which you will need to use:

  1. API Key (think of this like a username)
  2. API Key Secret (think of this like a password)
  3. Bearer Token (used for read queries such as getting latest tweets)

There is also a third key, a Bearer Token, but this you can ignore. It is for certain types of requests

At the bottom of the screen you’ll see a “Skip to Dashboard”, when you click on that you’ll then see the overview of your API metrics.

Within this screen you can see the limits of the number of calls per month for example and how much you have already consumed.

Next, click on the project and we have to generate the access tokens. Currently with the previous keys you can only read tweets, you cannot create ones as yet.

After clicking on the project, chose the “keys and tokens” tab and at the bottom you can generate the “Access Tokens”. In this screen you can also re-generate the API Keys and Bearer Token you just created before in case your keys were compromised or you forgot them.

Just like before, generate the keys and copy them.

By now, you have 5 security toknes:

  1. API Key – also known as the Consumer Key (think of this like a username)
  2. API Key Secret – also known as the Consumer Secret (think of this like a password)
  3. Bearer Token (used for read queries such as getting latest tweets)
  4. Access Token (‘username’ to allow you to create tweets)
  5. Access Token Secret (‘password’ to allow you to create tweets)

Step 2: Test your twitter API query

Now that you have the API keys, you can do some tests. If you are using a linux based machine you can use the curl command to do a query. Otherwise, you can use a site such as https://reqbin.com/curl to do an online curl request.

Here’s a simple example to get the most recent tweets. It uses the API https://api.twitter.com/2/tweets/search/recent which must include the query keyword which includes a range of parameter options (find out the list in the twitter query documentation).

curl --request GET 'https://api.twitter.com/2/tweets/search/recent?query=from:pythonhowtocode' --header 'Authorization: Bearer <your bearer token from step 1>'

The output is as follows:

{
    "data": [{
        "id": "1523251860110405633",
        "text": "See our latest article on THE complete beginner guide on creating a #discord #bot in #python \n\nEasily add this to your #100DaysOfCode  #100daysofcodechallenge #100daysofpython \n\nhttps://t.co/4WKvDVh1g9"
    }],
    "meta": {
        "newest_id": "1523251860110405633",
        "oldest_id": "1523251860110405633",
        "result_count": 1
    }
}

Here’s a much more complex example. This includes the following parameters:

  • %23 – which is the escape characters for # and searches for hashtags. Below example is hashtag #python (case insensitive)
  • %20 – this is an escape character for a space and separates different filters with an AND operation
  • -is:retweet – this excludes retweets. The ‘-‘ sign preceding the is negates the actual filter
  • -is:reply – this excludes replies. The ‘-‘ sign preceding the is negates the actual filter
  • max_results=20 – an integer that defines the maximum number of return results and in this case 20 results
  • expansions=author_id – this makes sure to include the username internal twitter id and also the actual username under an includes section at the bottom of the returned JSON
  • tweet.fields=public_metrics,created_at – returns the interaction metrics such as number of likes, number of retweets, etc as well as the time (in GMT timezone) when the tweet was created
  • user.fields=created_at,location – this returns when the user account was created and the user self-reported location in their profile.
curl --request GET 'https://api.twitter.com/2/tweets/search/recent?query=%23python%20-is:retweet%20-is:reply&max_results=20&expansions=author_id&tweet.fields=public_metrics,created_at&user.fields=created_at,location' --header 'Authorization: Bearer <Your Bearer Token from Step 1>'

Result of this looks like the following – notice that the username details is in the includes section below where you can link the tweet with the username with the author_id field.

{{
    "data": [{
        "id": "1523688996676812800",
        "text": "NEED a #JOB?\nSign up now https://t.co/o7lVlsl75X\nFREE. NO MIDDLEMEN\n#Jobs #AI #DataAnalytics #MachineLearning #Python #JavaScript #WomenWhoCode #Programming #Coding #100DaysofCode #DEVCommunity #gamedev #gamedevelopment #indiedev #IndieGameDev #Mobile #gamers #RHOP #BTC #ETH #SOL https://t.co/kMYD2417jR",
        "author_id": "1332714745871421443",
        "public_metrics": {
            "retweet_count": 3,
            "reply_count": 0,
            "like_count": 0,
            "quote_count": 0
        },
        "created_at": "2022-05-09T15:39:00.000Z"
    },
....
  }],
    "includes": {
        "users": [{
            "name": "Job Preference",
            "id": "1332714745871421443",
            "username": "JobPreference",
            "created_at": "2020-11-28T15:56:01.000Z"
        }, 
....
}

Step 3: Reading tweets with python code

Building on top of the tests conducted on Step 2, it is a simple extra step in order to convert this to python code using the requests module which we’ll show first and after show a simpler way with the library tweepy. You can simply use the library to convert the curl command into a bit of python code. Here’s a structured version of this code where the logic is encapsulated in a class.

import requests, json
from  urllib.parse import quote
from pprint import pprint

class TwitterBot():
    URL_SEARCH_RECENT = 'https://api.twitter.com/2/tweets/search/recent'
    def __init__(self, bearer_key):
        self.bearer_key = bearer_key

    def search_recent(self, query, include_retweets=False, include_replies=False):
        url = self.URL_SEARCH_RECENT + "?query=" + quote(query)
        if not include_retweets: url += quote(' ')+'-is:retweet'
        if not include_replies: url += quote(' ')+'-is:reply'

        url += '&max_results=20&expansions=author_id&tweet.fields=public_metrics,created_at&user.fields=created_at,location' 
        
        headers = {'Authorization': 'Bearer ' + self.bearer_key }

        r = requests.get(url, headers = headers)
        r.encoding = r.apparent_encoding.  #Ensure to use UTF-8 if unicode characters
        return json.loads(r.text)

#create an instance and pass in your Bearer Token
t = TwitterBot('<Insert your Bearer Token from Step 1>')
pprint( t.search_recent( '#python') )

The above code is fairly straightforward and does the following:

  • TwitterBot class – this class encapsulates the logic to send the API requests
  • TwitterBot.search_recent – this method takes in the query string, then escapes any special characters, then calls the requests.get() to call the https://api.twitter.com/2/tweets/search/recent API call
  • pprint() – this simply prints the output in a more readable format

This is the output:

However, there is a simpler way which is to use tweepy.

pip install tweepy

Next you can use the tweepy module to search recent tweets:

import tweepy

client = tweepy.Client(bearer_token='<insert your token here from previous step>')

query = '#python -is:retweet -is:reply' #exclude retweets and replies with '-'
tweets = client.search_recent_tweets(   query=query, 
                                        tweet_fields=['public_metrics', 'context_annotations', 'created_at'], 
                                        user_fields=['username','created_at','location'],
                                        expansions=['entities.mentions.username','author_id'],
                                        max_results=10)
#The details of the users is in the 'includes' list
user_data = {}
for raw_user in tweets.includes['users']:
    user_data[ raw_user.id ] = raw_user

for index, tweet in enumerate(tweets.data):
    print(f"[{index}]::@{user_data[tweet.author_id]['username']}::{tweet.created_at}::{tweet.text.strip()}\n")
    print("------------------------------------------------------------------------------")

Output as follows:

Please note, that after calling the API a few times your number of tweets consumed will have increased and may have hit the limit. You can always visit the dashboard at https://developer.twitter.com/en/portal/dashboard to see how many requests have been consumed. Notice, that this does not count the number of actual API calls but the actual number of tweets. So it can get consumed pretty quickly.

Step 4: Sending out a tweet

So far we’ve only been reading tweets. In order to send a tweet you can use the create_tweet() function of tweepy.

client = tweepy.Client( consumer_key= "<API key from above - see step 1>",
                        consumer_secret= "<API Key secret - see step 1>",
                        access_token= "<Access Token - see step 1>",
                        access_token_secret= "<Access Token Secret - see step 1>")


# Replace the text with whatever you want to Tweet about
response = client.create_tweet(text='A little girl walks into a pet shop and asks for a bunny. The worker says” the fluffy white one or the fluffy brown one”? The girl then says, I don’t think my python really cares.')

print(response)

Output from Console:

Output from Twitter:

How to Send Automated Tweets About the Latest News

To make this a bit more of a useful bot rather than simply tweet out static text, we’ll make it tweet about the latest things happened in the news about python.

In order to search for news information, you can use the python library pygooglenews

pip install pygooglenews

The library searches Google news RSS feed and was developed by Artem Bugara. You can see the full article of he developed the Google News library. You can put in a keyword and also time horizon to make it work. Here’s an example to find the latest python articles in last 24 hours.

from pygooglenews import GoogleNews
gn = GoogleNews()
search = gn.search('python programming', when = '12h')

for article in search['entries']:
    print(article.title)
    print(article.published)
    print(article.source.title)
    print('-'*80)  #string multiplier - show '-' 80 times

Here’s the output:

So, the idea would be to show a random article on the twitter bot which is related to python programming. The gn.search() functions returns a list of all the articles under the entries dictionary item which has a list of those articles. We will simply pick a random one and construct the tweet with the article title and the link to the article.

import tweepy
from pygooglenews import GoogleNews
from random import randint

client = tweepy.Client( consumer_key= "<your consumer/API key - see step 1>",
                        consumer_secret= "<your consumer/API secret - see step 1>",
                        access_token= "<your access token key - see step 1>",
                        access_token_secret= "<your access token secret - see step 1>")

gn = GoogleNews()
search = gn.search('python programming', when = '24h')

#Find random article in last 24 hours using randint between index 0 and the last index
article = search['entries'][ randint( 0, len( search['entries'])-1 ) ]

#construct the tweet text
tweet_text =  f"In python news: {article.title}.  See full article: {article.link}.  #python #pythonprogramming" 

#Fire off the tweet!
response = client.create_tweet( tweet_text )
print(response)

Output from the console on the return result:

And, most importantly, here’s the tweet from our @pythonhowtocode! Twitter automatically pulled the article image

This has currently been scheduled as a daily background job!

Error SendFox Connection: 403 Forbidden

403 Forbidden