Networking and remote
nc
Open raw TCP or UDP connections, or listen for them; for testing ports, talking to services by hand and piping data between hosts.
nc [OPTION...] HOST PORT | nc -l [OPTION...] [ADDRESS] PORT
netcat connects standard input and output to a network socket. nc host port opens a TCP
connection and sends whatever you type (or pipe in), printing whatever comes back;
nc -l port waits for someone to connect. That simple model makes it a universal test tool:
is the port open, what does the service say first, does my request get an answer.
Several incompatible netcats exist. These examples use netcat-openbsd, the default on
Debian and Ubuntu (and the basis of macOS's nc). Two of its habits matter: the listener's
port is given directly (nc -l 9000, not nc -l -p 9000 as in the traditional version), and
a client does not hang up when its input ends unless you pass -N (or set an idle timeout with
-w). ncat from the nmap project is a third variant with its own options.
The examples run on loopback, with a listener started in the background in the same command.
Across two machines it is the same: run the -l side on one and the client on the other.
Examples
Check whether a port is open
nc -zv 127.0.0.1 22
Connection to 127.0.0.1 22 port [tcp/ssh] succeeded!
-z connects and immediately closes without sending data; -v reports the result. The
message goes to standard error, and the exit status is 0 for success.
A closed port
nc -zv 127.0.0.1 9999
nc: connect to 127.0.0.1 port 9999 (tcp) failed: Connection refused
Nothing listens on 9999, so the connection is refused and nc exits with 1, which makes
nc -z usable in if tests and wait loops.
Check a range of ports
nc -zv 127.0.0.1 20-23
nc: connect to 127.0.0.1 port 20 (tcp) failed: Connection refused nc: connect to 127.0.0.1 port 21 (tcp) failed: Connection refused Connection to 127.0.0.1 22 port [tcp/ssh] succeeded! nc: connect to 127.0.0.1 port 23 (tcp) failed: Connection refused
A range checks each port in turn. Only 22 accepts. The exit status is 0 because at least one connection succeeded.
Wait for a service in a script
for i in 1 2 3; do
nc -z -w 1 127.0.0.1 8080 && { echo "web server is up"; break; }
sleep 1
done
Connection to 127.0.0.1 8080 port [tcp/http-alt] succeeded! web server is up
-w 1 limits each attempt to one second, so a filtered port that never answers cannot hang
the loop. Debian's nc prints the succeeded! line even without -v. A typical use is waiting for a database or web server to start before running
tests.
See what a service says first
nc -w 1 127.0.0.1 22 < /dev/null
SSH-2.0-OpenSSH_10.0p2 Debian-7+deb13u4
SSH servers announce their protocol and software version as soon as you connect. nc prints
it and, with no input and -w 1, gives up after a second of silence. Mail, FTP and many
other text protocols greet you the same way.
Speak HTTP by hand
printf 'GET /api/status.json HTTP/1.0\r\nHost: localhost\r\n\r\n' | nc 127.0.0.1 8080
HTTP/1.1 200 OK
Server: demo-httpd/1.0
Date: Sat, 31 Oct 2026 20:20:12 GMT
Content-type: application/json
Content-Length: 56
Last-Modified: Mon, 26 Oct 2026 13:48:10 GMT
{"status": "ok", "version": "2.4.1", "uptime_s": 86400} The request line, a header and a blank line, with the CRLF endings HTTP requires. The server replies with its status line, headers and body. This shows exactly what is on the wire, with no client adding or hiding anything.
Listen and connect
nc -l 127.0.0.1 9000 > received.txt &
sleep 0.3
echo "hello over tcp" | nc -N 127.0.0.1 9000
wait
cat received.txt
hello over tcp
The listener writes whatever arrives to received.txt. The client sends one line; -N
shuts down the connection once its input ends, which makes the listener exit too, and
wait waits for it.
Send a file between machines
nc -l 127.0.0.1 9000 > copy.csv &
sleep 0.3
nc -N 127.0.0.1 9000 < data/sales.csv
wait
cmp data/sales.csv copy.csv && echo "identical, $(wc -c < copy.csv) bytes"
identical, 405 bytes
Send a UDP datagram
nc -u -l 127.0.0.1 9001 > datagram.txt &
sleep 0.3
echo "metric.cpu 42" | nc -u -w 1 127.0.0.1 9001
sleep 0.2
cat datagram.txt
metric.cpu 42
-u switches to UDP, as used by syslog, statsd and DNS. UDP has no connection to close, so
the client uses -w 1 to quit after a second.
Common pitfalls
nc -l -p 9000is traditional-netcat syntax. netcat-openbsd wantsnc -l 9000and reports an error for-pcombined with-lon some versions.Without
-Nor-w, the openbsd client keeps the connection open after its input ends, so a command likeecho hi | nc host portcan hang waiting for the server.A successful
nc -zonly proves that something accepted a TCP connection, not that it is the service you expect or that it works. Talk to it (an HTTP request, a banner) to be sure.-u -zchecks for UDP are unreliable: with no reply, nc cannot tell an open port from a filtered one.
GNU vs BSD and macOS
The examples above ran the GNU/Linux version. These are the differences that matter on macOS and the BSDs (written from their documentation, not run here).
macOS's
ncderives from the same BSD code, so most of these examples work there; checkman ncfor-Nbefore relying on it. Traditional netcat (netcat-traditional), BusyBoxncand nmap'sncatdiffer in listener syntax and options.
Options worth knowing
A selection, described in our own words. For the full list, see nc(1) or nc --help.
| Option | What it does |
|---|---|
-l | Listen for an incoming connection instead of connecting. |
-k | With -l, keep listening for more connections after one ends. |
-z | Only check whether the port accepts connections; send no data. |
-v | Report connection results and errors. |
-n | Do not resolve host names or look up ports. |
-u | Use UDP instead of TCP. |
-N | Shut down the network connection after end of input. |
-w SECONDS | Time out connections and idle sessions after SECONDS. |
-q SECONDS | After end of input, wait SECONDS and then quit. |
-s ADDRESS | Send from this local address. |
-p PORT | Use this local source port. |
-4 | Use IPv4 only. |
-6 | Use IPv6 only. |
-U | Use Unix domain sockets. |
-C | Send CRLF as the line ending. |
-X PROTOCOL | Proxy protocol: 4 (SOCKS4), 5 (SOCKS5) or connect (HTTPS proxy). |
-x ADDRESS[:PORT] | Connect through this proxy. |
Related
curlTransfer data to or from a URL; the standard tool for HTTP requests, API calls and downloads from the shell.ssList network sockets on Linux; above all, which ports are listening and which connections are open.sshLog in to a remote machine or run a command on it over an encrypted connection; also forwards ports and jumps through hosts.pingSend ICMP echo requests to a host and report replies and round-trip times, to test reachability and latency.