How does the WebSocket close handshake and status codes work?
Understand the WebSocket close handshake: the Close frame, status codes like 1000, 1001, and 1006, and how peers shut a connection down cleanly.
Expected Interview Answer
The WebSocket close handshake is a graceful, two-way shutdown: one peer sends a Close control frame (opcode 0x8) carrying an optional status code and reason, the other replies with its own Close frame, and then the underlying TCP connection is torn down.
The status code is a two-byte big-endian integer at the start of the Close frame's payload, optionally followed by a UTF-8 reason. Common codes include 1000 (normal closure), 1001 (going away), 1002 (protocol error), 1003 (unacceptable data type), 1008 (policy violation), 1009 (message too big), and 1011 (unexpected server condition). Codes 1005 and 1006 are reserved and must never be sent on the wire — they signal 'no status received' and 'abnormal closure' locally when the connection dropped without a proper handshake. After sending Close a peer must not send more data frames but should still read until it receives the peer's Close.
- Signals why a connection ended, aiding debugging
- Lets both peers flush and shut down cleanly
- Distinguishes normal closure from protocol errors
- Enables clients to decide whether to reconnect
- Prevents half-open connections from lingering
AI Mentor Explanation
The close handshake is like the two captains agreeing to declare an innings rather than one side simply walking off. The declaring captain signals the umpire with a clear reason — a Close frame with a status code — and play only truly ends once the other side acknowledges and the umpires confirm. Code 1000 is a clean, agreed declaration; code 1006 is like both teams vanishing when the floodlights fail with no signal at all, an abnormal end nobody announced, leaving the scorers to record that the match simply stopped.
Step-by-Step Explanation
Step 1
Initiate closure
One peer sends a Close control frame (opcode 0x8) with an optional 2-byte status code and UTF-8 reason.
Step 2
Stop sending data
After sending Close, that peer must not send further data frames but keeps reading incoming ones.
Step 3
Acknowledge
The other peer responds with its own Close frame, echoing an appropriate status code.
Step 4
Tear down TCP
Once both Close frames are exchanged, the underlying TCP connection is closed.
Step 5
Handle abnormal drops
If TCP dies without a Close frame, the local endpoint reports 1006 (abnormal) or 1005 (no status) — never sent on the wire.
What Interviewer Expects
- Close is a two-way handshake, not a unilateral disconnect
- Knowledge of opcode 0x8 and the 2-byte status code format
- Meaning of common codes: 1000, 1001, 1002, 1008, 1009, 1011
- That 1005 and 1006 are reserved and never sent on the wire
- Behaviour after sending Close (stop data, keep reading)
Common Mistakes
- Thinking closing is one-sided with no acknowledgement
- Sending 1005 or 1006 explicitly in a Close frame
- Confusing normal closure (1000) with going away (1001)
- Sending data frames after the Close frame
- Ignoring the reason string's UTF-8 requirement
Best Answer (HR Friendly)
“Closing a WebSocket is like both sides agreeing to hang up rather than one just dropping the call. One side sends a 'closing' message with a numeric code explaining why — for example a normal end or an error — and the other side confirms before the connection is fully shut. If the line simply dies without that exchange, the app records it as an abnormal disconnect.”
Code Example
const ws = new WebSocket('wss://example.com/stream')
// Gracefully close with a normal-closure code and reason
function shutdown() {
ws.close(1000, 'client finished')
}
ws.onclose = (event) => {
console.log('code:', event.code) // e.g. 1000
console.log('reason:', event.reason) // 'client finished'
console.log('clean:', event.wasClean) // false if 1006 abnormal drop
if (!event.wasClean) scheduleReconnect()
}Follow-up Questions
- What is the difference between status codes 1005 and 1006?
- Why must a peer keep reading after sending a Close frame?
- What does the wasClean flag on the close event indicate?
- Which status code fits a server restart or shutdown?
- How is the status code encoded within the Close frame payload?
MCQ Practice
1. Which status code indicates a normal, intentional closure?
1000 means normal closure — the purpose the connection was established for has been fulfilled.
2. Which code must NEVER be sent explicitly in a Close frame?
1006 is reserved to indicate an abnormal closure detected locally; it cannot be set as an actual on-the-wire status code.
3. After sending a Close frame, what should a peer do?
The peer must stop sending data frames yet continue reading so it receives and processes the other side's Close frame.
Flash Cards
What opcode marks a Close control frame? — 0x8 — it carries an optional 2-byte status code and UTF-8 reason.
Meaning of code 1001? — Going away — e.g. a server shutting down or a browser navigating away from the page.
Why are 1005 and 1006 special? — They are reserved for local reporting (no status / abnormal closure) and must never be sent on the wire.
What must a peer do after sending Close? — Stop sending data frames but keep reading until it receives the peer's Close frame, then close TCP.
Continue Learning
Related Interview Questions
What are WebSocket frames and how does message framing work?
medium
How do you test a WebSocket application?
medium
What are the trade-offs of using WebSockets versus polling for real-time updates?
medium
How does WebSocket message fragmentation work, and why can a control frame appear in the middle of a message?
hard