
October 09, 2025
How to Build an End-to-End Real-Time Application with WebRTC and Node.js
How to Build an End-to-End Real-Time Application with WebRTC and Node.js
Did you ever want to develop an app for real-time chat, video, and collaboration without latency? These apps can readily employ WebRTC (Web Real-Time Communication) for peer-to-peer communication based on the browser. WebRTC and Node.js as the signalling server support rich, interactive apps. WebRTC and Node.js will assist you in building an end-to-end communication app in real time in this tutorial. This tutorial will assist you in building a video chat application, file-sharing site, or interactive collaborative tool.
What is WebRTC and How Does It Work?
WebRTC (Web Real-Time Communication) is an open-source initiative that allows browser peers to exchange voice, video, and data without the need for plugins or third-party software. It is peer-to-peer compliant, which makes it ideal for video chat, voice calls, and file exchange.
WebRTC employs peer-to-peer (P2P) communication between browsers. WebRTC does not establish connections. Signalling coordinates connections, user authentication, network setup, and session negotiation.
Our WebRTC application will employ Node.js as the signalling server to coordinate peer communication (trading connection metadata) and facilitate real-time interaction. Node.js facilitates peers to find each other and get connected, while WebRTC transfers media.
Setting Up the Project
We must first set up the client-side and server-side of our WebRTC app before developing it. Set up the Node.js server first.
First, create a project folder and start a Node.js project.
mkdir webrtc-app
cd webrtc-app
npm init -y
Install necessary dependencies:
npm install express socket.io
Express will be used to serve our application, and Socket.IO will handle real-time signaling between peers.
Set up the Node.js server in the server.js file:
const express = require('express');
const http = require('http');
const socketIo = require('socket.io');
const app = express();
const server = http.createServer(app);
const io = socketIo(server);
app.use(express.static('public')); // Serve static files
io.on('connection', socket => {
console.log('a user connected');
socket.on('disconnect', () => {
console.log('user disconnected');
});
socket.on('offer', (offer) => {
socket.broadcast.emit('offer', offer);
});
socket.on('answer', (answer) => {
socket.broadcast.emit('answer', answer);
});
socket.on('candidate', (candidate) => {
socket.broadcast.emit('candidate', candidate);
});
});
server.listen(3000, () => {
console.log('Server listening on port 3000');
});
This code configures the signalling server using Socket.IO for offer, answer, and candidate messages. These messages are essential for WebRTC connection.
Setting Up the Client-Side
Next, make the client-side application that uses WebRTC, and for this we need a webcam for both the local and remote users.
First, create the public/index.html file for the client interface:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WebRTC App</title>
<style>
video { width: 45%; margin: 10px; }
</style>
</head>
<body>
<h1>WebRTC Video Chat</h1>
<video id="localVideo" autoplay muted></video>
<video id="remoteVideo" autoplay></video>
<script src="/socket.io/socket.io.js"></script>
<script src="app.js"></script>
</body>
</html>
This HTML code creates two <video> elements: one for the local stream and one for the remote stream.
Handle WebRTC functionality in public/app.js:
const socket = io();
let localStream;
let peerConnection;
const remoteVideo = document.getElementById('remoteVideo');
const localVideo = document.getElementById('localVideo');
const configuration = {
iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
};
navigator.mediaDevices.getUserMedia({ video: true, audio: true })
.then(stream => {
localStream = stream;
localVideo.srcObject = stream;
})
.catch(error => {
console.error('Error accessing media devices.', error);
});
socket.on('offer', (offer) => {
peerConnection = new RTCPeerConnection(configuration);
peerConnection.setRemoteDescription(new RTCSessionDescription(offer));
peerConnection.addStream(localStream);
peerConnection.createAnswer()
.then(answer => {
peerConnection.setLocalDescription(answer);
socket.emit('answer', answer);
})
.catch(error => {
console.error('Error creating answer:', error);
});
peerConnection.onaddstream = event => {
remoteVideo.srcObject = event.stream;
};
peerConnection.onicecandidate = event => {
if (event.candidate) {
socket.emit('candidate', event.candidate);
}
};
});
function startCall() {
peerConnection = new RTCPeerConnection(configuration);
peerConnection.addStream(localStream);
peerConnection.createOffer()
.then(offer => {
peerConnection.setLocalDescription(offer);
socket.emit('offer', offer);
})
.catch(error => {
console.error('Error creating offer:', error);
});
peerConnection.onaddstream = event => {
remoteVideo.srcObject = event.stream;
};
peerConnection.onicecandidate = event => {
if (event.candidate) {
socket.emit('candidate', event.candidate);
}
};
}
This code uses getUserMedia to access the user's webcam and microphone for the local video element. RTCPeerConnection establishes the WebRTC connection, and createOffer and createAnswer exchange session descriptions between peers. The other peer receives a network configuration candidate.
Establishing the Connection
We need the signalling server to exchange offer, respond, and ICE candidates amongst peers to connect. The signalling server assists peers to discover each other and exchange WebRTC connection details.
Server code.js file emits offer, answer, and candidate events to connected clients. A user invokes startCall(), and the server makes an offer to the second user, who responds and creates the connection.
The flow:
- 1. The caller user makes an offer.
- 2. The signalling server forwards the offer to the second user.
- 3. The second user responds.
- 4. Finally, swap ICE candidates to improve connection.
But first, the local and remote video parts need to connect to each other directly.
Conclusion
Finally, you've created a WebRTC and Node.js video chat app in this lesson. Let's have a recap, WebRTC provides peer-to-peer communication, Node.js signals, and browser video and audio. You can enhance this simple app with text chat, file transfers, and group video calls. WebRTC and Node.js enable scalable, interactive real-time applications. Once you know WebRTC, you can build more robust real-time communication apps!
83 views