WebSocket Connections: Analyzing Real-Time Web Communication
A practical Fusebox guide to websocket connections.
WebSocket Connections: Analyzing Real-Time Web Communication
Published: January 2024
Reading time: 7 minutes
WebSockets power real-time features like chat, notifications, live updates, and collaborative editing. Here's how to detect, analyze, and understand WebSocket connections on any website.
What Are WebSockets?
Unlike regular HTTP requests (request → response → done), WebSockets create persistent, two-way connections:
HTTP: Client → Server → Response → Connection Closed
WebSocket: Client ↔ Server (continuous bidirectional communication)
This enables:
- Live chat messages
- Real-time notifications
- Stock price updates
- Collaborative editing
- Live sports scores
- Multiplayer games
Detecting WebSocket Connections
1. Browser DevTools Method
// In Chrome DevTools:
// 1. Network tab
// 2. Filter: WS
// 3. Look for 101 Switching Protocols
// Or programmatically:
const sockets = [];
const originalWebSocket = window.WebSocket;
window.WebSocket = function(...args) {
const socket = new originalWebSocket(...args);
sockets.push({
url: args[0],
protocols: args[1],
socket: socket,
created: new Date()
});
console.log('WebSocket created:', args[0]);
// Monitor events
socket.addEventListener('open', () => {
console.log('WebSocket opened:', args[0]);
});
socket.addEventListener('message', (event) => {
console.log('WebSocket message:', event.data);
});
socket.addEventListener('close', () => {
console.log('WebSocket closed:', args[0]);
});
return socket;
};
2. Performance API Detection
// Find WebSocket upgrade requests
performance.getEntriesByType('resource').forEach(entry => {
if (entry.name.startsWith('ws://') || entry.name.startsWith('wss://')) {
console.log('WebSocket connection:', entry.name);
}
});
3. Common WebSocket Patterns
// Socket.io
wss://example.com/socket.io/?transport=websocket
// SignalR
wss://example.com/signalr/connect
// Raw WebSocket
wss://example.com/ws
wss://example.com/realtime
// GraphQL Subscriptions
wss://example.com/graphql-ws
Real-World WebSocket Examples
Example 1: Chat Application
Connection detected:
URL: wss://chat.example.com/socket.io/?userId=123&token=abc
Protocol: socket.io
Messages observed:
→ {"type":"auth","token":"abc123"}
← {"type":"auth_success","userId":"123"}
→ {"type":"join_room","room":"general"}
← {"type":"room_joined","users":45}
← {"type":"message","user":"John","text":"Hello!","timestamp":1234567890}
→ {"type":"message","text":"Hi there!"}
← {"type":"message_sent","id":"msg_789"}
What this reveals:
- Using Socket.io (popular library)
- Token-based authentication
- Room-based chat system
- 45 users in room
- Message acknowledgment pattern
Example 2: Trading Platform
Multiple WebSocket connections:
// Price feed
wss://stream.exchange.com/quotes?symbols=BTC,ETH,DOGE
// Order updates
wss://api.exchange.com/orders/stream
// News feed
wss://news.exchange.com/realtime
Message frequency analysis:
Price updates: 10-50 messages/second
Order updates: 1-5 messages/minute
News updates: 1-2 messages/minute
Total bandwidth: ~100KB/second
Example 3: Collaborative Editor
WebSocket for Google Docs-style editing:
URL: wss://collab.app.com/doc/abc123
Protocol: ["v1.collab"]
Message types:
{
"type": "cursor",
"userId": "user456",
"position": {"line": 10, "ch": 45}
}
{
"type": "operation",
"op": ["retain", 100, "insert", "Hello", "retain", 50],
"revision": 234
}
{
"type": "presence",
"users": [
{"id": "123", "name": "Alice", "color": "#ff0000"},
{"id": "456", "name": "Bob", "color": "#00ff00"}
]
}
WebSocket Security Analysis
1. Authentication Methods
Token in URL (Common but risky):
wss://api.example.com/ws?token=secret123
// Token visible in logs, history
Token in protocol (Better):
new WebSocket('wss://api.example.com/ws', ['auth-secret123']);
Post-connection auth (Best):
const ws = new WebSocket('wss://api.example.com/ws');
ws.onopen = () => {
ws.send(JSON.stringify({
type: 'auth',
token: localStorage.getItem('authToken')
}));
};
2. Common Security Issues
Missing encryption:
// Bad: Unencrypted
ws://api.example.com/chat
// Good: Encrypted
wss://api.example.com/chat
No origin validation:
// Server should check Origin header
Origin: https://evil-site.com
// Prevent cross-site WebSocket hijacking
Missing rate limiting:
// Flooding attack possible
for (let i = 0; i < 10000; i++) {
ws.send('spam message ' + i);
}
Performance Analysis
1. Message Frequency Monitor
function monitorWebSocketPerformance(url) {
const ws = new WebSocket(url);
const stats = {
messagesReceived: 0,
bytesSent: 0,
bytesReceived: 0,
startTime: Date.now(),
messageLog: []
};
ws.onmessage = (event) => {
stats.messagesReceived++;
stats.bytesReceived += event.data.length;
// Log message rate
const elapsed = (Date.now() - stats.startTime) / 1000;
const rate = stats.messagesReceived / elapsed;
stats.messageLog.push({
time: Date.now(),
size: event.data.length,
rate: rate.toFixed(2)
});
// Alert if too frequent
if (rate > 100) {
console.warn('High message rate:', rate, 'msg/sec');
}
};
// Override send to track outgoing
const originalSend = ws.send;
ws.send = function(data) {
stats.bytesSent += data.length || 0;
return originalSend.call(this, data);
};
return stats;
}
2. Connection Health Check
class WebSocketHealthMonitor {
constructor(ws) {
this.ws = ws;
this.pingInterval = null;
this.lastPong = Date.now();
this.startHealthCheck();
}
startHealthCheck() {
// Send ping every 30 seconds
this.pingInterval = setInterval(() => {
if (this.ws.readyState === WebSocket.OPEN) {
this.ws.send(JSON.stringify({ type: 'ping' }));
// Check if pong received
setTimeout(() => {
if (Date.now() - this.lastPong > 35000) {
console.error('WebSocket unhealthy - no pong received');
this.ws.close();
}
}, 5000);
}
}, 30000);
// Listen for pongs
this.ws.addEventListener('message', (event) => {
const data = JSON.parse(event.data);
if (data.type === 'pong') {
this.lastPong = Date.now();
}
});
}
}
Common WebSocket Libraries
1. Socket.io Detection
// Socket.io signs
if (window.io) {
console.log('Socket.io detected');
// Monitor connections
const sockets = io.sockets;
console.log('Active sockets:', Object.keys(sockets).length);
}
// URL pattern
// wss://example.com/socket.io/?EIO=4&transport=websocket
2. SignalR Detection
// SignalR signs
if (window.$ && $.signalR) {
console.log('SignalR detected');
// Get active connections
const connections = $.signalR.connections;
}
// Or for newer versions
if (window.signalR) {
console.log('SignalR Core detected');
}
3. Native WebSocket
// No library wrapper
const ws = new WebSocket('wss://example.com/ws');
// Direct protocol usage
Debugging WebSocket Issues
1. Connection Problems
const ws = new WebSocket('wss://example.com/ws');
ws.onerror = (error) => {
console.error('WebSocket error:', error);
};
ws.onclose = (event) => {
console.log('WebSocket closed:', {
code: event.code,
reason: event.reason,
wasClean: event.wasClean
});
// Common close codes
switch(event.code) {
case 1000: console.log('Normal closure'); break;
case 1001: console.log('Going away'); break;
case 1006: console.log('Abnormal closure'); break;
case 1009: console.log('Message too big'); break;
case 1011: console.log('Server error'); break;
}
};
2. Message Debugging
// Log all WebSocket traffic
function debugWebSocket(url) {
const ws = new WebSocket(url);
// Log lifecycle
ws.onopen = () => console.log('🟢 Connected');
ws.onclose = (e) => console.log('🔴 Disconnected:', e.code);
ws.onerror = (e) => console.log('⚠️ Error:', e);
// Log messages with formatting
ws.onmessage = (event) => {
try {
const data = JSON.parse(event.data);
console.log('📥 Received:', data);
} catch {
console.log('📥 Received (raw):', event.data);
}
};
// Override send to log outgoing
const originalSend = ws.send.bind(ws);
ws.send = (data) => {
try {
const parsed = JSON.parse(data);
console.log('📤 Sending:', parsed);
} catch {
console.log('📤 Sending (raw):', data);
}
return originalSend(data);
};
return ws;
}
WebSocket Best Practices
1. Reconnection Logic
class ReconnectingWebSocket {
constructor(url, options = {}) {
this.url = url;
this.reconnectDelay = options.reconnectDelay || 1000;
this.maxReconnectDelay = options.maxReconnectDelay || 30000;
this.reconnectAttempts = 0;
this.connect();
}
connect() {
this.ws = new WebSocket(this.url);
this.ws.onopen = () => {
console.log('Connected');
this.reconnectAttempts = 0;
this.reconnectDelay = 1000;
};
this.ws.onclose = () => {
console.log('Disconnected, reconnecting...');
this.scheduleReconnect();
};
}
scheduleReconnect() {
setTimeout(() => {
this.reconnectAttempts++;
this.connect();
}, Math.min(this.reconnectDelay * Math.pow(2, this.reconnectAttempts),
this.maxReconnectDelay));
}
}
2. Message Queuing
class QueuedWebSocket {
constructor(url) {
this.url = url;
this.messageQueue = [];
this.connected = false;
this.connect();
}
connect() {
this.ws = new WebSocket(this.url);
this.ws.onopen = () => {
this.connected = true;
this.flushQueue();
};
this.ws.onclose = () => {
this.connected = false;
};
}
send(data) {
if (this.connected && this.ws.readyState === WebSocket.OPEN) {
this.ws.send(data);
} else {
this.messageQueue.push(data);
}
}
flushQueue() {
while (this.messageQueue.length > 0) {
const message = this.messageQueue.shift();
this.ws.send(message);
}
}
}
Quick WebSocket Audit
// Run this to analyze WebSockets on current page
(function auditWebSockets() {
console.log('🔍 WebSocket Audit');
// Check for WebSocket support
if (!window.WebSocket) {
console.log('❌ WebSockets not supported');
return;
}
// Check for libraries
const libraries = [];
if (window.io) libraries.push('Socket.io');
if (window.Primus) libraries.push('Primus');
if (window.SockJS) libraries.push('SockJS');
if (window.signalR || (window.$ && $.signalR)) libraries.push('SignalR');
if (libraries.length) {
console.log('📚 Libraries found:', libraries.join(', '));
}
// Monitor new connections
let connectionCount = 0;
const originalWS = window.WebSocket;
window.WebSocket = function(...args) {
connectionCount++;
console.log(`🔌 WebSocket #${connectionCount}:`, args[0]);
const ws = new originalWS(...args);
// Monitor this connection
ws.addEventListener('open', () => {
console.log(`✅ WebSocket #${connectionCount} opened`);
});
let messageCount = 0;
ws.addEventListener('message', () => {
messageCount++;
if (messageCount % 100 === 0) {
console.log(`📊 WebSocket #${connectionCount}: ${messageCount} messages`);
}
});
return ws;
};
console.log('✅ WebSocket monitoring active');
})();
The Bottom Line
WebSockets reveal:
- Real-time features of the application
- Architecture patterns (polling vs. push)
- Scale considerations (message frequency)
- Security implementation (auth, encryption)
- Third-party integrations (chat, analytics)
Understanding WebSockets helps you build better real-time features and debug connection issues.
Monitor WebSocket connections instantly: Fusebox tracks all WebSocket connections, messages, and performance metrics while you browse. See real-time communication in action. $29 one-time purchase.