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.

Chrome 141 mode: LNA violations for WebSockets produce a console warning but the connection is not blocked. This is the transition period before enforcement.
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 ms
Browser 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

See also