Make a Twitter bot that tweets random images

Learn how to make a Twitter bot that posts random images with node.js.

📅 5 years ago | Updated 3 months ago

Before you start making bots, consider reading these essays and articles. Also worth browsing: resources for cleaning up your bot's language.

New Making a bot that tweets a random image with Python, Google Drive, and Pipedream.

What is a bot?

Most people might think of bots as little automated programs that send out spam email and messages online. Yes, there are certainly those kinds of bots, but a bot is really just that: a little automated program, and it can automate all kinds of activities. Anything from generating images and poetry, to telling stories and letting you play games.

The only limits to what a bot can do is your imagination! And maybe the Twitter API rate limits.

In this tutorial, I am going to show you how easy it is to create your own Twitter bot using node.js, a popular framework that lets you run JavaScript on a server, as opposed to a browser, and Twit, a node.js library for interacting with Twitter’s public API.

A few words on APIs

API, which stands for Application Programming Interface, is, to put it simply, a way for you to interact with the data of a website by accessing it directly on their server.

So for example, with Twitter’s API you will be able to read Tweets as they are posted on the site, or post your own Tweets, respond to people, follow users, and pretty much everything else that a regular Twitter user could do using Twitter’s website or mobile app.

This is the key part: Twitter’s API is what lets you automate user behavior, in order to create a Twitter bot. And like I said in the beginning, this activity could be non-malicous and even entertaining.

So let’s make something fun then!

Node.js

First, let’s install node.js. The instructions will vary a bit depending on your operating system, so just follow the official download and installation guide.

Once you have node.js installed, you can open your command line (check out this brief tutorial if you need to get up to speed with using it) and type:

node --version

When you type this and hit Enter, you should see something like 6.0.0 (the number might be a bit different, but the point is that you should see a number to check that node.js was installed correctly).

Great, now let’s bootstrap our node.js application.

At its core, node.js is just JavaScript that can be executed on a web server. Let’s try this: create a file called server.js. Inside this file, type:

console.log('I am making a Twitter bot!');

Save the file, go back to your console, and run your script:

node '/home/stefan/twitter-bots/server.js' 

Your console will display I am making a Twitter bot!. Very well, you just wrote your first node.js application! Let’s move on to the actual bot now.

Node.js comes with a little program called npm, or Node Package Manager. npm lets you, among other things, keep node.js up to date, and install various libraries.

The one we are going to need today is called Twit. But before we install it, let’s do one thing real quick.

Go back to your command line and type npm init. You will be prompted to fill out some basic information about your node.js app.

You can pretty much just keep pressing Enter to accept the default values. Once that’s done, let’s go back to npm and Twit.

Still in the command line, type npm install twit --save. This will download the Twit library and place the necessary files into the node_modules folder.

There is no real need to interact with the actual files, instead open your server.js file, delete the console.log command, and replace it with the following:

const fs = require('fs'),
      path = require('path'),
      Twit = require('twit'),
      config = require(path.join(__dirname, 'config.js'));

Here we are loading a few modules (or libraries). You already know Twit, and fs and path are modules that come with node.js by default and let your work with files.

As for config, we are going to need to make another detour.

Creating a Twitter app

Before you can start writing any code, you will need something called API keys. These will let you make API calls, or in other words, interact with the data on Twitter’s website.

To get your API keys, you need to first create a Twitter app. Here’s a quick guide on how to do that.

After that, you will have the following information:

  • Consumer Key
  • Consumer Secret
  • Access Token
  • Access Token Secret

Now we need to create a new file called config.js, it will look like this:

const config = {
  consumer_key: 'XXXXX',
  consumer_secret: 'XXXXX',
  access_token: 'XXXXX',
  access_token_secret: 'XXXXX'
}

module.exports = config;

Replace XXXXX with matching values, for example, consumer_key should be your app’s Consumer Key, and so on.

Now you can go back to your server.js file and add the following code:

const T = new Twit(config);

T.post('statuses/update', {status: 'Look, I am tweeting!'}, function(err, data, response) {
  console.log(data)
});

So your full server.js file should look like this:

const Twit = require('twit'),
      fs = require('fs'),
      path = require('path'),
      config = require(path.join(__dirname, 'config.js'));

const T = new Twit(config);

T.post('statuses/update', {status: 'Look, I am tweeting!'}, (err, data, response) => {
  console.log(data);
});

And now, back to the console:

node server.js

Your console will fill up with a bit of information about the successful posting of your tweet, and if you switch to your browser and look at your bot’s profile page —

Your bot's first tweet

Congratulations, your bot is now tweeting!

There are two more steps left now. Making your bot do something interesting, and hosting your bot somewhere so that you can turn off your computer without having to shut down the script powering your bot.

Posting images

For this tutorial, I am going to use images from the History’s Most Powerful Protest Art article published on magenta.as. Feel free to download and use any images you like. Create a folder called images and add your images here.

Next, remove the code that posted your first tweet:

T.post('statuses/update', {status: 'Look, I am tweeting!'}, (err, data, response) => {
  console.log(data);
});

We are going to write these two functions:

Here is the first function:

const randomFromArray = (images) => {
  return images[Math.floor(Math.random() * images.length)];
}

We’re using a little trick here. On its own, Math.random() returns a random number between 0 and 1 (excluding the number 1). What we need is to pick a random number between 0 and the last index of our array, so that we can access a random element of the array.

In my case, images.length will be 5. So Math.random() * images.length will always give me a number between 0 and 5, but excluding the number 5, which is okay, because the index of an array in JavaScript starts at 0, and the last index is always its length minus 1.

To avoid picking a number like 3.202108, we are using the Math.floor() function, which rounds the number down to the nearest whole number.

With the randomFromArray() function in place, we can now start uploading the images. First, we need to keep track of them and what description goes with each. For this, let’s create a file images.js with the following structure:

const images = [
    {
        file: "all-power-to-the-people.jpg",
        text: "Source: https://source.com/image1",
        altText: "An illustration of a raised fist with the text 'All power to the people' surrounding it."
    },
    {
        file: "i-am-a-man.jpeg",
        text: "Source: https://source.com/image2",
        altText: "A crowd of the 1968 Memphis sanitation strike protesters carrying 'I Am a Man! signs."
    },
    {
        file: "la-lutte-continue.jpg",
        text: "Source: https://source.com/image3",
        altText: "A French protest art poster showing a factory chimney morphing into a raised fist."
    },
    {
        file: "love-trumps-hate.jpeg",
        text: "Source: https://source.com/image4",
        altText: "A collage of various pins with political messages, including 'Love trumps hate' and 'America is for everyone'."
    }
];

module.exports = images;

Once we have the images, we can pick one at random using the randomFromArray helper function.

const uploadRandomImage = (images) => {
    console.log('opening an image...');
    const randomImage = randomFromArray(images);
    const imagePath = path.join(__dirname, '/images/' + randomImage.file);
    const imageData = fs.readFileSync(imagePath, {encoding: 'base64'});
}

There are some more technical parts to this, but in essence, we pick a random image from our images.js object (using the randomFromArray function that we created), and then we load the file into a variable imageData.

The base64 encoding refers to Twitter requiring the uploaded media files to be “base64-encoded” (see this StackOverflow thread for a more technical explanation of what this means).

Once we load our image, we can use Twitter’s media/upload API endpoint (documented here). After the image is successfully uploaded to Twitter’s server, we can use the media/metadata/create endpoint (here’s the documentation for it, and here’s a quick overview from my blog) to add image description. And finally, we will use the statuses/update method we used previously to post our first tweet and use it to post the image. Here it is all together.

const uploadRandomImage = (images) => {
    console.log('opening an image...');
    const randomImage = randomFromArray(images);
    const imagePath = path.join(__dirname, '/images/' + randomImage.file);
    const imageData = fs.readFileSync(imagePath, {encoding: 'base64'});
       
    T.post('media/upload', {media_data: imageData}, (err, data, response) => {
        console.log('uploading an image...');

        if (err){
            console.log('error:', err);
        } else {
            console.log('adding description...');
            const image = data;

            T.post('media/metadata/create', {
                media_id: data.media_id_string,
                alt_text: {
                    text: randomImage.altText
                }            
            }, (err, data, response) => {
                console.log('tweeting...');
                T.post('statuses/update', {
                    status: randomImage.text,
                    media_ids: new Array(image.media_id_string)
                }, (err, data, response) => {
                    if (err){
                        console.log('error:', err);
                    }
				});
            });
        }
    });
}

And finally, to kick things off, let’s add this after our RandomImage function:

uploadRandomImage();

When you run node server.js now, you will see your Twitter bot post a random picture every 10 seconds (or 10,000 milliseconds).

Great job so far!

Your console will show what the bot is up to:

uploading an image...
adding description...
tweeting...

And once again, looking at our bot’s Twitter page, we see it was indeed posting.

Running into problems? See the full code on GitHub.

You can press CTRL+C while using the command line to end the script.

Also, if you want to delete the image after posting it, you can use fs.unlink for that, so add this to the uploadRandomImage function, after you successfully post an image to Twitter:

fs.unlink(imagePath, (err) => {
  if (err){
    console.log('error: unable to delete image ' + imagePath);
  }
  else{
    console.log('image ' + imagePath + ' was deleted');
  }
});

This way you can choose whether you want to cycle through all the images or only use each image once. You could also keep a list of images you already posted to avoid posting the same one twice in a row, or too many times. Or you could move the images to a different folder after posting them, and once your original folder is empty, move them back.

Hosting your bot

Great, so now you have your very own image-tweeting bot. The final step is moving the code to a server that will host the bot for you.

For a good overview of all your bot-hosting options, check out this list of available hosting solutions, but keep in mind that almost all of them are paid, starting at $5-7 a month. And the free options are usually quite limited (for example, Heroku only allows your app to run for a few hours every day if you’re on the free plan).

I made a Glitch version as well. Note that the code is a bit different, but essentially follows the same ideas.

I hope you enjoyed making your Twitter bot! Feel free to browse the Twit documentation and Twitter API documentation to learn more about what your bot can do, and maybe get some more ideas browsing open source Twitter bots here on Botwiki!

And you are always welcome to join the Botmakers community 🙂

Stefan

Creator of Botwiki and Botmakers, Botwiki editor, and Botmakers community manager.

Enjoyed the tutorial?

Consider supporting Botwiki!

Latest from the blog

Twitter shutting down free access to their API on February 9
Twitter shutting down free access to their API on February 9

I keep saying it's an end of an era quite often these days.

How do folks get into creative botmaking?
How do folks get into creative botmaking?

Sharing the stories of our early botmaking days.

What kind of bots are posting in the fediverse?
What kind of bots are posting in the fediverse?

Exploring the bots people make and follow in the fediverse.

Visit the blog

.