Content Index
- What is Flask-SocketIO and what is it for?
- Introduction to Flask-SocketIO and Full-Duplex Communication
- How Flask-SocketIO works
- Events, emit, and listen
- What is Full-Duplex communication?
- Flask-SocketIO on the Server
- Listening and sending messages
- The Client: JavaScript and Socket.IO
- Server Implementation (Flask)
- Differences between HTTP and WebSocket
- Installation and initial configuration
- ⚙️ Socket server configuration
- How Flask-SocketIO works
- Events, emit, and listen
- Create our Room
- Connect and disconnect
- Join and leave rooms
- Create a real-time chat with Flask-SocketIO
- ️ Server: handle events and messages
- Client: emit and receive messages
- Server
- Complete step-by-step example
- Authentication with Flask-Login
- Control who sees which messages
- ⚙️ Good practices and deployment in production
- Eventlet and Gunicorn
- Security and session handling
- Scalability and monitoring
- Conclusion
- ❓ Frequently Asked Questions (FAQs)
Flask-SocketIO is a Flask extension that allows for the integration of WebSockets into a Flask application, enabling real-time, bidirectional communication between the server and the client without the need to constantly refresh the page; for example, in a chat-type app, you send the message to the server, to another person, or a group of people; but you can also receive messages, therefore, in the classic client-server scheme, it is not possible to obtain the message in the same way you send them.
Therefore, you would have to be reloading or sending requests to the server after certain changes to check if you have any potential messages, but, in full-duplex communication, a channel exists between the server and the client (the reverse) and there is no need to send requests to the server every so often (which is an inefficient approach).
If you ever wanted to send and receive messages without having to reload the page, Flask-SocketIO is your ideal tool. This Flask extension allows you to add real-time (full-duplex) communication to your Python projects with surprising ease.
When I developed a chat system with Flask, I realized that traditional HTTP was not enough: I needed an active channel between the server and the client that would allow me to send data immediately. That's where Flask-SocketIO came in.
We left off knowing How to implement role-based access control in Flask
What is Flask-SocketIO and what is it for?
As we mentioned before, Flask-SocketIO is an extension that integrates WebSockets within a Flask project, allowing for permanent bidirectional communication between the server and browsers.
Flask-SocketIO uses a WebSocket implementation from the JavaScript Socket.IO library, which is compatible with multiple browsers and supports the creation of rooms to handle multiple simultaneous connections. Additionally, it provides functions to send messages to the client and receive messages from the client in real-time.
Communication between clients and servers is part of any application available today on the Internet. Web sockets are a protocol developed to facilitate this process. They allow us to establish bidirectional contact between a client (or several clients) and a server. You can think of your web browser as a client, for example. The server can be a backend program running on your system.
WebSocket is a communication protocol for the client-server model; to understand WebSocket, it is best to compare the specialty of WebSocket over HTTPS.

There are some advantages of WebSocket over HTTPS, but they mainly involve the possibility of creating a full-duplex channel between the client and server, and the possibility of creating rooms to house clients, creating broadcasts, among others.
Using WebSockets is very easy in Flask, just as it happens with other possible dependencies, we can install a plugin with which to have complete control of WebSockets in Flask and the enablement of a special server to be able to use WebSockets.
In this post, we will see how we can create rooms to communicate several clients with each other, with messages to the server and vice versa.
Introduction to Flask-SocketIO and Full-Duplex Communication
The tool we will use is Flask-SocketIO, an implementation of the popular Node.js Socket.io library adapted for Flask.
How Flask-SocketIO works
Events, emit, and listen
Flask-SocketIO works through events: the server listens and the client emits.
For example:
@socketio.on('message')
def handle_message(data):
print('Message received:', data)
socketio.emit('message', data)What is Full-Duplex communication?
Unlike the classic HTTP scheme (where the client requests and the server responds), Full-Duplex communication allows both the client and the server to send messages at any time without waiting for a prior request.
- Classic Scheme: The server cannot send you anything if you do not ask for it first (like refreshing the page).
- WebSockets: The server can "push" information to the client. This is ideal for chat applications, real-time notifications, or games.
The problem arises when you need the server to send you information without you doing anything. With HTTP, the server cannot initiate communication; you have to ask it first. In a chat-type application, if we used old technologies, we would have to make an "infinite loop" from the client asking every second: "Are there new messages?". This is a huge waste of resources, since 99% of the time the answer will be "no".
This is where Full-Duplex communication comes in. This model allows both the client and the server to send messages at any time. The server can "push" a message to the client immediately.
Flask-SocketIO on the Server
The basic configuration in Flask is simple: we load the extension, bind it to our application, and define a SECRET_KEY to secure communications.
Listening and sending messages
To organize communication, we use "tags" or events. For example, we can create a tag called chat.
- Receive: We use a decorator so a Flask function "listens" when the client sends something under that tag.
- Send: To respond, the server uses the emit function. Although there is a function called send, it is recommended to use emit, as it allows us to send structured data (such as text, numbers, or JSON) more efficiently.
The Client: JavaScript and Socket.IO
On the client side (the browser), we will use the Socket.IO JavaScript library. The fundamental steps are:
- Connection: The first thing is to establish the link. It is vital to verify that the client connects correctly, as the server could be down.
- Internal events: The library has its own events like connect and disconnect, which help us know the status of the communication.
- Listen and Emit: * Just like on the server, the client has an on function to listen to what the server sends.
It also has its own emit function to send messages to the server.
Server Implementation (Flask)
To start, we install the specific package:
$ pip install flask-socketioDifferences between HTTP and WebSocket
HTTP follows the classic pattern: the client requests and the server responds.
WebSocket, on the other hand, maintains an open channel that allows the server to also send data without waiting for a request.
In my experience, this completely changes the flow of an app: when a user sends a message, others receive it in real-time, without reloading or checking every second.
⚡ Advantages of full-duplex communication
- Instant data updates.
- Less load on the server (no constant polling).
- Ideal for chats, dashboards, games, streaming, or notifications.
Installation and initial configuration
️ Create a virtual environment and install Flask-SocketIO
As always, I recommend working in an isolated environment in a virtual environment for Flask:
$ python3 -m venv flask_socket_env
$ source flask_socket_env/bin/activate
$ pip install flask flask-socketio️ Base project structure
/flask_socket_app
│
├── app.py
└── templates/
└── index.html
⚙️ Socket server configuration
from flask import Flask, render_template
from flask_socketio import SocketIO
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secure_secret_key'
socketio = SocketIO(app)
@app.route('/')
def index():
return render_template('index.html')
if __name__ == '__main__':
socketio.run(app, debug=True)How Flask-SocketIO works
Events, emit, and listen
Flask-SocketIO works through events: the server listens and the client emits.
For example:
@socketio.on('message')
def handle_message(data):
print('Message received:', data)
socketio.emit('message', data)Create our Room
The use of rooms is a mechanism that allows us to have greater control over the users who can connect to our duplex channels from the client and the server; unlike the communication we have in Flask SocketIO in which we do not have this control, since any user who enters the section of our website where we enable sockets, as we show in the cover video. They will have full access to them without any control; but with rooms, we can now indicate which user is going to join or leave a room; this gives us much more control over which user can or cannot access to see the messages we share through that room; for this, we add one more parameter to communication both on the server and on the client when emitting events:
emit('chat', message['message'], broadcast=True, to=message['room'])
socket.emit('chat', { message: message.value.trim(), room:"room{{current_user.id}}"})Connect and disconnect
In Flask Socket IO, we can easily detect when we connect and disconnect from the socket server; for that:
@socketio.on('connect')
def connect():
print("Connected!!!!!!!")
@socketio.on('disconnect')
def disconnect():Join and leave rooms
Therefore, now we are going to use two more functions to be able to join a room or leave it.
To join a room:
join_room And to leave a room:
leave_roomCreate a real-time chat with Flask-SocketIO
️ Server: handle events and messages
The chat function, which we use to send messages from the server; that is, Flask:
@socketio.on('chat')
def chat(message):
print("Chat:", message)
socketio.emit('chat', message['message'], broadcast=True, to=message['room'])In this function, we emit an event, passed from the client, and with broadcast, we indicate that all clients who are listening to the message['room'] room will receive this message; this function is used from the client as we will see in a few moments.
Client: emit and receive messages
And from the client, that is, JavaScript:
<textarea id="message"></textarea>
<button onclick="sendMsg()">Send</button>
<script>
const socket = io();
function sendMsg() {
const message = document.querySelector("#message").value.trim();
if (!message) return alert("No message to send");
socket.emit('chat', { message: message, room: "room1" });
}
socket.on('chat', msg => console.log("New message:", msg));
</script>In this function, we do the typical checks to know if we have data, after this, through the emit function, we emit the event to the chat function hosted on the server, the one we saw earlier.
Server
Returning to the server, it is important to note that to use a socket, we need to join and also be able to leave that group; as we mentioned before, for that there are the join_room and leave_room functions, in which, with the session enabled, we join or leave the group respectively.
Finally, the functions to join or leave the group that we use:
@socketio.on('join')
def join(room):
username=current_user.name
print("Join")
join_room(room['room'])
emit('join', username+" joined the room", to=room['room'])
@socketio.on('leave')
def leave(room):
username=current_user.name
print("leave")
leave_room(room['room'])
emit('leave', username+" left the room", to=room['room'])As you can see, to make it a little more interesting, we use Flask Login to have different data for each user who makes a connection.
The room parameter can be taken from anywhere, a reference that comes from the view, database, etc.; in this example, we have it set by default from the client's chat function.
With this, we can send messages that will only be heard by users who are assigned after prior access to the room called "room"; for that, we have a couple of buttons:
<button onclick="join()">Join</button>
<button onclick="leave()">Leave</button>And their corresponding functions:
function join(){
socket.emit('join', { room:"room{{current_user.id}}"})
}
function leave(){
socket.emit('leave', { room:"room{{current_user.id}}"})
}Complete step-by-step example
These implementations are ideal for chat-type applications or live collaboration.
Finally, I leave you the complete code that is part of my complete Flask with Python course (link below):
from flask import Blueprint,render_template
from flask_socketio import emit, join_room, leave_room
from flask_login import login_required, current_user
from app import db, socketio
from app.user.models import User
from app.chat.models import MessageRoom
from datetime import datetime
roomBp = Blueprint('room',__name__)
@roomBp.route("/room")
@login_required
def index():
return render_template("room/index.html")
@socketio.on('chat')
@login_required
def chat(message):
print("We are in event "+str(message))
emit('chat', message['message'], broadcast=True, to=message['room'])
@socketio.on('join')
@login_required
def join(room):
username=current_user.name
print("Join")
join_room(room['room'])
emit('join', username+" joined the room", to=room['room'])
@socketio.on('leave')
@login_required
def leave(room):
username=current_user.name
print("leave")
leave_room(room['room'])
emit('leave', username+" joined the room", to=room['room'])Authentication with Flask-Login
I used Flask-Login for authenticated users to be able to join rooms.
This adds a real layer of security to the chat, something that many guides omit.
Control who sees which messages
By using rooms, you can decide which users receive each message, easily segmenting private or group conversations.
In the chat view:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Socket in Flask</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js"
integrity="sha512-q/dWJ3kcmjBLU4Qc47E4A9kTB4m3wuTY7vkFJDTZKjTs8jhyGQnaUrxa0Ytd0ssMZhbNua9hE+E7Qv1j+DyZwA=="
crossorigin="anonymous"></script>
</head>
<body>
<textarea id="message"></textarea>
<button onclick="sendMsj()">Send</button>
<button onclick="join()">Join</button>
<button onclick="leave()">Leave</button>
<script>
var socket = io()
function join(){
socket.emit('join', { room:"room{{current_user.id}}"})
}
function leave(){
socket.emit('leave', { room:"room{{current_user.id}}"})
}
function sendMsj() {
message = document.querySelector("#message")
if (message.value.trim() == "")
return alert("No message to send")
socket.emit('chat', { message: message.value.trim(), room:"room{{current_user.id}}"})
message.value = ""
}
socket.on('connect', function () {
console.log("Connected!")
})
socket.on('disconnect', function () {
console.log("Disconnected!")
})
socket.on('chat', function (message) {
console.log("chat "+message)
})
socket.on('leave', function (message) {
console.log("leave "+message)
})
socket.on('join', function (message) {
console.log("join "+message)
})
</script>
<h1>Hello World</h1>
</body>
</html>⚙️ Good practices and deployment in production
Eventlet and Gunicorn
For production, use Eventlet or Gunicorn with asynchronous workers:
$ pip install eventlet
$ socketio.run(app, host='0.0.0.0', port=5000, debug=False)Security and session handling
- Use a secure SECRET_KEY.
- Integrate role control with custom decorators.
- Isolate rooms and avoid unnecessary global broadcasts.
Scalability and monitoring
Flask-SocketIO can scale using Redis as a message backend and Nginx load balancers.
This is essential if you plan to handle tens of simultaneous users.
Conclusion
Flask-SocketIO turns a standard Flask application into an interactive and lively system.
You don't need complex infrastructure: a Python server and a few lines are enough to have real-time communication.
it is one of the simplest and most powerful ways to take a Flask project to the next level.
If you are interested in deepening your knowledge, I recommend practicing with rooms, authentication, and deployment with Eventlet: three pillars that make the difference between a demo and a professional app.
❓ Frequently Asked Questions (FAQs)
- Does Flask-SocketIO replace WebSocket?
- No. Flask-SocketIO implements WebSocket, but adds a compatibility layer and much simpler event control.
- Can I use Flask-SocketIO with React or Vue?
- Yes. You just need the corresponding Socket.IO client (socket.io-client) in your frontend app.
- What to do if events are not emitted?
- Verify that you use the same event name on the client and server, and that your application runs with socketio.run() and not with app.run().