Skip to content

Websocket Ws Vs Wss

DodaTech 4 min read

title: "WebSocket ws:// vs wss://" description: "Understand the differences between unencrypted ws:// and encrypted wss:// WebSocket connections, security implications, and performance trade-offs." weight: 14 date: 2026-06-28 lastmod: 2026-06-28 tags: ["apis", "websocket"]


WebSocket supports two URL schemes: `ws://` for unencrypted connections and `wss://` for TLS-encrypted connections. Choosing the right scheme is critical for security and compatibility.

## What You'll Learn

- ws:// vs wss:// differences
- TLS encryption for WebSocket
- Performance implications of encryption
- Browser compatibility requirements
- When to use each scheme

## Why It Matters

Using `ws://` in production exposes all WebSocket traffic to eavesdropping and tampering. Modern browsers also restrict `ws://` on secure pages, making `wss://` mandatory for most web applications.

## Real-World Use

A healthcare application requires `wss://` for all WebSocket connections to comply with HIPAA regulations. Patient data transmitted via WebSocket must be encrypted in transit, and `ws://` would violate compliance requirements.

## Flow Chart

```mermaid
flowchart LR
    A[WebSocket URL] --> B{Scheme}
    B -->|ws://| C[Unencrypted TCP]
    B -->|wss://| D[TLS Encrypted]
    C --> E[Port 80]
    D --> F[Port 443]
    C --> G[No Encryption]
    D --> H[TLS Handshake]
    G --> I[Eavesdroppable]
    H --> J[Secure Communication]

Code Examples

Example 1: Connection with Different Schemes

// Unencrypted - ws://
const wsClient = new WebSocket('ws://localhost:8080');

// Encrypted - wss://
const wssClient = new WebSocket('wss://secure.example.com:443/ws');

// Browser will reject ws:// on HTTPS pages
if (window.location.protocol === 'https:') {
  const ws = new WebSocket(`wss://${window.location.host}/ws`);
} else {
  const ws = new WebSocket(`ws://${window.location.host}/ws`);
}

Expected output: On HTTPS pages, only wss:// connections are allowed. ws:// connections are blocked by the browser.

Example 2: Node.js Server with TLS

const fs = require('fs');
const https = require('https');
const WebSocket = require('ws');

// Load TLS certificates
const server = https.createServer({
  cert: fs.readFileSync('/path/to/certificate.pem'),
  key: fs.readFileSync('/path/to/private.key'),
});

const wss = new WebSocket.Server({ server });

wss.on('connection', (ws) => {
  ws.send('Secure connection established');
  console.log('Client connected via WSS');
});

server.listen(443, () => {
  console.log('Secure WebSocket server on wss://localhost:443');
});

// Client connecting with WSS
const client = new WebSocket('wss://localhost:443', {
  rejectUnauthorized: false, // Only for self-signed certs
});

Expected output: Server starts with TLS, and clients connect securely using the wss:// scheme.

Example 3: Self-Signed Certificate for Development

const WebSocket = require('ws');
const https = require('https');
const selfsigned = require('selfsigned');

// Generate self-signed certificate
const attrs = [{ name: 'commonName', value: 'localhost' }];
const { cert, key } = selfsigned.generate(attrs, {
  days: 365,
  algorithm: 'sha256',
});

const server = https.createServer({ cert, key });
const wss = new WebSocket.Server({ server });

wss.on('connection', (ws) => {
  ws.send('Development WSS connection');
});

server.listen(9443);

// Client with self-signed cert acceptance
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
const client = new WebSocket('wss://localhost:9443');

Expected output: Development server uses self-signed certificate for WSS testing. Note: Never use NODE_TLS_REJECT_UNAUTHORIZED=0 in production.

Common Mistakes

Mistake Explanation
Using ws:// on HTTPS pages Browsers block mixed content; HTTPS pages require wss://
Using self-signed certs in production Always use trusted certificates from a CA in production
Forgetting TLS on sensitive data Any authentication tokens or sensitive data require wss://
Ignoring certificate hostname mismatch Certificate CN/SAN must match the WebSocket server hostname
Using wrong port Default ws:// port is 80; default wss:// port is 443

Practice Questions

  1. What is the difference between ws:// and wss://?
  2. Why do browsers block ws:// on HTTPS pages?
  3. How do you set up a WSS server with a valid certificate?
  4. What are the performance costs of using wss:// vs ws://?
  5. How do you handle self-signed certificates during development?

Challenge

Set up a production-grade WebSocket server with WSS using Lets Encrypt certificates. Implement automatic certificate renewal and verify the connection is properly encrypted using Wireshark or a similar tool.

FAQ

Does wss:// add significant latency?

TLS handshake adds one round trip (30-100ms) to initial connection. After handshake, encryption overhead is minimal (1-3% CPU).

Can I use wss:// with a reverse proxy?

Yes, terminate TLS at the proxy (NGINX, Envoy) and forward plain ws:// to the backend. This is a common deployment pattern.

What certificate types work with WSS?

Any TLS certificate works: self-signed for development, Lets Encrypt for production, or commercial CA certificates.

Do all WebSocket libraries support WSS?

Most libraries support both ws:// and wss://. Check the documentation for TLS configuration options.

Can I use wss:// without a domain name?

You need a hostname that matches the certificate. For IP addresses, consider using a reverse proxy with DNS.

Is wss:// required for localhost development?

No, ws:// works for localhost. Use wss:// when testing features that require secure contexts (like service workers or geolocation).

Mini Project

Write a script that benchmarks ws:// vs wss:// connections. Measure connection time, throughput for large messages, and latency for small messages. Document the performance characteristics and recommend appropriate use cases for each.

What's Next

Learn how to integrate WebSocket with Express.js

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro