Paste a wss:// or ws:// address, press Connect and this tester opens a real WebSocket from your own browser. Type a message, send it, and every outgoing and incoming frame lands in a timestamped log. When the socket ends you see the close code, the reason and whether the closing handshake finished cleanly.
| Value | Constant | Meaning |
|---|---|---|
| 0 | CONNECTING | Created, handshake not finished yet |
| 1 | OPEN | Ready: send() works now |
| 2 | CLOSING | The closing handshake has started |
| 3 | CLOSED | Closed, or the connection never opened |
Updated
Nothing here goes through our servers. The connection is opened by the WebSocket object built into the browser tab you are reading this in, so the server sees your browser, your IP address and this page's origin, https://we.inc. A server that checks the Origin header may refuse it. Because this page is served over https, prefer a wss:// address; a plain ws:// one can be blocked by the browser as insecure.
The tester runs in this browser tab. Your messages travel only between your browser and the server address you enter.
The 1000 to 1015 range is defined for the protocol itself. 3000 to 3999 is registered with IANA for libraries and frameworks, and 4000 to 4999 is free for private use between your own client and server.
| Code | Name | What it usually means |
|---|---|---|
| 1000 | Normal Closure | The work is done and the socket was closed on purpose |
| 1001 | Going Away | The server is shutting down or the page navigated away |
| 1002 | Protocol error | One side broke the framing rules |
| 1003 | Unsupported Data | Data of a type the endpoint cannot accept, such as binary to a text-only server |
| 1005 | No Status Received | Reserved: a close frame arrived with no code in it |
| 1006 | Abnormal Closure | Reserved: no close frame at all, often a failed handshake or dropped network |
| 1007 | Invalid frame payload data | A message had inconsistent data, for example text that is not UTF-8 |
| 1008 | Policy Violation | A generic refusal when 1003 and 1009 do not fit |
| 1009 | Message Too Big | A frame was larger than the endpoint accepts |
| 1010 | Mandatory Ext. | The client wanted an extension the server did not agree to |
| 1011 | Internal Error | The server hit an unexpected condition |
| 1012 | Service Restart | The server is restarting |
| 1013 | Try Again Later | A temporary condition such as overload |
| 1014 | Bad Gateway | A proxy got an invalid answer from the upstream server |
| 1015 | TLS handshake | Reserved: the TLS handshake failed, for example an untrusted certificate |
| 3000 to 3999 | Registered | Defined by libraries and frameworks |
| 4000 to 4999 | Private use | Whatever your client and server agree on |
This is what the tester does under the hood: open, log every message, and report the close code.
const socket = new WebSocket("wss://echo.example.com/socket");
socket.addEventListener("open", () => {
socket.send(JSON.stringify({ type: "hello" }));
});
socket.addEventListener("message", (event) => {
console.log("received", event.data);
});
socket.addEventListener("close", (event) => {
console.log("closed", event.code, event.reason, event.wasClean);
});
// later: end with a normal closure and a short reason
// socket.close(1000, "done");
The browser sends an ordinary HTTP request carrying Upgrade: websocket, a random Sec-WebSocket-Key and an Origin header. A willing server answers with status 101 Switching Protocols and a Sec-WebSocket-Accept value derived from that key. From then on the same TCP connection carries frames in both directions.
Every attempt ends with either an open event or a close event. If you see close without open, the upgrade never succeeded, which narrows the fault to the address, the network or the server's handshake rules.
The close entry in the log carries three things. code is the number from the table below. reason is any text the other side sent, often empty. wasClean is true only when both sides exchanged close frames, so false usually means the network dropped or the server crashed.
The usual cause is an origin check. Your app connects from its own origin, while this page connects from https://we.inc. If the server only accepts listed origins, it rejects the handshake and the browser reports close code 1006. The other thing to try is the wss:// form of the address, since this page itself is served over https.
No. The page only creates a socket in your tab and writes to a log in memory. Messages go directly between your browser and the server you typed. Reloading the page clears the log.
Not from a browser. The WebSocket constructor takes only a URL and an optional list of sub-protocols. Servers that need a token usually read it from a query string, a cookie or the first message after the connection opens.
The browser WebSocket interface has only send() and close() as methods. Ping and pong are control frames that the browser answers on its own when a server pings it, so page scripts never see them. Send a normal text message if your server uses an application-level heartbeat.
Scripts may only pass 1000 or a code from 3000 to 4999 to close(). Any other number throws an InvalidAccessError. Codes in the 1001 to 1015 range are set by browsers and servers themselves.
Related: WebSocket server in Node.js, FastAPI WebSocket guide, CORS explained, HTTP status codes, localhost:3000 explained.
Start for free or see all free tools. We.Inc is free to start, with no card needed. AI building is on paid plans from $20 a month.
We.Inc is an AI-powered website builder you can resell under your own brand. Launch a branded client dashboard, bill on Stripe Connect, and deliver AI-generated websites in minutes. White-label plans start at $99 a month for 25 client sites, with a 7-day free trial and no per-site fees.