demo · v142 · network
WebSocket Upgrade Tester
Test how Chrome’s Local Network Access policy treats WebSocket connections to loopback, private-range, and public targets. Toggle between Chrome 141 (warnings only) and Chrome 142 (enforced blocking) to see the enforcement change.
ws://127.0.0.1:8080
Loopback
Connects to a local WebSocket server on the loopback address. Typical for dev tools, hot-reload servers, and local agents. Requires LNA headers in Chrome 142+.
Idle
ws://192.168.1.100:3000
Private network
Connects to a device on the local LAN (e.g. an IoT device or home router). Class C private range. Blocked by Chrome 142 LNA enforcement without proper preflight response.
Idle
wss://echo.websocket.org
Public / WAN
Public WebSocket echo server over TLS. No LNA restrictions apply — this is a public address. Connection proceeds normally.
Idle
Required HTTP 101 response headers
For a local WebSocket server to pass the LNA preflight, the OPTIONS preflight response (and optionally the 101 Upgrade response) must include:
| Header | Value | Required? | Notes |
|---|---|---|---|
| Access-Control-Allow-Private-Network | true |
Required | Must be present in OPTIONS preflight response. Core LNA header. |
| Access-Control-Allow-Origin | https://your-site.example.com |
Required | Must match the page origin. Wildcards disallowed with credentials. |
| Access-Control-Allow-Methods | GET |
Required | WebSocket upgrade uses GET; include it in the allowed methods list. |
| Access-Control-Allow-Headers | Upgrade, Connection, Sec-WebSocket-Key, Sec-WebSocket-Version |
Recommended | Explicitly allow the WebSocket upgrade headers. |
| Access-Control-Max-Age | 600 |
Recommended | Cache the preflight for 10 min to avoid a round-trip on every reconnect. |
# Minimal local WebSocket server response (OPTIONS preflight)
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://your-public-site.example.com
Access-Control-Allow-Private-Network: true
Access-Control-Allow-Methods: GET
Access-Control-Allow-Headers: Upgrade, Connection, Sec-WebSocket-Key, Sec-WebSocket-Version
Access-Control-Max-Age: 600
WebSocket handshake with LNA preflight
Click a test target above to animate this timeline.
1. Page initiates
new WebSocket("ws://...")~0 msBrowser detects target is a private/local address. Chrome 142 pauses and starts an LNA preflight.
2. Browser sends OPTIONS preflight+round-trip (LAN: ~1–5 ms, loopback: <1 ms)
Headers include
Access-Control-Request-Private-Network: true, Access-Control-Request-Method: GET, and the page origin.3. Server responds 204 with LNA headers+server processing
Server must reply with
Access-Control-Allow-Private-Network: true. If absent or status is not 2xx, Chrome blocks and fires an error event on the WebSocket.4. Browser sends WebSocket upgrade (GET + Upgrade: websocket)+round-trip
Now that LNA preflight passed, the real HTTP/1.1 101 Switching Protocols handshake proceeds normally.
5. Server replies 101 Switching Protocols
Connection is open. Subsequent frames are not subject to further LNA checks.
Total overhead vs direct connect: typically 1–8 ms (LAN) or <1 ms (loopback). Cached preflights (
Access-Control-Max-Age) skip steps 2–3 on reconnects within the TTL window.
Enforcement timeline
Chrome 130 (2024): LNA preflight for fetch/XHR — warning-only period begins
Chrome 133 (2025): LNA for fetch/XHR — enforcement begins
Chrome 141 (2025): LNA extended to WebSockets — WARNING only
(connection still succeeds; console shows deprecation warning)
Chrome 142 (2025): LNA for WebSockets — ENFORCED
(connection blocked if preflight absent or fails)
# To check at runtime:
// Your WS server logs will show the OPTIONS preflight before the GET upgrade
// Chrome DevTools → Network tab → filter by WS → look for the OPTIONS request