Building an IRC Bot: Frameworks for Python, Node.js, Go & Rust
In this “In a Nutshell Tutorial,” I’ll show you how quickly you can write a small IRC bot in different languages using various frameworks.
Why Python?
Python is one of the most popular programming languages today and offers countless libraries for text processing. I work professionally with Python frameworks like FastAPI and enjoy integrating systems like this.
Why Node.js?
On the server side, Node.js is modern and its integration fits naturally into many JavaScript frameworks. If you code regularly, you’ll find Node.js hard to avoid.
Why Go?
Go excels at IRC bots thanks to built-in concurrency features (Goroutines) and straightforward network programming. The compiled binaries are small and fast—ideal for bots that need to run 24/7.
Why Rust?
Whatever project comes up, implementing it with Rust is always worth considering. So here’s a quick Rust implementation to show how straightforward it can be. Rust delivers memory safety without a garbage collector—perfect for long-lived bots.
The Core Principles of an IRC Bot
To build a solid foundation or find the right starting point, it helps to map out the core tasks an IRC bot needs to handle. Rather than UML diagrams or flowcharts, let’s use a simple task list.
What all IRC bots do at their core:
- Establish a TCP connection to the IRC server
- Set a nickname
- Handle authentication (NickServ / SASL) if needed
- Join channels
- Read messages (events)
- Respond to PRIVMSG
- Send replies as needed
Of course, you can extend the functionality endlessly. In this guide we’ll also look at a plugin system and async methods.
There are many tutorials that explain everything from scratch, but this “In a nutshell tutorial” assumes you have the basics down and jumps straight into installations and requirements.
Python – irc (simplest entry point)
Installation
pip install irc
Minimal Bot
import irc.bot
class MyBot(irc.bot.SingleServerIRCBot):
def __init__(self):
server = [("irc.IRC-Mania.de", 6667)]
nickname = "MyPyBot"
irc.bot.SingleServerIRCBot.__init__(self, server, nickname, nickname)
def on_welcome(self, connection, event):
connection.join("#ircmania")
def on_pubmsg(self, connection, event):
msg = event.arguments[0]
if msg == "!ping":
connection.privmsg(event.target, "pong")
if __name__ == "__main__":
MyBot().start()
What’s happening here?
on_welcome→ join channelon_pubmsg→ messages in the channel- simple string logic for commands
You should grasp the pattern here. Now you can explore frameworks—and they make things even simpler. Python offers plenty of suitable options.
Python – irc3 (modern & modular)
irc3 is a modern, plugin-based IRC framework for Python. It includes built-in command handlers, automatic reconnection logic, and a clean plugin architecture. Perfect for larger bots with lots of features.
Installation
pip install irc3
Bot
import irc3
from irc3.plugins.command import command
@irc3.plugin
class Plugin:
def __init__(self, bot):
self.bot = bot
@command
def ping(self, mask, target, args):
"""!ping command"""
self.bot.privmsg(target, "pong")
config = dict(
nick='MyIrc3Bot',
autojoins=['#ircmania'],
host='irc.IRC-Mania.de',
port=6667,
includes=['irc3.plugins.core', __name__],
)
irc3.IrcBot(**config).run()
Advantage: plugins and commands out of the box
Python – pydle (async & modern)
pydle is a modern, async-based IRC framework. The key advantage over irc3 is native async/await support, which is ideal for I/O-intensive bots. pydle is lighter and more flexible, though it has fewer built-in features than irc3.
Installation
pip install pydle
Bot
import pydle
class MyBot(pydle.Client):
async def on_connect(self):
await self.join('#ircmania')
async def on_message(self, target, source, message):
if message == "!ping":
await self.message(target, "pong")
client = MyBot("MyPydleBot")
client.run("irc.IRC-Mania.de", tls=False)
Node.js – irc-framework
Node.js is excellent for IRC bots thanks to its event-driven architecture. The non-blocking I/O model maps perfectly to IRC’s message system. irc-framework is the most popular library, offering excellent reconnection features and a plugin system.
Installation
npm install irc-framework
Bot
const IRC = require('irc-framework');
const bot = new IRC.Client();
bot.connect({
host: 'irc.IRC-Mania.de',
port: 6667,
nick: 'MyNodeBot'
});
bot.on('registered', () => {
bot.join('#ircmania');
});
bot.on('message', (event) => {
if (event.message === '!ping') {
bot.say(event.target, 'pong');
}
});
Go – go-ircevent
Installation
go get github.com/thoj/go-ircevent
Bot
package main
import (
"github.com/thoj/go-ircevent"
"fmt"
)
func main() {
bot := irc.IRC("MyGoBot", "MyGoBot")
bot.AddCallback("001", func(e irc.Event) {
bot.Join("#ircmania")
})
bot.AddCallback("PRIVMSG", func(e irc.Event) {
if e.Message() == "!ping" {
bot.Privmsg(e.Arguments[0], "pong")
}
})
err := bot.Connect("irc.IRC-Mania.de:6667")
if err != nil {
fmt.Println(err)
return
}
bot.Loop()
}
Rust – irc crate
Rust is a solid choice for IRC bots since it provides memory safety without garbage collection. This means Rust bots are reliable and stable over the long term.
Installation
cargo add irc
Bot
use irc::client::prelude::*;
fn main() {
let config = Config {
nickname: Some("MyRustBot".to_owned()),
server: Some("irc.IRC-Mania.de".to_owned()),
channels: vec!["#ircmania".to_owned()],
..Default::default()
};
let mut client = Client::from_config(config).unwrap();
client.identify().unwrap();
for message in client.stream().unwrap() {
if let Ok(message) = message {
if let Command::PRIVMSG(_, ref msg) = message.command {
if msg == "!ping" {
let _ = client.send_privmsg("#ircmania", "pong");
}
}
}
}
}
Integrating IRC Bots into Python Web Frameworks
Absolutely—you can integrate IRC bots beautifully into modern Python web frameworks. This opens exciting possibilities for web applications with chat integration.
Overview: Python Web Frameworks for IRC Bots
FastAPI
Suitability: Excellent
- Asynchronous API backend
- WebSocket support for live chat
- Automatic API documentation
- Perfect for microservices
Streamlit
Suitability: Very good
- Rapid dashboard development
- No frontend knowledge required
- Live updates with session state
- Ideal for prototypes
Django
Suitability: Good
- Full-featured web framework
- Admin interface for bot management
- ORM for message history
- Real-time features with Channels
Flask
Suitability: Good
- Lightweight and flexible
- Simple integration
- Socket.IO for real-time
- Minimalist approach
Fastify
Suitability: Very good
- High-performance API
- Async/await support
- Plugin system
- WebSocket integration
Sanic
Suitability: Good
- Asynchronous framework
- WebSocket support
- High-speed performance
- Python 3.6+ features
FastAPI Integration (perfect… fast)
from fastapi import FastAPI, WebSocket
import asyncio
import threading
from irc.bot import SingleServerIRCBot
app = FastAPI()
class IRCBot(SingleServerIRCBot):
def __init__(self):
server = [("irc.IRC-Mania.de", 6667)]
nickname = "FastAPIBot"
super().__init__(server, nickname, nickname)
self.messages = []
def on_pubmsg(self, connection, event):
msg = event.arguments[0]
self.messages.append({
"channel": event.target,
"user": event.source.split("!")[0],
"message": msg,
"timestamp": asyncio.get_event_loop().time()
})
irc_bot = IRCBot()
threading.Thread(target=irc_bot.start, daemon=True).start()
@app.get("/messages")
async def get_messages():
return {"messages": irc_bot.messages[-20:]}
@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
await websocket.accept()
while True:
await websocket.send_json({"messages": irc_bot.messages[-5:]})
await asyncio.sleep(1)
Streamlit Integration (very good)
import streamlit as st
import threading
from irc.bot import SingleServerIRCBot
class StreamlitIRCBot(SingleServerIRCBot):
def __init__(self):
super().__init__([("irc.IRC-Mania.de", 6667)], "StreamlitBot", "StreamlitBot")
if 'messages' not in st.session_state:
st.session_state.messages = []
def on_pubmsg(self, connection, event):
st.session_state.messages.append({
"channel": event.target,
"user": event.source.split("!")[0],
"message": event.arguments[0],
"time": time.strftime("%H:%M:%S")
})
if 'irc_bot' not in st.session_state:
st.session_state.irc_bot = StreamlitIRCBot()
threading.Thread(target=st.session_state.irc_bot.start, daemon=True).start()
st.title("IRC Bot Dashboard")
for msg in reversed(st.session_state.messages[-10:]):
st.chat_message(msg["user"]).write(f"**{msg['channel']}**: {msg['message']}")
Django Integration (good)
# views.py
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from irc.bot import SingleServerIRCBot
import threading
class DjangoIRCBot(SingleServerIRCBot):
def __init__(self):
super().__init__([("irc.IRC-Mania.de", 6667)], "DjangoBot", "DjangoBot")
django_bot = DjangoIRCBot()
threading.Thread(target=django_bot.start, daemon=True).start()
@csrf_exempt
def send_message(request):
if request.method == 'POST':
channel = request.POST.get('channel')
message = request.POST.get('message')
django_bot.connection.privmsg(channel, message)
return JsonResponse({'status': 'sent'})
Benefits of Framework Integration
- Web interface: Control the bot from your browser instead of the command line
- API endpoints: Other applications can communicate with your bot
- Data persistence: Store chat history in databases
- Monitoring: Live dashboards to track bot activity
- Multi-user access: Multiple users can control the bot simultaneously
- Real-time features: WebSocket integration for live updates
I hope these quick introductions spark your curiosity about IRC bots and Internet Relay Chat again. This site exists for exactly that reason. You’ll find detailed beginner tutorials here and on IRC-Mania.de.
What All Bots Have in Common
At the end of the day, every programming language follows the same recipe—just sometimes with different ingredients:
Regardless of language:
| connect | TCP connection to IRC server |
| register | Nick + User |
| join | Enter a channel |
| listen | Read events |
| react | Respond to PRIVMSG |
Typical IRC Bot Features (next level)
Once you move beyond the basics, you’ll encounter these classics:
🔹 Moderation
- Kick / Ban / mute
- Word filtering
- User management
🔹 Logging Bot
- Saves channel history
- Search functionality
- Statistics
🔹 API Bot
- !weather Berlin
- GitHub / CI status
- External integrations
🔹 Anti-Spam
- Flood detection
- Rate limiting
- Pattern matching
🔹 Reconnect Logic Important: IRC connections drop frequently!
We started with simple functions above. If you want to build something larger, it’s worth spending time on a basic architectural foundation. You don’t need formal class diagrams or use-case models, but having a clear direction will save you headaches later.
I’ll show you a production-ready IRC bot architecture, plus how to cleanly separate multi-channel handling and async/threading concerns so your bot doesn’t crash after two days or lose messages.
Production-Ready IRC Bot Architecture
The Target
A stable IRC bot needs clear separation of concerns:
┌─────────────────┐ │ IRC Client │ ← Connection to server └─────────┬───────┘ │ ┌─────────▼───────┐ │ Event Dispatcher│ ← Routes events └───────┬─┬───────┘ │ │ ┌───────▼─▼───────┐ │ Plugin System │ ← Features └─────────────────┘ │ ┌────────▼─┐ ┌────▼────────┐ │ Plugin A │ │ Plugin B │ ← Features └──────────┘ └─────────────┘
Architecture
bot/
├── core.py (IRC client)
├── dispatcher.py (event routing)
├── plugins/
│ ├── ping.py
│ ├── logger.py
│ └── admin.py
└── main.py
Core Bot (async + reconnect)
import pydle
import asyncio
class CoreBot(pydle.Client):
def __init__(self, nickname, channels):
super().__init__(nickname)
self.channels = channels
self.plugins = []
self.reconnect_delay = 5
async def on_connect(self):
for channel in self.channels:
await self.join(channel)
async def on_disconnect(self, expected):
while True:
try:
await self.reconnect()
break
except:
await asyncio.sleep(self.reconnect_delay)
async def on_message(self, target, source, message):
for plugin in self.plugins:
await plugin.handle_message(self, target, source, message)
def register_plugin(self, plugin):
self.plugins.append(plugin)
Plugin System
class PingPlugin:
async def handle_message(self, bot, target, source, message):
if message == "!ping":
await bot.message(target, "pong")
Main Runner
from core import CoreBot
from plugins.ping import PingPlugin
bot = CoreBot("MyBot", ["#dev", "#test"])
bot.register_plugin(PingPlugin())
bot.run("irc.libera.chat", tls=False)
Multi-Channel Behavior
This happens automatically:
- Bot joins #dev and #test
- Bot responds independently in each channel
Example:
#dev: !ping -> pong#test: !ping -> pongThreaded Architecture (if you’re not using async)
Alternative approach (traditional, for instance with Python irc lib):
The Problem:
The IRC loop blocks everything, which slows down your plugins.
The Solution:
Worker threads IRC Thread ───► Event Queue ───► Worker Threads
Example pattern:
from queue import Queue
import threading
event_queue = Queue()
def worker():
while True:
event = event_queue.get()
handle_event(event)
threading.Thread(target=worker, daemon=True).start()
IRC callback:
def on_message(msg):
event_queue.put(msg)
Benefits:
- The IRC connection stays responsive
- CPU-intensive tasks don’t block message handling
Production Features (essential for real bots)
1. Auto-Reconnect
async def on_disconnect(self, expected):
while True:
try:
await self.reconnect()
break
except:
await asyncio.sleep(5)
2. Rate Limiting (Flood Protection)
IRC servers will kick you if you send too many messages at once.
import time
last_send = 0
def safe_send(bot, target, msg):
global last_send
if time.time() - last_send < 1:
time.sleep(1)
bot.message(target, msg)
last_send = time.time()
3. SASL / NickServ Auth
CAP REQ :sasl
AUTHENTICATE PLAIN
Required for:
- Reserved nicknames
- IRC networks like Libera
4. Logging System
async def on_message(self, target, source, message):
print(f"[{target}] {source}: {message}")
Better approaches:
- SQLite or PostgreSQL
- Elasticsearch (for larger bots)
5. Plugin Hot Reload (advanced)
import importlib
def reload_plugin(module):
importlib.reload(module)
Allows:
- Updating your bot without disconnecting
Production Architecture (the complete picture)
IRC Server │ Async IRC Client │ ┌───────────▼───────────┐ │ Event Dispatcher │ └───────┬───────┬───────┘ │ │ Plugin System Logger │ Thread Pool (optional heavy tasks)
A production IRC bot is not a script—it’s:
An event-driven async system with plugin architecture and a resilience layer

