IRC+ IRCPlus.nlIRC resources & community

IRC Guides ยท Python

Write a small Python IRC bot

Intermediate ยท about 20 min read

This tutorial builds a tiny IRC bot in Python 3 using only the standard library (socket). No frameworks required. Ideal for learning the protocol before you move to asyncio or full bot frameworks.

Also see: Run the IRCPlus Python bots.

1. Preparation

  • Python 3.9+ recommended (python3 --version)
  • Permission to connect to an IRC server (use a test channel; do not flood)
  • Replace SERVER, PORT, NICK and CHANNEL below

Many networks expect TLS on port 6697. The minimal example uses plain TCP on 6667 for clarity; production bots should use ssl.

2. The bot code

Save as mini_bot.py:

#!/usr/bin/env python3
"""Minimal IRC bot for learning โ€” IRCPlus.nl guides."""

import socket
import re

SERVER = "irc.example.org"
PORT = 6667
NICK = "MiniBot"
CHANNEL = "#test"
IDENT = "minabot"
REALNAME = "IRCPlus mini bot"

def send(sock, line: str) -> None:
    sock.sendall((line + "\r\n").encode("utf-8", errors="replace"))

def main() -> None:
    sock = socket.create_connection((SERVER, PORT), timeout=30)
    sock.settimeout(300)

    send(sock, f"NICK {NICK}")
    send(sock, f"USER {IDENT} 0 * :{REALNAME}")

    buf = ""
    joined = False

    while True:
        data = sock.recv(4096)
        if not data:
            break
        buf += data.decode("utf-8", errors="replace")
        while "\r\n" in buf:
            line, buf = buf.split("\r\n", 1)
            if not line:
                continue
            print("<<", line)

            # PING/PONG keeps the connection alive
            if line.startswith("PING "):
                send(sock, "PONG " + line[5:])
                continue

            # Wait until registered, then JOIN
            if (not joined) and (" 001 " in line or " 376 " in line or " 422 " in line):
                send(sock, f"JOIN {CHANNEL}")
                joined = True

            # :nick!user@host PRIVMSG #chan :text
            m = re.match(
                r"^:([^!]+)![^ ]+ PRIVMSG ([^ ]+) :(.*)$",
                line,
            )
            if not m:
                continue
            nick, target, text = m.group(1), m.group(2), m.group(3)
            if text.strip().lower() == "!ping":
                reply = f"PRIVMSG {target} :Pong, {nick}!"
                send(sock, reply)
                print(">>", reply)

    sock.close()

if __name__ == "__main__":
    main()

3. Run it

python3 mini_bot.py

In the channel, type !ping โ€” the bot should answer. Stop with Ctrl+C.

Be kind to networks Use a unique nick, join only channels you are allowed to automate, and rate-limit any automatic messages. Repeated reconnect storms can get your host banned.

4. Next steps

  • Wrap the socket with ssl.create_default_context() for port 6697
  • Identify with NickServ after 001
  • Parse more commands; store state in a dict or SQLite
  • Study asyncio examples in Python downloads (chanbot.py, etc.)