wss vs ws: Secure WebSocket vs Unencrypted Explained
ws:// vs wss:// at a Glance
Section titled “ws:// vs wss:// at a Glance”ws:// | wss:// | |
|---|---|---|
| Encryption | None | TLS (same as HTTPS) |
| Default port | 80 | 443 |
| Works on HTTPS pages | No (blocked by mixed content) | Yes |
| Passes through proxies | Often stripped or blocked | Yes (encrypted tunnel) |
| Production use | Local development only | Required |
Why wss:// Is Required in Practice
Section titled “Why wss:// Is Required in Practice”Encryption is reason enough, but two practical issues make
ws:// unusable in production even if you don’t care about
security.
Mixed content blocking
Section titled “Mixed content blocking”If your page is served over HTTPS — and every production page
should be — browsers refuse to open ws:// connections. This is
the same mixed content policy that blocks loading HTTP images on
HTTPS pages. The connection silently fails. No error dialog, no
user prompt, just a failed WebSocket in the console.
Mixed Content: The page was loaded over HTTPS, but attemptedto connect to the insecure WebSocket endpoint 'ws://...'.This request has been blocked.There is no workaround. If your page is HTTPS, your WebSocket
must be wss://.
Proxy and firewall interference
Section titled “Proxy and firewall interference”Corporate proxies, transparent proxies, and some ISP-level
middleboxes inspect unencrypted traffic. They often don’t understand
the WebSocket upgrade handshake and either drop the connection or
strip the Upgrade header. The result: your WebSocket works fine
on your home network and fails silently for a subset of users
behind corporate firewalls.
wss:// solves this because the TLS tunnel is opaque to
intermediaries. They see an HTTPS connection to port 443 and
pass it through.
TLS Performance
Section titled “TLS Performance”The TLS handshake adds roughly 1-2ms of latency on modern hardware. After the handshake, per-frame encryption overhead is negligible — AES-GCM on modern CPUs with hardware acceleration adds microseconds per frame, not milliseconds.
The performance argument for ws:// made sense in 2010. It
doesn’t in 2026.
TLS Termination Patterns
Section titled “TLS Termination Patterns”Most production deployments don’t terminate TLS at the application level. The typical pattern:
Client (wss://) --> Load Balancer/Proxy (TLS termination) --> Backend (ws://)The load balancer or reverse proxy handles the TLS certificate and
encryption. Your application server receives plain ws://
connections on an internal network. This is simpler, faster, and
lets you manage certificates in one place.
Common TLS termination points:
- Nginx — handles TLS and proxies
ws://to your backend usingproxy_passwithUpgradeheaders - Cloudflare — terminates TLS at the edge, proxies to
your origin over
ws://orwss:// - AWS ALB — terminates TLS with ACM certificates, forwards WebSocket connections to target groups
- HAProxy — TLS termination with WebSocket-aware connection handling
Common Issues
Section titled “Common Issues”Self-signed certificates
Section titled “Self-signed certificates”Browsers silently reject WebSocket connections to servers with self-signed or invalid TLS certificates. Unlike HTTPS, there is no “click to proceed anyway” dialog. The connection just fails with a generic error.
For development, use mkcert to create locally-trusted certificates. For production, use Let’s Encrypt (free, automated) or any real certificate authority.
Protocol mismatch in JavaScript
Section titled “Protocol mismatch in JavaScript”Hardcoding ws:// in client code is the most common mistake.
Match the page protocol instead:
// Bad: hardcoded ws:// will fail on HTTPS pagesconst ws = new WebSocket('ws://example.com/ws');
// Good: match the page protocolconst protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';const ws = new WebSocket(`${protocol}//${window.location.host}/ws`);Frequently Asked Questions
Section titled “Frequently Asked Questions”What is the difference between ws and wss?
Section titled “What is the difference between ws and wss?”ws:// is unencrypted WebSocket. wss:// is WebSocket over
TLS — identical framing and message format, different transport
security. The relationship mirrors HTTP vs HTTPS. Use wss://
for everything except localhost during development.
Do I need SSL for WebSocket?
Section titled “Do I need SSL for WebSocket?”Yes. Beyond encryption, wss:// is required for compatibility.
Browsers block ws:// from HTTPS pages, and network
intermediaries regularly interfere with unencrypted WebSocket
connections. The only place ws:// works reliably is
localhost.
Does wss add latency?
Section titled “Does wss add latency?”The TLS handshake adds 1-2ms on modern hardware. Per-frame encryption overhead is in the microsecond range with hardware-accelerated AES. TLS latency is not a factor in your performance budget.
Related Content
Section titled “Related Content”- WebSocket API Reference — browser API for creating and managing WebSocket connections
- The Road to WebSockets — how WebSocket fits into the evolution of realtime web protocols
- WebSocket Protocol Deep Dive — the framing, handshake, and protocol internals behind ws and wss
- Nginx WebSocket Proxy — how to configure TLS termination and WebSocket proxying in Nginx
- Cloudflare WebSocket Proxy — Cloudflare configuration for WebSocket connections