Netcat Cheatsheet

Listener Mode

Use this Netcat reference while you build software engineering projects, review code, or refresh the syntax you reach for most.

Binding a port

nc -l 8080                  # OpenBSD nc, macOS nc, Ncat
nc -l -p 8080               # netcat-traditional, GNU netcat, BusyBox
nc -lvnp 8080               # verbose, no DNS, the habitual form

The -p difference is the single most common paste failure. OpenBSD nc takes the port as a positional argument and rejects -p with -l. netcat-traditional requires -p. Ncat accepts both. If nc -l -p 8080 errors with "cannot use -p and -l", you are on OpenBSD nc, so drop the -p.

FlagEffect
-lListen instead of connect
-kKeep listening after a client disconnects
-vPrint each connection as it arrives
-nNo reverse DNS on the client address
-s addrBind one interface only, instead of all of them
-uUDP listener
-w nGive up after n seconds with no connection

One connection, then exit

Plain -l accepts exactly one client and exits when it disconnects. That is usually a feature, because a one-shot listener is a clean test target.

# Terminal 1
nc -lv 8080

# Terminal 2
echo "hello" | nc 127.0.0.1 8080

Terminal 1 prints hello and then both processes exit. To stay up for a second client:

nc -lkv 8080                 # OpenBSD nc, Ncat
ncat -lkv 8080               # same, explicit

netcat-traditional and GNU netcat have no -k. Loop in the shell instead:

while true; do nc.traditional -l -p 8080; done

-k in Ncat handles clients sequentially by default. For concurrent clients add -m:

ncat -lk -m 20 8080          # up to 20 simultaneous connections

Binding addresses and permissions

nc -l 8080                       # all interfaces, 0.0.0.0 and often ::
nc -l -s 127.0.0.1 8080          # loopback only, not reachable off-box
nc -l -s 10.0.0.7 8080           # one specific interface
sudo nc -l 80                    # ports below 1024 need root
SymptomCause
Permission deniedPort below 1024 without root
Address already in useSomething is bound there already
Works locally, not remotelyBound to 127.0.0.1, or a firewall
Client connects, sees nothingExpected, the listener sends only what you type

Find what holds the port:

ss -ltnp 'sport = :8080'          # Linux
lsof -nP -iTCP:8080 -sTCP:LISTEN  # macOS and Linux

A listener that exits leaves the port in TIME_WAIT briefly, so an immediate rebind can fail for up to a minute. Wait, or use a different port.

Serving a fixed response

A listener is a pipe, so redirect a file into it. This is the fastest possible stub server.

# Send a file's contents to whoever connects, once
nc -l 8080 < response.txt

# A real HTTP response, headers and all
printf 'HTTP/1.1 200 OK\r\nContent-Length: 3\r\nConnection: close\r\n\r\nhi' \
  | nc -l 8080

# Serve the same response to every client, forever
while true; do
  printf 'HTTP/1.1 200 OK\r\nContent-Length: 2\r\n\r\nok' | nc -l 8080
done

# Ncat, keeps listening and re-reads the file each time
ncat -lk 8080 --send-only < response.txt

Content-Length must match the body byte count exactly or the client hangs waiting for the rest. Connection: close lets the client know the response ended, which matters when you get the length wrong.

Capturing what a client sends

Debugging a webhook, an agent, or a misconfigured client: point it at a netcat listener and read the raw bytes.

# Print the request, headers and body
nc -lv 8080

# Save it and also watch it
nc -lv 8080 | tee /tmp/request.txt

# Accept, log with a timestamp, keep listening
while true; do
  echo "--- $(date -Is) ---"
  nc -l 8080
done | tee -a /tmp/requests.log

# Ncat logs the session itself, no shell plumbing
ncat -lk 8080 -o /tmp/session.log      # plain text
ncat -lk 8080 -x /tmp/session.hex      # hex dump

Most HTTP clients wait for a response and will report a timeout, but you still see the full request first, which is the point. To make the client happy, send a minimal 200 back as shown above.

Chat and broker modes

Two listeners plus a client is enough for a two-way channel, and Ncat has purpose-built modes.

# Bidirectional: both sides type, both sides see it
nc -l 8080          # host A
nc hostA 8080       # host B

# Ncat relays between every connected client
ncat --broker -lk 8080

# Ncat's chat server, prefixes messages with a user id
ncat --chat -lk 8080

--broker is the useful one. Every client connected to the same broker sees what every other client sends, so it is a throwaway message bus for testing without deploying anything.

Access control

Only Ncat can filter who connects, which is a real reason to prefer it for a listener exposed beyond loopback.

ncat -lk 8080 --allow 10.0.0.5
ncat -lk 8080 --allow 10.0.0.0/24
ncat -lk 8080 --allowfile /etc/ncat.allow
ncat -lk 8080 --deny 10.0.0.99
OptionEffect
--allow <hosts>Only these may connect, everything else refused
--allowfile <f>One host or CIDR per line
--deny <hosts>Blocklist, everything else allowed
--denyfile <f>Blocklist from a file

Plain nc -l accepts anything that reaches the port. A netcat listener has no authentication and no encryption, so bind it to 127.0.0.1 unless you have a specific reason not to, and never leave one running.

Listener checklist

WantCommand
One-shot test targetnc -lv 8080
Persistent targetnc -lkv 8080
Loopback onlync -lv -s 127.0.0.1 8080
Log the client's bytesnc -lv 8080 | tee /tmp/r.txt
Fixed HTTP 200 replyprintf 'HTTP/1.1 200 OK\r\n\r\n' | nc -l 8080
Concurrent clientsncat -lk -m 20 8080
TLS listenerncat -lk --ssl 8443
Restrict by sourcencat -lk 8080 --allow 10.0.0.0/24
Old netcat, keep alivewhile true; do nc -l -p 8080; done