CLI
The official command line interface for the VPNDetection API.
Getting Started
No account is needed to start: the free tier answers ip and is_vpn, and allows 1000 requests per day per source address.
macOS
brew tap vpndetection-io/tap
brew install vpndetectionDebian / Ubuntu
Install from our apt repository, which keeps the CLI up to date with apt upgrade:
echo "deb [trusted=yes] https://apt.vpndetection.io/ /" | sudo tee /etc/apt/sources.list.d/vpndetection.list
sudo apt update && sudo apt install vpndetectionOr install a single .deb without the repository:
curl -Ls https://github.com/vpndetection-io/cli/releases/latest/download/deb.sh | shWindows
winget install Mslm.VPNDetectionchoco install vpndetectionOr install for the current user without a package manager:
iwr -useb https://github.com/vpndetection-io/cli/releases/latest/download/windows.ps1 | iexDocker
docker run --rm ghcr.io/vpndetection-io/cli 45.83.91.1Using go install
go install github.com/vpndetection-io/cli@latestThe binary is named after the module, so rename it to vpndetection if you want the examples below to read the same.
Using curl / wget
Binaries are published for 22 platform and architecture pairs on the releases page. Pick yours:
# Linux amd64; for Windows use ".zip" instead of ".tar.gz"
curl -LO https://github.com/vpndetection-io/cli/releases/latest/download/vpndetection_0.1.0_linux_amd64.tar.gz
tar -xzf vpndetection_0.1.0_linux_amd64.tar.gz
sudo mv vpndetection /usr/local/bin/macOS has a one-line installer that picks the right architecture for you:
curl -Ls https://github.com/vpndetection-io/cli/releases/latest/download/macos.sh | shNote that the binaries are not code-signed, so macOS Gatekeeper will ask before running one the first time, and Windows SmartScreen may warn.
From source
git clone https://github.com/vpndetection-io/cli
cd cli
./scripts/build.shThe result lands in build/. Go 1.25 or newer.
Quick Start
Default help message
Invoking the CLI with nothing shows what it can do:
$ vpndetection
Usage: vpndetection <ip | cidr | range | file>... [<opts>]
vpndetection <cmd> [<opts>] [<args>]
...Login
You can use the CLI without an account, but a key widens the answer and raises your allowance. Create one in the console, then:
$ vpndetection login
API key:
stored key mk_1************************abcd in session "default", now activeThe prompt does not echo and the key does not reach your shell history. vpndetection signup opens the console to create an account first.
My IP
$ vpndetection myip
ip 45.83.91.1
is_bogon false
is_vpn trueThis is the address our edge observed, so behind a proxy or a VPN it reports the exit you left through.
Any IP
$ vpndetection 45.83.91.1
ip 45.83.91.1
is_bogon false
is_vpn true
is_hosting true
is_relay false
is_tor false
is_cdn false
vpn.provider mullvad
vpn.last_seen 2026-09-12
hosting.provider m247
hosting.confidence highPrivate, reserved and documentation addresses are answered locally without a request, so they cost nothing and work offline.
Piping
Addresses can come from standard input, and from arguments, at the same time:
$ cat addresses.txt | vpndetection
$ vpndetection 1.1.1.1 8.8.8.0/24 9.9.9.1-9.9.9.9 addresses.txtAnything resolving to more than one address prints JSON keyed by address; a single address prints the readable block. That follows the resolved count, so 10.0.0.1/32 is one and 10.0.0.0/30 is four.
Field filter
$ vpndetection 45.83.91.1 -f is_vpn
is_vpn true
$ vpndetection 45.83.91.1 -f is_vpn,vpn.provider
is_vpn true
vpn.provider mullvad
$ vpndetection 45.83.91.1 -f vpn # the whole objectBulk
bulk always prints the machine format, whatever the count, which is what a script wants:
$ vpndetection bulk 8.8.8.0/24 --csv > answers.csv
$ vpndetection bulk addresses.txt --jsonl | jq -r 'select(.is_vpn) | .ip'Bulk runs stream: nothing is held in memory beyond one batch, so a /8 is a long command rather than an impossible one, and output starts immediately. With no arguments at a terminal it reads addresses you type, one per line, ending at a blank line.
Output formats are --pretty, --json, --jsonl, --csv and --yaml.
Sessions
Credentials are stored in named sessions, so one machine can hold several organizations' keys and switch between them without logging in again:
$ vpndetection login --session work
$ vpndetection login --session acme --base-url https://api.example.com
$ vpndetection session list
NAME KEY API LAST USED
acme mk_4***************mnop https://api.example.com never
* default mk_1***************abcd default 2h ago
work mk_9***************wxyz default never
$ vpndetection session use work
$ vpndetection --session work 45.83.91.1 # one command, without switching--base-url points a session at another deployment of the API; a session without one talks to https://api.vpndetection.io.
A key can also come from --key or the VPNDETECTION_API_KEY environment variable, in that order of precedence. The config file is written 0600 inside a 0700 directory.
Plan and usage
$ vpndetection whoami
key mk_1************************abcd
from session default
api https://api.vpndetection.io
org 85bb51e4-2eb6-4a31-8e4d-02ba8b98fe61
plan max
fields max tier
used 412,908 of 5,000,000
[### ] 8.3%
hard limit none; requests above the quota are billed as overage
resets 2026-10-04T07:00:00Z (in 20d)Also spelled myaccount and quota. Usage counts against the anniversary of your subscription, not the calendar month and not the billing period, and it is the same number a lookup is gated on.
Databases
The same classifications, published as files you host yourself. Access is granted by contract and needs a key carrying the db.download scope.
$ vpndetection db list
ID NAME LICENCE STANDING TERM
vpn_ip_v1 VPN IP standard licensed renews 2027-01-04
$ vpndetection db metadata vpn_ip_v1
$ vpndetection db download vpn_ip_v1
$ vpndetection db download cdn_ip_v1 --format mmdb cdn.mmdb
$ curl -fL "$(vpndetection db url vpn_ip_v1)" -o vpn_ip_v1.csv.gzDownloads are verified against the published sha256 and land through a .part file, so an interrupted transfer never leaves a truncated file that reads as a whole database.
Auto-Completion
Auto-completion is supported for at least the following shells:
bash
zsh
fishIt completes commands, flags, the values flags take, field names, and the session names this machine actually holds.
NOTE: it may work for other shells as well, because the implementation is in Go and is not shell-specific.
Installation
Installing auto-completions is as simple as running one command, which covers bash, zsh and fish:
vpndetection completion installStart a new shell afterwards to pick it up.
If you want to customize the installation (for example when the auto-installation does not work as expected), you can request the completion line for each shell instead:
# get bash completion script
vpndetection completion bash
# get zsh completion script
vpndetection completion zsh
# get fish completion script
vpndetection completion fishvpndetection completion uninstall removes it again.
Shell not listed?
If your shell is not listed here, you can open an issue.
Note that as long as the COMP_LINE environment variable is provided to the binary itself, it will output completion results. So if your shell provides a way to pass COMP_LINE on auto-completion attempts to a binary, then have your shell do that with the vpndetection binary itself.
Data
How much you get back per lookup depends on the plan behind your key. See the plans for what each includes. All examples in this document use a key with everything enabled.
A field your plan does not include is missing from the answer, not false. is_tor absent means we did not check; is_tor: false means we checked and it is not a Tor node. The readable output prints only what you were served; CSV writes an empty cell for absent and the literal false for false. --show-absent renders the lot.
Caching
Answers are cached on disk, so looking the same address up twice costs one request rather than two.
vpndetection cache info
vpndetection cache clear
vpndetection --nocache 45.83.91.1
vpndetection config list
vpndetection config cache=disable cache_ttl=24hEntries are partitioned by credential, because which fields an answer carries depends on the plan behind the key — one key's answers are never served to another's. Clearing empties every partition.
Color Output
Disabling color output
The CLI respects either the --nocolor flag or the NO_COLOR environment variable to disable color output.
Color on Windows
To enable color support for the Windows command prompt, run the following to enable Console Virtual Terminal Sequences:
REG ADD HKCU\CONSOLE /f /v VirtualTerminalLevel /t REG_DWORD /d 1You can disable this by running the following:
REG DELETE HKCU\CONSOLE /f /v VirtualTerminalLevel