← Back to blogYouTube Video

October 23, 2026 • By

WebSockets tutorial: how they work and when to use them

Can't play the video or having issues? Here's the direct link.

The short version

  • A WebSocket is a connection that stays open between the browser and the server, so either side can send a message at any time.
  • HTTP is request and response: the server can only answer when the client asks. WebSockets are events, and neither side has to reply.
  • A WebSocket starts as an HTTP request with an Upgrade header, and the same connection then carries WebSocket messages.
  • Use WebSockets when the server has to push updates without being asked, like chat messages or progress from a long-running job. Keep HTTP for everything else.
  • Use wss:// rather than ws://, and pick it from the page's own protocol so the same code works locally and in production.

A WebSocket is a connection between a browser and a server that stays open, so either side can send a message whenever it wants. Plain HTTP can't do that. With HTTP the server only ever answers requests, so if the client doesn't ask, the server has no way to tell it anything.

That one difference decides when you need WebSockets. Below I go through how HTTP works, how WebSockets work, when to pick each one, and then a small working demo with a Flask server and plain JavaScript in the browser. The video above covers the same ground if you'd rather watch.

How HTTP works: the client asks, the server answers

Every website you visit runs on HTTP. It's a request-response protocol. Your browser (the client) sends a request to the server for index.html, the server sends back the HTML, and the browser renders the page. Then the browser asks for the site's icon, and the server sends the icon back.

Every exchange starts with the client. If the browser never asks for the icon, the server never sends it, because there's no request to respond to. For loading pages and calling most APIs, that's exactly what you want.

The problem HTTP can't solve

Say you're building a messaging app like WhatsApp or Discord. Other people send messages to the server all the time, and your browser has to show them as they arrive. But your browser doesn't know when a new message has landed, so it doesn't know when to ask.

The usual workaround is polling: the browser asks "anything new?" every few seconds. Most of those requests come back empty, and a message can still sit on the server for a few seconds before the next poll picks it up. It works, but it's the wrong shape for the problem. What you want is for the server to say "here's a new message" the moment it has one.

How WebSockets work: events in both directions

A WebSocket starts life as an HTTP request. The browser sends a normal request with an Upgrade: websocket header, the server answers with 101 Switching Protocols, and from then on that same connection stays open and carries WebSocket messages instead of HTTP. That's why people describe WebSockets as an upgrade of HTTP.

After the upgrade, the model is completely different. HTTP is request and response. WebSockets are events. The client can send an event and the server can respond, or the server can send an event and the client can respond, and neither side has to respond at all. Replying is good practice, but nothing in the protocol requires it.

So a real conversation over a WebSocket can look like this: the server sends an event, the client says nothing back, the server sends another one, the client sends one of its own, and then the server sends two more. No request ever has to come first.

WebSocket vs HTTP

HTTPWebSocket
Who can start an exchangeOnly the clientEither side
ConnectionA request, then a responseStays open until one side closes it
Does every message need a reply?Yes, every request gets a responseNo, a reply is optional
URL schemehttp:// and https://ws:// and wss://
Good forPages and most APIsChat, games, live updates, notifications

Use WebSockets when the server has to push something to the client without being asked. Keep HTTP for everything else. They aren't competitors, and most real apps use both: HTTP to load the page and fetch data, and one WebSocket for the live parts.

When to use WebSockets

These are the cases where I'd reach for them:

  • A messaging app, where new messages have to show up the moment someone sends them.
  • A multiplayer game, where every player needs to see what the others do many times a second, and sends their own moves up the same connection.
  • A long-running job on the server. It can send an update to the browser as each step finishes, and the user watches it happen instead of refreshing.
  • A shared document or whiteboard, where everyone sees each other's edits as they type.

If only the server ever needs to talk, Server-Sent Events are a simpler option worth a look, since they run over plain HTTP. If neither side needs to push anything, you don't need either one.

Build a WebSocket server in Flask

Here's a minimal app to see all of this working. The server sends random events to the browser on its own schedule, and whenever the browser sends a message, the server replies with "Message received".

I'm using Python with Flask and the Flask-Sock extension, and plain JavaScript in the browser with no libraries. Most people will be on Node.js, and that's fine: the server has the same shape in any language, and the browser code is identical.

Install the two packages:

pip install flask flask-sock

The project has three files:

websockets-demo/
├── app.py
├── templates/
│   └── index.html
└── static/
    └── index.js

Here's the server, app.py:

import random
import threading
import time

from flask import Flask, render_template
from flask_sock import Sock
from simple_websocket import ConnectionClosed

app = Flask(__name__)
sock = Sock(app)

EVENTS = [
    "New order received",
    "User signed up",
    "Report finished generating",
    "Payment processed",
    "Backup completed",
]


@app.route("/")
def index():
    return render_template("index.html")


@sock.route("/ws")
def websocket(ws):
    # Two threads send on this socket, so they take turns
    send_lock = threading.Lock()

    def send(message):
        with send_lock:
            ws.send(message)

    def background_sender():
        while ws.connected:
            time.sleep(random.uniform(1, 3))
            try:
                send(random.choice(EVENTS))
            except ConnectionClosed:
                break

    threading.Thread(target=background_sender, daemon=True).start()

    # receive() blocks until the client sends something, and raises
    # ConnectionClosed when it leaves, which Flask-Sock handles for us
    while True:
        data = ws.receive()
        send(f"Message received: {data}")


if __name__ == "__main__":
    app.run(debug=True)

The / route is plain HTTP. It renders the page, and that's all it does.

The /ws route is the WebSocket. Flask-Sock handles the upgrade handshake and hands the function a ws object for that one client. The function then does two jobs at once:

  1. It starts a background thread running background_sender, which sends a random event from the list every one to three seconds, for as long as the client stays connected. This is the part HTTP can't do: the server talks without being asked.
  2. It sits in a loop waiting for the client. Every time a message arrives, it sends back "Message received" with the text.

Both of those send on the same socket from different threads, so they share a lock and never write at the same moment. When the browser tab closes, receive() raises ConnectionClosed, Flask-Sock cleans up, and the background thread stops within a few seconds.

The browser side: the native WebSocket API

Browsers have WebSockets built in, so the client needs no library. The page itself is a text box plus a list the messages go into. Here's templates/index.html:

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>WebSockets demo</title>
</head>
<body>
  <p>Status: <strong id="status">Connecting...</strong></p>
  <form id="form">
    <input id="message" placeholder="Say something" autocomplete="off">
    <button>Send</button>
  </form>
  <ul id="log"></ul>
  <script src="{{ url_for('static', filename='index.js') }}"></script>
</body>
</html>

And static/index.js, which is where the WebSocket lives:

// Same rule as http and https: use the secure wss:// when the page itself is on https
const scheme = location.protocol === "https:" ? "wss:" : "ws:";
const socket = new WebSocket(`${scheme}//${location.host}/ws`);

const statusText = document.getElementById("status");
const log = document.getElementById("log");

function addLine(text) {
  const item = document.createElement("li");
  item.textContent = text;
  log.append(item);
}

socket.addEventListener("open", () => {
  statusText.textContent = "Connected";
});

socket.addEventListener("message", (event) => {
  addLine(`Server: ${event.data}`);
});

socket.addEventListener("close", () => {
  statusText.textContent = "Disconnected";
});

socket.addEventListener("error", () => {
  addLine("The connection had an error");
});

document.getElementById("form").addEventListener("submit", (event) => {
  event.preventDefault();
  const input = document.getElementById("message");
  if (socket.readyState === WebSocket.OPEN && input.value) {
    socket.send(input.value);
    addLine(`You: ${input.value}`);
    input.value = "";
  }
});

The first two lines pick the URL. The difference between ws:// and wss:// is the same as the difference between http:// and https://: one is encrypted and the other isn't. Use the secure one. Deriving it from the page's own protocol means the same code works on your laptop over http and in production over https. Browsers also block a plain ws:// connection from a page served over https, so getting this wrong breaks the app in production.

The rest is event handlers. open fires when the connection is up, message fires for every event the server sends, close fires when either side ends the connection, and error fires when something goes wrong. socket.send() is how the browser sends its own events, and the form calls it when you press Send.

Run it

From the project folder:

flask --app app run

Open http://127.0.0.1:5000. The status switches to "Connected", and within a few seconds events start appearing in the list, without you sending anything. Type "hello" and press Send, and the server answers with "Message received: hello" in between its own events.

Watch the list for a minute and you'll see the server keep talking to the browser without a single request from it.

Learn how it works, and let AI write the syntax

I didn't spend long on the code in the video, and I'd do the same here. Everyone uses a different stack, and AI writes most of the code for us now anyway. Ask any AI tool for "a WebSocket server in Express" and you'll get something close to the Flask code above in a few seconds.

What AI can't do for you is decide whether you need a WebSocket in the first place. That takes knowing how the protocols work under the hood: HTTP only answers, a WebSocket lets either side speak, and each one fits different problems. WebSockets aren't better than HTTP, and you shouldn't use them everywhere. When the client and server need to talk in real time without waiting on requests and responses, that's where they're the right tool.

Video transcript

Show
WebSockets. This video is going to be about how WebSockets work, where you should be using them, what the use cases of WebSockets are, and how to implement them. WebSockets are for when you want the client to be able to communicate with the server. They're kind of an upgrade of the HTTP protocol, which has a client-server architecture where the client can request updates from the server, but the server can't send requests to the client, right? WebSockets solve that problem. When you use WebSockets, you can have the client communicate with the server or the server communicate with the client. You can have any of it, right? Now, this is how the HTTP protocol works. Every single website you visit, the entire internet, right, is working on the HTTP protocol. And how this works is this is basically a request-response kind of a protocol where the client over here, in this case, our browser, is going to send a request to the server to get index.html, which is an HTML file. The server will respond with the response over here, which returns index.html, and then the browser will render it and show you the page, right? Similar thing over here. The client will send a request to the server to get the icon of the website, and the server will then respond to that request by returning the icon. So we have a client-server architecture, which is based on the request-response cycle, right? The client sends a request, the server returns a response. If the client doesn't send a request over here, if I didn't, let's say, if the client doesn't send a request for the favicon over here, then the server can't return it, right? The server won't be able to return it, right? Because there's no request to respond to. And that's the problem with HTTP, right? The client always has to request an update from the server before the server can respond. But when you have a situation like where the client doesn't know whether an update has happened or not but still needs real-time communication between the client and server, right? Let's say you're building some sort of an online messaging app, right, like WhatsApp or Discord or something. If other people are sending messages to the server, then your client, your browser, needs to be able to see those messages as well, right? So you can actually talk to people on the app. But how do you know whether new messages have arrived and you need to send requests to fetch those messages or not, right? That's the problem that WebSockets are going to solve. This is how WebSocket protocol works. It's an event protocol, which is the complete opposite of HTTP, which is a request-response protocol, right? The client sends a request. The server sends a response, right? WebSockets are based on events. And the way events work is the client can send an event and the server can respond to it, or the server can send an event and the client can respond to it. And it's not necessary to respond back. Even it's a good practice, but you don't even need to respond over here. So, for example, over here, the server is sending an event to the client. The client doesn't respond back. It doesn't need to. The server sends another event to the client. The client then sends an event to the server, and then the server sends two more events to the client. So this is what WebSocket looks like. You can have the clients communicating directly with the server and the server communicating directly with the clients without needing some sort of a request in between them. You can have events. You can have events, and the server and the client both can send and receive events to and from each other. And that's the beauty of WebSockets. So in applications where you need real-time communication, like some multiplayer gaming server, for instance, or an online messaging app, or even just logging updates to a client, right? If you have some sort of a long-running application process in the server and you want to make sure that the client gets notified of updates to that process, you can use WebSockets for that. The server can send events to the client, and the client browser can then display those events to you, the end user, right? Now let's look at some of the code. I have a very simple, very minimal app written over here. This is using Python Flask for the back end, and it's using, where is it, it's using simple native JavaScript on the browser, on the client side, to use WebSockets. And let me just show you what this looks like so you have an idea of WebSockets, of how WebSockets work and stuff, right? Let's run this and see what the app actually looks like. So this is what WebSockets look like in a real application. You can see I'm not sending any message over here, but the server is responding to me already with these events and these messages over here, right? I don't need to send a message, but I can obviously, I could say hello or whatever, and it's going to respond back, "Message received," and then it's going to keep sending its own events, right? That's the beauty of WebSockets. The server can directly communicate with the client, in this case, my browser, without necessarily having to receive a request from said client, right? So that's how WebSockets work. They're event-based, which is a complete opposite of HTTP, which is request-based, right? And I'm not going to go too deep into the code over here because, one, every single developer over here is using their own tech stack. Most people are using Node.js instead of Python over here. And also, we live in 2026, guys. AI is writing 90% of the code for us. You don't need to know the syntax as much as you need to know concepts and how things work. That is why I spent so much time explaining the concept over here, how WebSockets work under the hood. That is why I spent the entire first portion of the video discussing the differences between WebSockets and the HTTP protocol over here. Because let's be honest, AI can write all of the code for you. What you really need to understand in this day and age is how that code works, what it's doing, and how these different protocols and algorithms and data structures and all of these different concepts work under the hood, right? The code is not so much important anymore as much as these concepts. But I'll still give you a quick overview of the code. You have a little homepage over here that just renders the index.html template. Then you have this WebSocket routes that literally just starts a new thread that's going to run the background sender function over here, right? And this background sender function is just going to send random events to the clients, these bunch of random events that we have defined in the list over here, right? So all these little events that you keep seeing over here, right, this is happening from that background sender function. And once this thread has begun, we just have an infinite loop over here that listens for new data to be received from the client. And every single time we receive some data, we send "message received." So, like you saw before, if I type something over here, it's going to receive that data and say "message received." So that's the backend code for this over here. If I go to index.html, you'll see this is just a very basic UI that uses Tailwind and stuff to make everything look a bit pretty, right? The real code is in index.js, right? And even here, most of the code is just for design and UI purposes. You can see I'm adding a bunch of Tailwind classes based on whether the client state has connected or disconnected or it's connecting, right? I just adding a bunch of Tailwind classes over here to make the UI look pretty. The real beauty is over here where we create a new WebSocket with our WebSocket URL over here. And the way we do this is we basically just use the HTTPS URL over here to determine whether we need to have WSS or WS. And the difference between both of these is literally just the difference between HTTP and HTTPS. One is secure, the other is not. And you can use whichever you prefer, obviously, but use the secure version. That's going to be a better. So we create a new WebSocket by passing in the URL. We have a little log function over here that literally just, again, has a bunch of Tailwind classes to display the messages that the socket sends, right? And then we just have a bunch of event handlers over here. So what happens when the WebSocket is opened, when we receive a message, when we close the WebSocket, if we receive an error, and these are just a bunch of functions that handle these events, right? These are just a bunch of event handlers. And then we just have a send message function over here, which is literally just going to take our message and send it to the client over there, right? And that's what we do from this little text box over here, right? When I send a message, it runs that send message function and sends it to the WebSocket. Anyway, that's the high-level overview of the code. Like I said, that's not really important in this day and age. AI can write the code for you. What's really important is understanding the concepts. So make sure you focused on the first bit of the video over here and understood the differences between the HTTP protocol and the WebSocket protocol and how both of them work and what problems they solve. It's not that the WebSocket protocol is perfect and you should use it all the time. There are different use cases for HTTP and for WebSockets. And when you want real-time communication between client and server without needing to wait for requests and responses, right, that's when WebSockets really shines. And so if you've got a use case like that, then use it over there. Anyway, that's the video. Like, comment, subscribe. Thank you for watching, and let me know what you want to see next. And a quick shameless plug to end the video. I'm a web and mobile developer, and I work as a freelancer building web apps and mobile apps for people. And if that is something you're interested in, or you know somebody who's interested in that, if you want to work with me to build a project or something, then go to the top link in the description and book a call with me. We're going to talk on the call, and we're going to just, we're going to discuss your project and we're going to get to work building it. If that's something you're interested in, guys, top link in the description. Other than that, thank you for watching the video. Like, comment, subscribe, and I'll see you in the next one.

Share this article

Hassan Aziz pointing up

Dude, you’re at the bottom of my landing page.

Just book a call already if you’re that interested.

You scrolled all the way here.