Programming IRC Bots: Frameworks for Python, Node.js, Go & Rust
In this “In a Nutshell Tutorial” I want to show you how quickly you can write a small IRC bot in different languages with different frameworks.
Why Python?
Because Python is currently one of the most popular programming languages and offers countless libraries for text processing. I also work professionally with Python frameworks like FastAPI, etc., and I like to integrate such systems.
Why Node.js?
On the server side with Node.js, very modern and the integration could be incorporated into numerous JS frameworks. If you program a lot, you can hardly avoid Node.js.
Why Go?
Go is perfect for IRC bots because of its built-in concurrency features (Goroutines) and simple network programming. The compiled binaries are small and fast - ideal for bots that should run 24/7.
Why Rust?
Regardless of which project is coming up, an implementation with Rust is always considered. Therefore, here too a quick implementation with Rust to demonstrate the simplicity. Rust offers memory safety without a garbage collector - perfect for long-lived bots.
Basic Principle of an IRC Bot
To build a proper scaffold, or to find the beginning and middle, you need to briefly note or internalize the core tasks of an IRC bot. Instead of using UML diagrams or flow charts, we work with a simple task list.
All IRC bots do essentially this:
TCP connection to IRC server Set nick Optional auth (NickServ / SASL) Join channel Read messages (events) React to PRIVMSG Optionally respond
Of course, we can expand the tasks or functions infinitely in extension. But here we’ll also look at a plugin system and async methods.
We have many tutorials that explain everything from scratch, in this “in a nutshell tutorial” we assume absolute basic knowledge and start immediately with installations and necessary “requirements”.
Python – irc (easiest entry)
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 happens here?
on_welcome→ join channelon_pubmsg→ messages in the channel- simple string logic for commands
You should already understand the principle here. Now you can look into frameworks. Of course, it’s even simpler with frameworks. Python offers numerous suitable frameworks.
Python – irc3 (modern & modular)
irc3 is a modern, plugin-based IRC framework for Python. It offers built-in command handlers, automatic reconnection logic, and clean plugin architecture. Perfect for larger bots with many 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 + Commands out of the box
Python – pydle (async & modern)
pydle is a modern, async-based IRC framework. The main advantage over irc3 is native async/await support, which is ideal for I/O-intensive bots. pydle is lighter and more flexible, but 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 perfect for IRC bots because of its event-driven architecture. The non-blocking I/O model fits perfectly with IRC’s messaging system. irc-framework is the most popular library with excellent reconnection features and 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 good choice for IRC bots because it offers memory safety without a garbage collector. This means Rust bots are long-lived and stable.
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 in Python Web Frameworks
Yes, you can integrate IRC bots excellently into modern Python web frameworks! This opens up entirely new 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
- Fast dashboard development
- No frontend knowledge needed
- Live updates with session state
- Ideal for prototypes
Django
Suitability: Good
- Complete web framework
- Admin interface for bot management
- ORM for chat history
- Real-time features with channels
Flask
Suitability: Good
- Lightweight & 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'})
Advantages of Framework Integration
- Web Interface: Control via browser instead of command line
- API Endpoints: Other applications can communicate with the bot
- Data Persistence: Storage of chat histories in databases
- Monitoring: Live dashboards for bot activities
- Multi-User: Multiple users can control the bot
- Real-Time Features: WebSocket integration for live updates
I hope these brief introductions inspire you to explore IRC bots and Internet Relay Chat again. That’s what this page is for. You’ll find extensive beginner tutorials on this site as well as on IRC-Mania.de.
What All Bots Have in Common
In the end, all programming languages cook with the same recipe, but not always with the same water:
Regardless of language:
| connect | TCP to IRC server |
| register | Nick + User |
| join | Enter channel |
| listen | Read events |
| react | React to PRIVMSG |
Typical IRC Bot Features (next level)
As you progress, these classics come into play:
🔹 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 often drops connections!
Above we started programming with simple functions. If you want to program something larger, it’s worth building a small functional skeleton. It doesn’t need to be class diagrams or use-case diagrams, but a rough direction would be good.
I’ll show you a production-ready IRC bot architecture, plus how to cleanly separate multi-channel + async/threads so your bot doesn’t crash after 2 days or lose messages.
Production-ready IRC Bot Architecture
Target Design
A stable IRC bot needs separation of concerns:
┌─────────────────┐ │ IRC Client │ ← Connection to server └─────────┬───────┘ │ ┌─────────▼───────┐ │ Event Dispatcher│ ← Events routing └───────┬─┬───────┘ │ │ ┌───────▼─▼───────┐ │ 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 + #test
- Bot responds independently of the channel
Example:
#dev: !ping -> pong#test: !ping -> pongThreaded Architecture (if you do NOT use async)
Alternative (classic, e.g. Python irc lib):
Problem:
IRC loop blocks → plugins slow everything down
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)
Advantage:
- IRC stays fast
- CPU-heavy tasks do NOT block
Production Features (important in 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 otherwise.
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
needed for:
- reserved nicks
- IRC networks like Libera
4. Logging System
async def on_message(self, target, source, message):
print(f"[{target}] {source}: {message}")
better:
- SQLite / PostgreSQL
- Elasticsearch (for large bots)
5. Plugin Hot Reload (advanced)
import importlib
def reload_plugin(module):
importlib.reload(module)
allows:
- Update bot without disconnect
Production Architecture (final picture)
IRC Server │ Async IRC Client │ ┌───────────▼───────────┐ │ Event Dispatcher │ └───────┬───────┬───────┘ │ │ Plugin System Logger │ Thread Pool (optional heavy tasks)
A real IRC bot is not a script, but:
Event-driven async system + Plugin architecture + Resilience layer