Find a file
2026-09-03 11:38:00 +03:00
.github ci: refetch the annotated tag before reading its body 2026-08-11 19:17:03 +03:00
docs docs: rewrite the READMEs as a step-by-step guide and move the rest into docs/ 2026-09-03 11:38:00 +03:00
.dockerignore feat: add Dockerfile with UPX-compressed scratch image 2026-07-20 13:01:04 +03:00
.gitignore chore: ignore account and report files 2026-07-19 16:45:44 +03:00
argv.go fix: strip the path termux-exec injects into argv on Android 2026-08-11 11:43:14 +03:00
argv_android.go fix: strip the path termux-exec injects into argv on Android 2026-08-11 11:43:14 +03:00
argv_other.go fix: strip the path termux-exec injects into argv on Android 2026-08-11 11:43:14 +03:00
bind.go perf: give every wg tunnel the batch-1 bind, not conn.NewDefaultBind 2026-08-11 18:42:14 +03:00
bind_linux.go docs: drop comments that restate the code 2026-07-27 16:42:01 +03:00
bind_other.go feat: route -I/-interface through the interface via SO_BINDTODEVICE 2026-07-23 15:38:26 +03:00
cli.go fix: cap the Go runtime at 32MiB so a full scan is not OOM-killed 2026-08-11 17:47:36 +03:00
console_other.go fix: use ASCII status glyphs and spinner on Windows 2026-08-04 11:54:46 +03:00
console_windows.go fix: use ASCII status glyphs and spinner on Windows 2026-08-04 11:54:46 +03:00
discovery.go fix: drop host ping replies that came from another endpoint 2026-08-13 13:45:35 +03:00
dns_android.go fix: resolve DNS on Android, where there is no /etc/resolv.conf 2026-08-11 15:49:12 +03:00
Dockerfile ci: bump the Docker build image to go 1.26 2026-08-08 16:05:07 +03:00
findjunk.go feat: add find-sni to search a MASQUE SNI that gets through 2026-08-06 16:33:39 +03:00
findsni.go feat: let find-sni search an SNI for either MASQUE transport 2026-08-08 15:43:52 +03:00
flags.go feat: add -ping-target to aim the in-tunnel ping 2026-08-31 11:57:52 +03:00
geo.go feat: read the exit region and node location from a single /meta fetch 2026-07-30 14:20:27 +03:00
go.mod feat: add -p masque-h2, CONNECT-IP over TCP with real endpoint pools (closes #3) 2026-08-08 15:27:49 +03:00
go.sum feat: add -p masque-h2, CONNECT-IP over TCP with real endpoint pools (closes #3) 2026-08-08 15:27:49 +03:00
i1gen.go feat: generate the awg init packet with -gen-i1 2026-07-25 17:29:22 +03:00
i1gen_test.go docs: drop comments that restate the code 2026-07-27 16:42:01 +03:00
install.sh feat: print the macOS quarantine hint in install.sh 2026-08-11 11:44:51 +03:00
LICENSE chore: add license 2026-07-21 13:38:38 +03:00
main.go fix: fall back to plain output when the live TUI cannot start (closes #16) 2026-08-31 12:12:18 +03:00
masque.go feat: add scan -through to nest one WARP tunnel inside another 2026-08-09 16:44:49 +03:00
meta.go feat: read the exit region and node location from a single /meta fetch 2026-07-30 14:20:27 +03:00
nest.go feat: render the whole chain in the mihomo config under -through 2026-08-09 18:18:52 +03:00
pools.go feat: add -p masque-h2, CONNECT-IP over TCP with real endpoint pools (closes #3) 2026-08-08 15:27:49 +03:00
quic.go docs: drop comments that restate the code 2026-07-27 16:42:01 +03:00
README.md docs: rewrite the READMEs as a step-by-step guide and move the rest into docs/ 2026-09-03 11:38:00 +03:00
README_RU.md docs: rewrite the READMEs as a step-by-step guide and move the rest into docs/ 2026-09-03 11:38:00 +03:00
register.go fix: stop register from overwriting an account file it could not read (closes #5) 2026-08-13 11:28:36 +03:00
report.go feat: add -ping-target to aim the in-tunnel ping 2026-08-31 11:57:52 +03:00
socks.go fix: stop repeating the country in the socks exit row 2026-08-11 11:11:47 +03:00
tui.go feat: print scan progress in plain output mode 2026-08-13 16:11:06 +03:00
tui_test.go feat: print scan progress in plain output mode 2026-08-13 16:11:06 +03:00
tunnel.go feat: add -ping-target to aim the in-tunnel ping 2026-08-31 11:57:52 +03:00
ui.go feat: keep colour in the console tables when CLICOLOR_FORCE is set 2026-07-30 15:57:07 +03:00
version.go fix: cache the latest-version answer in the temp dir, not on flash 2026-08-13 12:11:05 +03:00
warp.go feat: add -sweep-ports to probe every port of an endpoint (closes #15) 2026-08-31 11:57:52 +03:00
warp_test.go feat: add -sweep-ports to probe every port of an endpoint (closes #15) 2026-08-31 11:57:52 +03:00
wgconf.go feat: add -conf-type mihomo-json 2026-08-29 20:50:46 +03:00
workers.go perf: probe phase 1 addresses in parallel instead of one at a time 2026-08-11 18:57:07 +03:00

WARPSCOUT

WARPSCOUT multi-node

Find Cloudflare WARP endpoints that work from your network, and see where they exit.

GitHub Release Build Status Tests GitHub Downloads Docker Pulls License: MIT

Documentation: 🇬🇧 English · 🇷🇺 Русский

Contents

What it is

Cloudflare WARP has thousands of endpoint addresses, and the one you connect to decides which Cloudflare edge node (colo) your tunnel lands on. That matters: since April 2026 traffic through the Moscow node DME is filtered by DPI, and some sites simply do not open through it even though WARP itself connects fine. The same config pointed at an endpoint on a foreign node works without that problem.

The official WARP client gives you no way to pick the node. WARPSCOUT walks the endpoint addresses, shows the node and exit region for each one, and writes a ready-to-import config for the best of them.

  • A single file, nothing to install
  • No admin rights and no TUN device
  • Windows, Linux, macOS, Android and Docker
  • A live table while scanning, plus a report file on disk

Installation

Windows

  1. Open the releases page and download warpscout_..._windows_amd64.zip.
  2. Unpack it anywhere, for example into C:\warpscout.
  3. Open that folder, hold Shift and right-click empty space → Open PowerShell window here (on Windows 11 - Open in Terminal).
  4. Check that it runs:
.\warpscout.exe version

Every command below goes into that same window.

Note

If Windows complains about the downloaded file, right-click warpscout.exe → Properties → tick Unblock at the bottom

Android

The easiest way is the ready-made app openwarpkit/warpscout-android by OpenWarpKit. Grab the APK for your architecture from its releases page.

In Termux the one-line install below works as it does on Linux.

Linux, macOS, OpenWrt, Termux

curl -fsSL https://raw.githubusercontent.com/vernette/warpscout/master/install.sh | sh

If there is no curl (OpenWrt routers, for one):

wget -qO- https://raw.githubusercontent.com/vernette/warpscout/master/install.sh | sh

The script picks the right archive for your system and puts warpscout into ~/.local/bin, on OpenWrt into /usr/bin, in Termux into $PREFIX/bin. Run it again to update.

Note

macOS only. The first run is blocked because the file came from the internet. Clear the flag once: xattr -d com.apple.quarantine warpscout

Other ways

Arch Linux (AUR, packaged by Nebulosa, not maintained by this repository):

paru -S warpscout      # build from source
paru -S warpscout-bin  # prebuilt release binary

Docker - see running in Docker.

From source, Go 1.25 or newer:

go install github.com/vernette/warpscout@latest

Installer options go after sh -s --, and INSTALL_DIR picks another directory:

INSTALL_DIR=/usr/local/bin sh -c "$(curl -fsSL https://raw.githubusercontent.com/vernette/warpscout/master/install.sh)"

curl -fsSL https://raw.githubusercontent.com/vernette/warpscout/master/install.sh | sh -s -- --version v0.8.1
curl -fsSL https://raw.githubusercontent.com/vernette/warpscout/master/install.sh | sh -s -- --uninstall

If you want a specific archive by hand, here is what to take:

Your OS File
Windows windows_amd64.zip
Mac on Apple silicon darwin_arm64.tar.gz
Mac on Intel darwin_amd64.tar.gz
Linux, regular PC or server linux_amd64.tar.gz
Linux on ARM (Raspberry Pi, some VPS) linux_arm64.tar.gz
OpenWrt router, x86_64 linux_amd64.tar.gz
OpenWrt router, ARM64 linux_arm64.tar.gz
Android, in Termux android_arm64.tar.gz

Quick start

The examples are written for Windows. On Linux, macOS and Termux type warpscout instead of .\warpscout.exe.

Step 1. Create a WARP account

.\warpscout.exe register

This writes warpscout-account.json next to the binary. You do it once - without that file scanning will not start. Details in the WARP account.

Step 2. Scan the endpoints

.\warpscout.exe scan -p awg -P
  • -p awg is AmneziaWG, obfuscated WireGuard. On filtering networks plain WireGuard (-p wg) usually gets through nowhere at all, so start with awg right away.
  • -P additionally measures latency and packet loss inside the tunnel. The scan takes longer, but endpoints that connect and then pass nothing are weeded out.

A scan takes a couple of minutes. The result is a table sorted so that the best endpoint is on top.

WARPSCOUT scan with -tun-ping

Step 3. Pick an endpoint

Look at the NODE column. Any row will do where the node is not DME, loss (LOSS) is 0%, and the ping is on the lower side.

To skip picking by hand, let the tool do it. -exclude-node DME drops the Moscow node and -best prints the single best address:

.\warpscout.exe scan -p awg -P -exclude-node DME -best
# 188.114.98.58:2408

Or the other way round - keep only the countries or nodes you want:

.\warpscout.exe scan -p awg -P -country DE,NL -best
.\warpscout.exe scan -p awg -P -node HEL,ARN -best

Step 4. Get a config

-conf writes a ready config for the best endpoint straight away:

.\warpscout.exe scan -p awg -P -exclude-node DME -conf warp.conf

Import warp.conf into the AmneziaWG client (Windows, Android, Linux, macOS) like any other config. If you scanned with -p wg, you get a plain WireGuard config.

Other formats (mihomo, usque), DNS, MTU and routing are covered in configs and filters.

Reading the table

Column What it means
SEEN AS The country websites will think you are in if you route traffic through this endpoint
NODE The Cloudflare edge node the tunnel landed on, as an airport code (FRA, ARN, DME)
NODE LOCATION Where that node sits, city and country
ENDPOINT PING A plain ping to the endpoint address. It only tells you how far the address is
TUN PING Latency inside the tunnel, to 1.1.1.1. Appears with -P
LOSS Packet loss inside the tunnel. Appears with -P
SPEED Download speed inside the tunnel. Appears with -speed

SEEN AS and NODE LOCATION are different things: a tunnel can go through Frankfurt and still exit as Russia. SEEN AS answers "which country will websites see", NODE answers "through which node, and which filtering, does the traffic go".

One subnet can hand out several different nodes, so rows with similar addresses but different nodes are perfectly normal.

Besides the on-screen table the tool writes a report file, warpscout-report-<timestamp>.txt, with every endpoint it found. -no-report turns it off.

If nothing works

Go down the list, running the scan again at each step.

  1. A -p wg scan finds nothing, or every endpoint ends up in the torn down list. That is expected on a filtering network. Use -p awg.

  2. -p awg finds nothing either. Change the fake first packet the connection opens with:

    .\warpscout.exe scan -p awg -P -gen-i1 quic
    

    Instead of quic you can try dns, sip, stun, random. This is usually what helps.

  3. No -gen-i1 profile helped. Let the tool search for working obfuscation parameters. It rescans until it finds a working set, then prints a ready-to-run command:

    .\warpscout.exe find-junk -gen-i1 random
    

    More in getting past blocking.

  4. AmneziaWG does not get through at all. Try MASQUE, Cloudflare's second transport - over TCP it looks like ordinary HTTPS:

    .\warpscout.exe find-sni -p masque-h2
    .\warpscout.exe scan -p masque-h2 -masque-sni www.apple.com
    

    More in MASQUE.

What torn down means

Some endpoints land in a separate torn down list instead of the working ones. Those connected and passed data at first, and were then cut mid-stream - that is what DPI does to a tunnel it does not like. In everyday use it looks like a VPN that connects, works for a few seconds and hangs for good.

Only -P can see this. Without it the same endpoints look perfectly fine:

WARPSCOUT wg scan without -tun-ping

With -P it turns out every one of them gets cut:

WARPSCOUT wg scan with -tun-ping

Torn-down endpoints are never picked by -best or -conf. They are shown so you can see how much of the pool your network kills - which is the signal to change -gen-i1.

Commands

Command What it does
register Create a WARP account and save it. Start here
scan Scan the endpoints and show the working ones
find-junk Search for AmneziaWG parameters that get past the filter
find-sni Search for a MASQUE SNI that gets past the filter
socks Serve one endpoint as a local SOCKS5 proxy, to test it
version Print the installed version

Useful flags

Flag What it does
-p, -proto Protocol: wg, awg, masque, masque-h2 (default wg)
-P, -tun-ping Measure latency and loss inside the tunnel, and weed out torn-down endpoints
-best Print one best ip:port instead of the tables
-conf FILE Write a ready config for the best endpoint (-conf - prints it instead)
-node, -country Keep only these nodes or countries, comma-separated
-exclude-node, -exclude-country Drop them instead. Stacks with the two above
-n, -sample N Addresses to try per subnet (default 5)
-f, -full Try every address of every subnet. Slow but thorough
-speed Add the SPEED column - a download test. Noticeably slower
-6, -ipv6 Scan IPv6 endpoints instead of IPv4
-o FILE, -no-report Where to write the report file, or skip it entirely
-emoji Show country flags next to regions
-t, -timeout N Per-request timeout in seconds (default 2)
-jt N How many tunnels to bring up at once (default 10)

The full flag list of any command is warpscout <command> -h, for example .\warpscout.exe scan -h.

Going further

  • How it works - the scan phases, region versus node, checking a VPS region
  • The WARP account - what register does, what the account file holds, registering from a blocked network
  • Getting past blocking - AmneziaWG obfuscation, -gen-i1, junk packets, find-junk
  • MASQUE - -p masque and -p masque-h2, picking an SNI, usque configs
  • Configs and filters - -conf formats, DNS and MTU, -target, the speed phase, the report format
  • SOCKS5 proxy - check one endpoint with third-party services
  • WARP-in-WARP - scanning from inside another WARP tunnel
  • Docker - running in a container
  • Troubleshooting - ENDPOINT PING shows ?, the tool gets killed on a router, macOS refuses to run it

Credits

Support the author

CloudTips     NOWPayments