WebSocket Close Codes
Every WebSocket close code from 1000 to 4999, what fires it, who sends it, and how a well-behaved client should react. Based on RFC 6455 with notes on real-world proxy and library behaviour.
The Four Ranges
Standard (RFC 6455)
Codes defined directly by the WebSocket protocol specification. Have well-known meanings across all implementations.
Reserved
Reserved for future IANA assignment. Must not be used in application code.
Library / Framework
Available for libraries and frameworks that need their own close codes (Socket.IO, GraphQL-WS, MQTT-over-WS).
Application
Available for application-specific close codes. Define the meanings in your API documentation.
Frequently Asked Questions
What does WebSocket close code 1006 mean?+
1006 means abnormal closure, the connection terminated without a proper close frame being exchanged. It is the most common production close code and almost always indicates a network or proxy issue: TCP reset, mobile radio handoff, firewall idle-kill, or an intermediate proxy (NGINX, AWS ALB, Cloudflare) timing out the connection. The endpoint never receives 1006 over the wire; it is a synthetic code surfaced by the WebSocket library to the application. Fix it by reconnecting with exponential backoff and checking proxy idle timeouts upstream.
What is the difference between WebSocket close codes 1000 and 1001?+
1000 (Normal Closure) means the connection finished the work it was opened for and shut down cleanly. 1001 (Going Away) means the endpoint is healthy but is leaving, a browser navigating away, a tab closing, or a server gracefully restarting. Treat 1000 as do-not-reconnect and 1001 as reconnect-with-backoff. Both are 'expected' close codes and should not trigger error logging.
Can I use custom WebSocket close codes?+
Yes, RFC 6455 reserves the range 4000–4999 for application-defined close codes. Use them to signal protocol-specific conditions like 'idle timeout', 'duplicate session', or 'rate limited' so clients can react programmatically. Codes 3000–3999 are for libraries and frameworks (Socket.IO, GraphQL-WS, MQTT-over-WS). Codes 1016–2999 are reserved for IANA and must not be used in custom code.
Why am I seeing close code 1011?+
1011 (Internal Error) is the WebSocket equivalent of HTTP 500, the server encountered an unexpected condition and could not continue. Common causes: uncaught exception in your WebSocket handler, OOM, unhandled promise rejection, or a panic. Check the server logs for the underlying stack trace. Clients should reconnect with backoff; if you see 1011 repeatedly, your handler has a bug.
What is close code 1005 and why can't I send it?+
1005 (No Status Received) is a reserved synthetic code. It is never sent on the wire, the WebSocket library surfaces it to your application when the peer's close frame contained no status code at all. RFC 6455 explicitly forbids sending 1005 in a close frame. The same rule applies to 1006 (abnormal closure) and 1015 (TLS handshake failure), these are all internal-only signals.
How should my client handle different close codes?+
Use a small policy table: 1000 = do nothing; 1001/1012/1013 = reconnect with backoff ≥ 5s; 1006 = reconnect with exponential backoff starting at 1s; 1008/1003 = log and stop reconnecting (you have a bug); 1011 = reconnect with backoff and alert ops if it persists; 3000/3003 = re-authenticate first, then reconnect; 4xxx = follow your application's documented behaviour. Always cap reconnect attempts to avoid hot loops.
Related Tools & References
Need to actually test a WebSocket connection or decode why your peer is closing it? These tools pair well with this reference.