Guides, Nov 10, 2026

# What the real delay test measures, and why it shows -1

The real delay test starts the proxy with one server's config, sends a small HTTP request through it to a test URL, and shows how long the answer took. A number means a request went out through the server and came back. A -1 is not a time: it means no good answer arrived within the app's limit, and it doesn't say which step failed.

Tahir Mehmood, 10 min read

Every V2Ray client has a button that tests a server and prints a number in milliseconds. Sometimes it prints -1 instead, and the server may or may not be broken. This post explains what each test really does, why the number and the -1 mean what they mean, and how to tell a dead server from a bad test.

I read the test code in the current releases on 11 November 2026: v2rayN 7.25.6, v2rayNG 2.3.15 (with the AndroidLibXrayLite library it pins), Hiddify 5.5.5, NekoBox for Android 1.4.2 and sing-box 1.14.4. Labels and defaults change between versions, so check your own settings if yours is older or newer.

## What is the real delay test in v2rayN and v2rayNG?

It is a test that uses the proxy itself. The app starts its core with that one server's settings and fetches a test URL through it, so the number covers the whole path: your device, the server, the test site and back.

In v2rayNG the menu item is **Test real delays** (测试真连接延迟 in Chinese). For each server, version 2.3.15 does this:

1.  For TCP-based configs, it first opens a plain TCP connection to the server's host and port with a 1 second limit. If that fails, the result is -1 and nothing else runs. Hysteria2, WireGuard and configs with an `h3` ALPN skip this step.
2.  It builds a test config from the server's settings and starts the Xray core with it.
3.  It sends a GET request to the **Real delay test URL** through the core, twice, with a 12 second limit, and keeps the faster of the two.
4.  Only an HTTP 200 or 204 reply counts. Anything else is a failure.

v2rayNG runs these for many servers at once. The setting is **Concurrent real-delay tests**, and the default is 16.

In v2rayN the item is **Test real delay** (测试真连接延迟 (多选), because it works on the servers you select). It starts a core for each server with a local SOCKS port, then sends two GET requests to the **Speed Ping Test URL**, 100 ms apart. Both have to finish within 5 seconds in total, and the faster one is the result.

Hiddify and NekoBox have the same idea under other names. Hiddify's proxy list has **Test delay**, and NekoBox has **URL Test** next to TCPing and ICMPing.

| App and version | Tests it offers | Default test URL | A failed test shows |
| --- | --- | --- | --- |
| v2rayN 7.25.6 | Test tcping, Test real delay, Test download speed, Test Configurations UDP Delay | `https://www.google.com/generate_204` | `-1` |
| v2rayNG 2.3.15 | Test TCP delays (TCPing), Test real delays | `https://www.gstatic.com/generate_204` | `-1 ms` in red |
| Hiddify 5.5.5 | Test delay | `http://captive.apple.com/hotspot-detect.html` | A red cross; labels such as "Delay test timeout" and "Not responding" |
| NekoBox for Android 1.4.2 | TCPing, ICMPing, URL Test | `http://cp.cloudflare.com/` | The reason, such as Timeout, Connection refused or Unreachable |

## How is it different from a ping or TCP test?

A TCP test (TCPing) only opens a connection to the server's port and closes it. ICMPing sends an ordinary ping to the host. Neither speaks the proxy protocol, so both pass when the UUID is wrong, the user was deleted, or the REALITY key changed.

| Test | What a pass proves | What it can't see |
| --- | --- | --- |
| ICMPing | The host answers ping | Whether the port is open; many servers drop ping anyway |
| TCPing | The port accepts a TCP connection | The TLS or REALITY handshake, the user, the transport, traffic |
| Real delay or URL test | One HTTP request went through the proxy and came back | Your routing rules and DNS settings, UDP, large transfers |

The real delay number is also not a ping time, so don't compare it with TCPing. It includes the proxy handshake and a full HTTP exchange with the test site, often over TLS. Several times the TCPing value is normal.

One more detail explains why the number can look better than it feels. v2rayN and v2rayNG send two requests and keep the faster one, and the second request can reuse the connection the first one opened. So the figure you see often leaves out the cost of setting up a new connection. For comparison, sing-box's own `urltest` sends a single HEAD request, and on a multiplexed outbound it opens the session with one request before the timed one.

## Which test URL should I use, and does it matter?

Use a small address that answers with 204 or a tiny page and is served from many places, such as one of the `generate_204` URLs your app already lists. The choice changes the number a lot and the pass or fail result only a little.

The request leaves from the server, not from you. So what matters is whether the server can reach the test site quickly. A test URL hosted far from the server adds that distance to every result, and it can make a good server look slow.

Two differences between the apps are worth knowing:

-   **Status codes.** v2rayNG only accepts 200 or 204. v2rayN 7.25.6 doesn't check the status at all: any HTTP reply counts. If the test site answers your server's IP address with an error page, v2rayNG shows -1 and v2rayN shows a time.
-   **http or https.** An `https://` test URL adds a TLS handshake with the test site to the time. Hiddify and NekoBox default to plain `http://` addresses, which is one reason their numbers can be lower for the same server.

Where to change it:

| App | Setting |
| --- | --- |
| v2rayN | Speed Ping Test URL, in the option settings |
| v2rayNG | Real delay test URL, in Settings |
| Hiddify | Connection test URL, under Settings, General |
| NekoBox | Connection Test URL, in the settings |

If you compare servers, keep the same URL for all of them. If you compare apps, set them to the same URL first.

## Why does the test show -1 or a timeout?

\-1 is the value the app stores when it got no acceptable answer in time. It says the test failed, but not where. Work it out from the steps the test takes.

In rough order of how often I see them:

1.  **The TCP pre-check failed (v2rayNG).** The host doesn't resolve, the port is closed or filtered, or the connection simply took longer than 1 second. On a slow mobile network a distant server can fail here while still being usable.
2.  **The proxy handshake failed.** The UUID or password is wrong, the user was removed or reached its quota or expiry date on the panel, the REALITY public key or short ID changed, or the `flow` or transport settings don't match the server. The [VLESS key checker guide](https://tunnelhq.com/blog/how-to-check-vless-key/) lists the server log lines that tell these apart.
3.  **The core couldn't load the config.** The link has a field your app's core version doesn't accept, so the proxy never starts and the result is -1. Updating the app, or fixing the link, is the only cure.
4.  **The server can't reach the test URL.** Its DNS is broken, or a firewall blocks outgoing traffic. The handshake works, and the test still fails.
5.  **It was too slow.** v2rayN gives both requests 5 seconds together. A server that answers in 6 seconds gets -1 in v2rayN and a time in v2rayNG, which allows 12.
6.  **The test site returned an error status** (v2rayNG only, as above).

A quick way to narrow it down: run TCPing on the same server. If TCPing fails too, the problem is the network path or the port. If TCPing passes and real delay shows -1, the problem is the protocol settings or the server's own outgoing connection. For REALITY servers, [why REALITY stops working](https://tunnelhq.com/blog/xray-reality-not-working/) walks through the usual causes.

If many servers show -1 only when you test them all together, and pass one at a time, lower the number of parallel tests. On a weak phone or a busy network, 16 at once can be too many.

Be careful with the cleanup buttons. v2rayNG has **Delete invalid configs** and v2rayN has **Remove invalid by test results**, and both remove every server whose last result was a failure. v2rayNG's own setting to do this automatically warns: "Test results may not be accurate; deleted config cannot be recovered."

## Why does real delay pass but sites still don't load?

Because the test proves one small request to one address worked at one moment. Normal browsing uses parts of the setup the test leaves out.

-   **Routing and DNS.** v2rayNG builds a separate config for the test: it removes the routing rules, the DNS and FakeDNS settings, and mux. So a pass says nothing about those. If sites fail while the test passes, look at your routing rules and DNS server first.
-   **UDP.** The test is HTTP over TCP. Calls, games and QUIC need UDP through the proxy. v2rayN has a separate **Test Configurations UDP Delay** for this.
-   **Large transfers.** A 204 reply fits in a few packets. Pages that stall after they start loading often point to an MTU problem or a throttled link. A download speed test shows this better.
-   **Blocked sites.** Some sites refuse traffic from the server's IP address. The test site answers, and the site you want doesn't.
-   **Time.** The result is a snapshot. A server can pass at 9:00 and fail at 9:05.

## How do I test a key without a client app?

Run the core yourself and send a request through it with curl, or paste the key into an online tester. Both give you a second opinion that doesn't depend on your app's test code.

With Xray-core, write the link's fields into a client config with a local SOCKS inbound on port 10808 (the [VLESS key checker guide](https://tunnelhq.com/blog/how-to-check-vless-key/) has a full example), start it, and run:

```
./xray run -test -c client.json
./xray run -c client.json
# in a second terminal:
curl -sS -o /dev/null -w '%{http_code} %{time_total}s\n' \
  -x socks5h://127.0.0.1:10808 https://www.gstatic.com/generate_204
```

`204` and a time means the key works. curl prints the status code, so you see exactly what v2rayN would have hidden.

The other way is the [TunnelHQ tester](https://tunnelhq.com/test/). Paste the share link, and one of our checkers runs the real handshake and then sends HTTP requests through the tunnel to a few well-known addresses. The result shows **Connect time**, how long the tunnel took to come up, and **Latency**, one round trip through it. It's free for 5 tests every 24 hours, with no sign-up.

The tester runs from TunnelHQ's network, not yours, and that is useful in itself. If the tester passes and your app shows -1, the server is fine and the problem is between you and it. If both fail, look at the server.

From a terminal, the [thq CLI](https://tunnelhq.com/docs/cli/) runs the same check and prints the same numbers as JSON:

```
thq test 'vless://<uuid>@vpn.example.com:443?security=reality&...' --json
```

The JSON has `status`, `latency_ms`, `connect_ms` and, on a failure, `error_message`. The CLI exits with 1 when the test fails, so you can use it in a script.

## How do I get told when the delay test would fail?

Run the same kind of test on a schedule from outside your network, and alert after a couple of failures in a row, not on the first one. A test you press by hand only tells you about the moment you pressed it.

That is what a TunnelHQ monitor does. Each check runs the real handshake and sends traffic through the tunnel, every 5, 2 or 1 minutes depending on the plan. By default a monitor is marked **Down** after 2 failed checks in a row, and the alert goes to your channels. On Pro and Business you can [pin a monitor to countries](https://tunnelhq.com/docs/concepts/regions/), which helps when a server works from one place and is blocked from another. [VLESS monitoring](https://tunnelhq.com/vless-monitoring/) explains the check, and every plan starts with a 14-day free trial.

If your servers reach users through a subscription URL, test every entry in it, not just one. [How to test every server in a V2Ray subscription](https://tunnelhq.com/blog/test-every-server-in-a-subscription/) covers that.

Source: https://tunnelhq.com/blog/v2ray-real-delay-test/
