Upgrading from WebSocket to XHTTP Transport
Chapters
In chapter 3, we built a fully functional VLESS + WebSocket + TLS + CDN proxy. That setup works well — but the underlying transport protocol is now living on borrowed time. This chapter walks you through upgrading from WebSocket to XHTTP, the transport layer that Xray officially recommends going forward.
Why Move Away from WebSocket
Starting in 2026, Xray has officially deprecated WebSocket as a transport protocol. If you run your current config, you'll see this warning on startup:
You can check whether your config triggers this warning by running:
The message is clear: WebSocket support will be removed in a future release. Migrating now means you control the timeline, rather than scrambling when a breaking update drops.
XHTTP vs WebSocket at a Glance
| Dimension | WebSocket | XHTTP |
|---|---|---|
| Protocol basis | HTTP/1.1 Upgrade handshake | Standard HTTP POST/GET streaming |
| Connection model | Single long-lived full-duplex connection | Multiplexed, standard HTTP semantics |
| CDN compatibility | Requires explicit CDN support for WS | Natively compatible (plain HTTP requests) |
| Detection risk | Upgrade handshake is a distinct fingerprint | Indistinguishable from normal web traffic |
| Nginx configuration | Requires Upgrade/Connection headers | Standard reverse proxy — nothing special |
| Performance | Good | Better (reduced handshake overhead) |
| Client support | All clients | v2rayN, v2rayNG, sing-box — not Clash |
| Xray status | Deprecated | Officially recommended |
Core Advantages of XHTTP
Better stealth
WebSocket has a recognizable fingerprint: the Connection: Upgrade and Upgrade: websocket headers are trivial for DPI systems to flag. XHTTP uses standard HTTP requests — your proxy traffic looks identical to someone browsing a website.
Superior CDN compatibility
WebSocket requires CDNs to explicitly support persistent connections (Cloudflare's free tier imposes connection count and duration limits). XHTTP is just HTTP — any CDN that handles regular web traffic will pass it through without special configuration.
Simpler server configuration
Nginx no longer needs to handle WebSocket upgrade logic. A plain HTTP reverse proxy block is all you need, which means fewer moving parts and fewer things that can break.
Client compatibility note: As of May 2026, Clash Verge Rev (mihomo core) does not support XHTTP. If you rely on Clash-based clients, you'll need to keep a WebSocket inbound running alongside XHTTP. v2rayN, v2rayNG, and sing-box all have full XHTTP support.
Migration Steps
If you already have the chapter 3 WebSocket deployment running, the migration requires exactly three changes.
Step 1 — Update the Xray Config
Change the streamSettings section from:
To:
That's two substitutions:
"network": "ws"becomes"network": "xhttp""wsSettings"becomes"xhttpSettings"
The path stays the same.
Step 2 — Update the Nginx Config
Change the proxy location block from:
To:
Here's what changed and why:
| Change | Reason |
|---|---|
Remove Upgrade and Connection headers | XHTTP doesn't use WebSocket upgrade — these headers are unnecessary |
Add proxy_buffering off | XHTTP uses streaming; Nginx must not buffer the response or data will stall |
Step 3 — Restart Services
Verify that Xray starts cleanly:
If the output shows Configuration OK. with no deprecated warning, you're done on the server side.
Client Configuration
v2rayN Share Link
Import directly by pasting this link format into v2rayN (Server → Import bulk URLs from clipboard):
Manual Configuration Reference
| Parameter | Value |
|---|---|
| Address | proxy.example.com |
| Port | 443 |
| UUID | Your UUID |
| Encryption | none |
| Transport | xhttp |
| Path | /your-random-path |
| TLS | Enabled |
| SNI | proxy.example.com |
| Skip cert verification | No |
v2rayNG on Android
Same as v2rayN — import the share link directly.
Running WebSocket and XHTTP Side by Side
If some of your devices use Clash-based clients that don't support XHTTP yet, you can run both transports simultaneously. Define two inbounds in your Xray config on different ports with different paths:
Then add a separate Nginx location block for each path — the XHTTP block uses proxy_buffering off, and the WebSocket block uses the Upgrade/Connection headers as before.
This dual-inbound approach lets you migrate clients incrementally. Once Clash adds XHTTP support, you can remove the WebSocket inbound entirely.
Verifying the Migration
If all three checks pass, your migration is complete.
Fresh XHTTP Setup from Scratch
If you're starting here without a chapter 3 WebSocket deployment, here's the complete configuration for a VLESS + XHTTP + TLS + CDN setup.
Complete Xray Configuration
Complete Nginx Configuration
Replace YOUR-UUID with a freshly generated UUID (xray uuid), /your-random-path with a random string (e.g., /a8f3k2m9), and proxy.example.com with your actual domain.
Summary of Changes
| Component | What Changed |
|---|---|
| Xray config | ws to xhttp, wsSettings to xhttpSettings |
| Nginx | Remove WebSocket upgrade headers, add proxy_buffering off |
| Client | Import XHTTP share link in v2rayN |
After migration you gain:
- No more deprecation warnings from Xray
- Traffic that looks like ordinary HTTP (no WebSocket upgrade fingerprint)
- A cleaner, simpler Nginx configuration
- Guaranteed compatibility with future Xray releases
What Comes Next
Chapters 5 and 6 explore a fundamentally different approach: VLESS + Reality. Instead of relying on your own TLS certificate and a CDN, Reality borrows the TLS certificate of a major website (like microsoft.com) to create a virtually undetectable proxy. Chapter 5 covers the theory — how Reality's handshake works and why censors can't distinguish it from legitimate traffic. Chapter 6 provides the complete deployment guide.