Choose a core based on the server’s requirements, not just the client’s name. This guide is for users importing nodes, switching cores, or migrating JSON configurations. First, distinguish the client from the core; then check the protocol, transport, and security layer. Finally, use configuration checks and connection logs to troubleshoot. If a node specifies REALITY or xtls-rprx-vision, use an Xray runtime that supports those features. For standard nodes, check the specific fields and version as well.
Client vs. core: know which does what
v2rayN, v2rayNG, and v2flyNG are client apps. Managing server lists, importing subscriptions, toggling the system proxy, and changing UI settings are client-side tasks. The core handles configuration parsing, connections, routing rules, and traffic forwarding. Seeing an option in the client doesn’t mean the currently running core supports it.
On Android, v2rayNG uses the Xray core, while v2flyNG uses the V2Fly core. For desktop v2rayN, check the version, node type, and runtime logs to identify the core in use; don’t infer it from the desktop shortcut alone. When troubleshooting, note the client and core versions separately—they’re not the same thing.
- Subscription import fails: Check the subscription content and the client’s parsing support first. The core may not have started yet.
- Core fails to start: Check the generated configuration, field types, port conflicts, and core feature support.
- Core starts but connections fail: Check the server settings, handshake logs, and actual network path.
Xray and V2Fly: a shared origin doesn’t guarantee compatibility
V2Fly is a community project that continues the development of V2Ray; its core program is commonly called V2Ray Core. Xray forked from the V2Ray codebase in 2020 and has since developed independently. The two share concepts such as inbounds, outbounds, routing, and DNS, but their features and configuration structures have diverged.
So, “both can proxy traffic” doesn’t mean you can swap one executable for the other. During migration, a matching protocol name only suggests that the first layer may correspond. It doesn’t guarantee that transport settings, security layers, routing expressions, or DNS configuration will also match.
| Comparison | Xray | V2Fly | What it means in practice |
|---|---|---|---|
| Project background | Developed as a fork of V2Ray | Community project continuing V2Ray | Core concepts are similar, but that doesn’t make every field interchangeable |
| Core protocols such as VMess | Corresponding implementations available | Corresponding implementations available | Still check the transport, security layer, and version |
| XTLS Vision | Supports the corresponding flow control | Not a drop-in replacement | Nodes using Vision require a compatible Xray core |
| REALITY | Supports the corresponding security layer | Cannot run Xray REALITY configurations directly | Renaming fields won’t make migration work |
| Configuration changes | Check Xray’s field and version requirements | Distinguish configuration systems such as V4 and V5 | Confirm the configuration format and loading method before migrating |
Takeaway: list node dependencies before deciding to switch cores
If your current nodes depend on REALITY or Vision, stick with Xray. Test a migration only if the server provider offers a connection option supported by the target core—don’t simply remove fields you don’t recognize.
XTLS Vision vs. REALITY: flow control vs. security layer
In common VLESS configurations, XTLS Vision is specified with flow: xtls-rprx-vision. It applies a specific handling path to eligible traffic; it isn’t a standalone subscription format or a speed boost you can add to any transport. If the server isn’t configured for the corresponding flow control, adding Vision on the client won’t make the connection compatible.
REALITY operates at the security layer and involves server authentication and related handshake parameters. Clients typically need the server name, public key, Short ID, and other details. The UI may label the key material Public key or use a name specific to a different version; don’t swap parameters just because the labels differ. Never enter the server’s private key in the client’s public key field.
VLESS + Vision + REALITY
- Protocol
- VLESS
- Transport
- TCP; called RAW in some versions
- Flow
xtls-rprx-vision- Security layer
- REALITY
- Key settings to check
- Server name, public key, Short ID
This shows how fields relate in a common setup; it isn’t a complete working configuration. Every value must match the server.
VMess + WebSocket + TLS
- Protocol
- VMess
- Transport
- WebSocket
- Example path
/ws- Security layer
- TLS
- Key settings to check
- UUID, Host, path, server name
The path is an example, not a replacement for the actual value in your subscription. Parameters for standard TLS and REALITY aren’t interchangeable.
- Vision isn’t REALITY: Vision can also be used with compatible TLS setups. Seeing Vision doesn’t tell you which security layer is in use.
- REALITY isn’t a port: Servers often use port 443, but the port alone doesn’t determine the protocol or security layer.
- VLESS isn’t Vision: Saying a core “supports VLESS” doesn’t prove it supports
xtls-rprx-vision. - Don’t assume WebSocket is interchangeable: Simply changing the Vision setup above to WebSocket doesn’t mean you can expect the same features or connection behavior.
Configuration compatibility: check four layers, don’t run a global replace
Share links, subscription text, data saved by the client, and JSON read by the core are different layers. Successfully importing a vless:// link only means the client parsed it. Check that the generated runtime configuration retains the flow control, security layer, and transport settings. Conversely, a complete JSON configuration may not be importable as a standard node link.
- Check the protocol layer: Confirm whether it’s VMess or VLESS, along with the user ID and authentication parameters. Older VMess configurations may use legacy compatibility settings; verify these against the server details and current implementation rather than copying fixed values from outdated guides.
- Check the transport layer: Confirm the type—TCP/RAW, WebSocket, or another option—and check fields such as path and Host. Names and configuration formats can change between versions, so don’t rely on UI labels alone.
- Check the security layer: Confirm whether it’s TLS, REALITY, or disabled. Check the server name, certificate verification, key material, and fingerprint requirements. Disabling certificate verification isn’t a general fix.
- Check the runtime setup: Compare inbound listen addresses, ports, routing tags, DNS, and file paths. Even with correct protocol handshake parameters, traffic may not route as expected if an outbound tag reference is invalid.
V2Fly’s V4 and V5 configuration systems also need to be treated separately. Having the same .json extension doesn’t guarantee the fields have the same structure. When migrating a full configuration, check its structure against the target core’s documentation. For everyday use, it’s usually easier to import a compatible link from the service provider and let the client generate the runtime configuration.
Validate the migration: test the local listener and remote handshake separately
When comparing cores, keep the server, network, and test target consistent, and record the parameters for each run. The values below are for a local comparison setup only—not client defaults or speed test results. The example uses port 10809 for a local HTTP proxy bound to the loopback address, so the test port isn’t exposed to the local network.
First check that the core can read the configuration
The following command-line checks require a client.json that the target core can read. The Xray example uses its command-line syntax; the V2Fly example uses the V5 command-line syntax. If your distribution differs, check the relevant program’s help output first. Configuration tests only verify that the file loads; they don’t prove the remote server is reachable.
# Check Xray configuration
xray run -test -config client.json
# Check V2Fly V5 command-line configuration
v2ray test -c client.json
Next, check whether requests reach the local proxy
After starting a test configuration, send a request through an explicit local proxy address. This example assumes port 10809 provides an HTTP proxy; don’t copy http:// if the inbound only supports SOCKS. You can replace the example target https://example.com/ with an HTTPS address you’ve confirmed is reachable.
curl --proxy http://127.0.0.1:10809 --connect-timeout 10 --max-time 30 -I https://example.com/
- Local connection refused: First check whether the core is running and listening on the correct port. Don’t immediately change the remote protocol.
- Remote connection times out: Check the server address, port, firewall, and network path. A timeout alone doesn’t prove the core is incompatible.
- Handshake or authentication error: Check the UUID, Flow, server name, public key, and Short ID one at a time. Avoid changing several settings at once.
- Request succeeds, but some sites fail: Check DNS, routing, and differences between target sites. A problem with one site doesn’t mean the whole protocol has failed.
Don’t run two configurations that both use port 10809. Stop the previous one before comparing, and keep the local port and test command consistent. Otherwise, a port conflict—or requests still going through the old process—can make a local setup issue look like a core difference.
Choosing a core: consider node features and maintenance costs
There’s no need to migrate a working configuration just because “the other core got an update.” Evaluate a new version based on its fixes, protocol support, and client compatibility. Before updating, record the current client and core versions and which nodes work. Keep a restorable copy of the configuration to make rollbacks much faster.
| Use case | Recommended choice | What to check |
|---|---|---|
| Node explicitly requires REALITY or Vision | Use a compatible Xray core | Check client support and the actual core version; keep all node parameters intact |
| Using an Xray-feature node on Android | Check v2rayNG compatibility | After importing, make sure the transport, security layer, and Flow are all present |
| Using a V2Fly configuration on Android | Check v2flyNG compatibility | Confirm the node features, configuration format, and built-in core support |
| Managing multiple nodes on desktop | Use v2rayN and check which core is running | Check the startup logs to see what actually loaded; don’t rely on the name in the list |
Bottom line: change one variable at a time
First, run a baseline test with the original node and core. Then test node combinations supported by the target core. Don’t change the subscription, DNS, routing, and transport all at once, or it’ll be hard to tell which layer caused a failure.
Common pitfalls: distinguish successful imports, startup, and connections
Why won’t a node imported from v2rayNG connect in v2flyNG?
First check whether the node uses REALITY or Vision. A link appearing in the UI doesn’t mean the V2Fly core implements those features. If it’s a standard node, check the transport, security layer, and authentication parameters. You’ll need a compatible option from the server provider—not to remove feature-specific fields and keep trying.
Is Xray always faster than V2Fly?
You can’t assume that. Throughput and latency also depend on server load, round-trip time, packet loss, device performance, and transport. Vision’s handling has specific requirements; one speed test can’t establish a rule for every network. Test repeatedly under consistent conditions and watch for connection errors too.
Why can’t I switch protocols if the domain and port 443 are the same?
A domain and port are just the connection entry point. The server behind them may use a specific protocol, security layer, or forwarding rule. Whether the client uses VMess, VLESS, TLS, or REALITY, the server must be configured for it. The same port doesn’t mean the handshake works the same way.
What should I remove before sharing logs for troubleshooting?
Keep the client and core versions, error type, timestamp, and relevant field names. Redact subscription URLs, UUIDs, private keys, and other credentials. Full subscription URLs may contain access tokens, so don’t post them publicly. Sharing only the log lines relevant to the issue makes troubleshooting easier.