Getting Started with Chatbots & IRC


Let’s create a basic chatbot that connects to Twitch chat and responds to two commands, !echo and !haiku. In this example, we’ll use:

Step 1: Setup

You’ll need an OAuth token for the account you want to use as the chatbot. This is how we verify the identity of your chatbot with our servers. To get the token, do one of the following:

When you get your token, you must specify scopes (the permissions you are allowed on behalf of the authorized Twitch user). In this example, you need a token with the chat:read and chat:edit scopes.

Also, before running the bot, make sure you’ve installed the tmi.js and haikudos modules with this command:

npm i tmi.js haikudos

Step 2: Sample Code

To use the sample code, replace three strings in the opts object — <BOT USERNAME>, <OAUTH TOKEN>, and <CHANNEL NAME> — with your information.

const tmi = require('tmi.js')
const haikudos = require('haikudos')

// Valid commands start with:
let commandPrefix = '!'
// Define configuration options:
let opts = {
  identity: {
    username: <BOT USERNAME>,
    password: 'oauth:' + <OAUTH TOKEN>
  channels: [

// These are the commands the bot knows (defined below):
let knownCommands = { echo, haiku }

// Function called when the "echo" command is issued:
function echo (target, context, params) {
  // If there's something to echo:
  if (params.length) {
    // Join the params into a string:
    var msg = params.join(' ')
    // Interrupt attempted slash and dot commands:
    if (msg.charAt(0) == '/' || msg.charAt(0) == '.') {
      msg = 'Nice try...'
    // Send it back to the correct place:
    sendMessage(target, context, msg)
  } else { // Nothing to echo
    console.log(`* Nothing to echo`)

// Function called when the "haiku" command is issued:
function haiku (target, context) {
  // Generate a new haiku:
  haikudos((newHaiku) => {
    // Split it line-by-line:
    newHaiku.split('\n').forEach((h) => {
    // Send each line separately:
    sendMessage(target, context, h)

// Helper function to send the correct type of message:
function sendMessage (target, context, message) {
  if (context['message-type'] === 'whisper') {
    client.whisper(target, message)
  } else {
    client.say(target, message)

// Create a client with our options:
let client = new tmi.client(opts)

// Register our event handlers (defined below):
client.on('message', onMessageHandler)
client.on('connected', onConnectedHandler)
client.on('disconnected', onDisconnectedHandler)

// Connect to Twitch:

// Called every time a message comes in:
function onMessageHandler (target, context, msg, self) {
  if (self) { return } // Ignore messages from the bot

  // This isn't a command since it has no prefix:
  if (msg.substr(0, 1) !== commandPrefix) {
    console.log(`[${target} (${context['message-type']})] ${context.username}: ${msg}`)

  // Split the message into individual words:
  const parse = msg.slice(1).split(' ')
  // The command name is the first (0th) one:
  const commandName = parse[0]
  // The rest (if any) are the parameters:
  const params = parse.splice(1)

  // If the command is known, let's execute it:
  if (commandName in knownCommands) {
    // Retrieve the function by its name:
    const command = knownCommands[commandName]
    // Then call the command with parameters:
    command(target, context, params)
    console.log(`* Executed ${commandName} command for ${context.username}`)
  } else {
    console.log(`* Unknown command ${commandName} from ${context.username}`)

// Called every time the bot connects to Twitch chat:
function onConnectedHandler (addr, port) {
  console.log(`* Connected to ${addr}:${port}`)

// Called every time the bot disconnects from Twitch:
function onDisconnectedHandler (reason) {
  console.log(`Disconnected: ${reason}`)

Step 3: Results

Now you have a working chatbot that can respond to two basic commands. The rest is up to you!

Next Steps

For complete information, see the Chatbots & IRC Guide and the rest of the Twitch IRC documentation.

Code samples are available here.