netcat (nc) Command in Linux, with Examples

The nc command, short for netcat, is one of those tools that looks simple at first and keeps surprising you the longer you use it. It reads and writes data across network connections using TCP or UDP, which sounds straightforward until you realize how many problems that actually solves. Port testing, file transfers, banner grabbing, reverse shells, proxies, debugging network services. All with one tool that ships on almost every Linux system.

I use nc regularly during server troubleshooting. It cuts out the noise fast. Is the port open? Is something actually listening? Is the firewall blocking it? nc answers those questions in seconds without needing a dedicated tool for each one.

This guide covers real, practical usage. Not every flag in the man page, just the ones that matter.

Install netcat

Most distributions already have some version of netcat installed. There are a few variants: netcat-openbsd and netcat-traditional are the two most common on Debian-based systems. On Red Hat-based systems, ncat from the nmap project is often the default.

To install on Ubuntu/Debian:

sudo apt install netcat-openbsd

On Fedora/RHEL/CentOS:

sudo dnf install nmap-ncat

On Arch Linux:

sudo pacman -S openbsd-netcat

Check what version you have and what binary name it uses:

nc --version
which nc
which ncat

Note: The OpenBSD variant and traditional netcat differ in some flags. This guide uses the OpenBSD variant (nc), which is the most widely available. ncat from nmap is generally compatible but has some extra features of its own.

One thing that trips people up: nc is a command name, not a single program. On any given machine it might be OpenBSD netcat, Ncat from the Nmap project, BusyBox, or traditional netcat. They mostly behave the same for basic use, but some flags differ, and a few are missing entirely depending on which one you have. BusyBox is the one to watch for. It ships in Alpine, most container images, and a lot of routers, and its nc is heavily stripped down, so options like -z, -k, and -U may not be there at all. When in doubt, run nc --version or check the binary as shown above, then confirm your flags against man nc.

Basic Syntax

nc [options] host port

Or to listen:

nc -l [port]

That is the full core of it. Everything else is built on top of those two modes: connect to something, or listen for something.

Note that listen syntax is one of the things that varies by implementation. The OpenBSD variant used here takes nc -l 8080. BusyBox and traditional netcat often want the port passed with -p instead, as nc -l -p 8080. If a listener refuses to start, try the -p form.

Test If a Port Is Open

This is the thing I use nc for most often. You need to know if a port is open and accepting connections, without installing anything extra.

nc -zv example.com 80

The -z flag means zero-I/O mode: connect and immediately close. The -v flag gives verbose output so you can see what happened.

Output when the port is open:

Connection to example.com 80 port [tcp/http] succeeded!

Output when the port is closed or filtered:

nc: connect to example.com port 80 (tcp) failed: Connection refused

You can scan a range of ports too:

nc -zv example.com 20-25

This is useful for quickly checking which ports in a range are open. It is not a replacement for nmap when you need thorough scanning, but for quick checks it gets the job done. See the guide to network troubleshooting in Linux for more tools you can combine with this.

Test UDP Ports

By default nc uses TCP. Add -u to switch to UDP:

nc -zvu example.com 53

UDP testing is less reliable than TCP because there is no handshake. A non-response does not definitively mean the port is closed. But it is still useful for services like DNS, SNMP, or NTP where you want a quick check.

Set a Connection Timeout

By default, nc will wait a long time when connecting to a filtered port. Use -w to set a timeout in seconds:

nc -zv -w 3 example.com 443

This gives up after 3 seconds instead of hanging. Very useful in scripts where you do not want to wait indefinitely.

Transfer Files Over the Network

This is one of those capabilities that surprises people. You do not need scp or rsync for a quick one-off transfer if nc is available on both ends. It is not encrypted, so only use this on trusted networks.

On the receiving machine (start listening first):

nc -l 9999 > received_file.tar.gz

On the sending machine:

nc receiving-host-ip 9999 < file_to_send.tar.gz

The file transfers and then the connection closes. Simple and fast. For transferring a whole directory, combine it with tar:

On the receiver:

nc -l 9999 | tar xzvf -

On the sender:

tar czvf - /path/to/directory | nc receiving-host-ip 9999

Note: For anything sensitive, use SSH-based file transfers instead. Netcat sends data in plaintext.

Chat Between Two Machines

This sounds like a toy feature but it is actually handy when you are troubleshooting network connectivity between two machines and want to confirm bidirectional communication is working.

On machine A (listener):

nc -l 5555

On machine B (connector):

nc machine-a-ip 5555

Now you can type on either end and it appears on the other. Ctrl+C or Ctrl+D closes the connection. It confirms that both TCP direction and the port are fully functional end-to-end.

Grab a Service Banner

Many services send a banner when you connect. You can grab that banner with nc to check the software version, confirm the service is running, or identify what is listening on a port.

Connect to an SSH server:

nc example.com 22

You will get something like:

SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.6

Connect to an SMTP server:

nc mail.example.com 25
220 mail.example.com ESMTP Postfix (Ubuntu)

Connect to an HTTP server and send a raw request:

nc example.com 80
GET / HTTP/1.0
Host: example.com

(Press Enter twice after the Host line to send the request.)

You will get back the full HTTP response headers and body. This is useful for checking what a server returns before involving a browser or curl.

This only works on plaintext ports. Point plain nc at an HTTPS service on port 443 and you will get an encrypted handshake back, which looks like garbage on your terminal. To talk to a TLS service by hand, use ncat with the --ssl flag:

ncat --ssl example.com 443

Then type your raw request as before. If ncat is not installed, openssl s_client -connect example.com:443 does the same job.

Test a Local Service

You do not need a remote host. You can connect to services running locally too. Testing a web server running on a non-standard port, checking that a database is listening, verifying an app started correctly:

nc -zv localhost 3306
nc -zv 127.0.0.1 8080

This pairs well with VPS benchmarking and testing when you want to confirm services are reachable before running heavier tests. If you want to see everything currently listening on the machine first, the ss command lists open sockets and the processes behind them.

Test a Unix Socket

Not every service listens on a TCP port. A lot of them, PHP-FPM, Docker, database sockets, listen on a Unix domain socket instead. The OpenBSD variant and ncat can connect to those with -U:

nc -U /run/php/php-fpm.sock

Or the Docker daemon socket:

nc -U /var/run/docker.sock

This is handy when you need to confirm a socket exists and accepts connections before pointing an application at it. Note that -U is not available in BusyBox netcat, so this one depends on which implementation you have.

Create a Simple TCP Server for Testing

You can spin up a listener that echoes back a test response. This is useful when you are building a client application and want something simple to connect to.

Listen and send a message to every client that connects:

echo "hello from server" | nc -l 8888

From another terminal or machine:

nc server-ip 8888

The client receives the message and the connection closes. The listener exits after one connection. To keep it running in a loop (with traditional or ncat):

while true; do echo "hello" | nc -l 8888; done

Wait for a Service to Come Up

This one shows up constantly in container setups. You need to hold off starting an application until the thing it depends on, a database, a message queue, is actually accepting connections. The -z flag makes this a one-liner:

until nc -z database 5432; do
  echo "waiting for database..."
  sleep 1
done

The loop keeps testing port 5432 on the host named database and only continues once the connection succeeds. You will find some version of this in a huge number of Docker entrypoint scripts, where a web app has to wait for Postgres or MySQL to finish starting. Add a -w timeout if you want it to give up eventually rather than loop forever.

Keep the Listener Open: -k Flag

The OpenBSD variant of nc supports -k to keep listening after a client disconnects:

nc -lk 8888

This is more useful for testing multiple connections without restarting the listener each time. Note that -k is not available in all variants of netcat.

Proxy Traffic with netcat

You can chain two nc instances together to create a basic TCP proxy. Traffic hits one port and gets forwarded to another host and port.

mkfifo /tmp/ncpipe
nc -l 8080 < /tmp/ncpipe | nc real-server.com 80 > /tmp/ncpipe

The named pipe connects the output of the listener to the input of the outbound connection and vice versa. This is a debugging technique, not something you would run in production. But it is genuinely useful when you need to intercept or inspect traffic in a pinch.

Check Network Throughput (Quick and Dirty)

You can get a rough idea of raw TCP throughput between two machines using nc and /dev/zero. This is not a replacement for iperf3, but it works in a pinch.

On the receiver, watch throughput with pv (pipe viewer):

nc -l 9998 | pv > /dev/null

On the sender:

nc receiver-ip 9998 < /dev/zero

pv will show real-time throughput. Install it with sudo apt install pv or sudo dnf install pv if it is not already present.

Useful Flags Reference

  • -l – Listen mode. Wait for an incoming connection instead of initiating one.
  • -v – Verbose. Show connection status and other info.
  • -z – Zero I/O mode. Scan without sending data. Used for port checking.
  • -u – Use UDP instead of TCP.
  • -w seconds – Timeout. Give up after this many seconds.
  • -k – Keep listening after client disconnects (OpenBSD variant).
  • -n – Skip DNS resolution. Use numeric IPs only.
  • -p port – Specify the local source port.
  • -e command – Execute a command after connecting (not available in all variants).
  • -4 / -6 – Force IPv4 or IPv6.

A Few Real-World Scenarios

Check if a firewall rule is blocking a port

Set up a listener on the server:

nc -l 9000

Try to connect from the client:

nc -zv server-ip 9000

If it connects, the port is open through the firewall. If it hangs or refuses, something is blocking it. This is often the fastest way to confirm a firewall rule change worked before deploying an application.

Verify a database port is reachable from the app server

nc -zv -w 3 db-server-ip 5432

If this fails from your app server but succeeds from the database server itself, the network or firewall is the issue, not the database configuration.

Debug a slow connection

Connect and time how long the handshake takes:

time nc -zv -w 5 example.com 443

If the connection is slow to establish, it points to DNS resolution delay, routing issues, or a slow server response rather than an application problem. Combine this with traceroute for a fuller picture.

Test outbound connectivity from a restricted server

Sometimes you need to confirm a server can reach the outside world on a specific port. For example, checking that a server can reach an external SMTP relay on port 587:

nc -zv -w 5 smtp.mailprovider.com 587

If this fails but port 25 works, you know the outbound firewall is filtering port 587 specifically.

Limitations to Know

Netcat is not encrypted. Do not use it for sensitive data transfers on untrusted networks. It is also not a full-featured port scanner. For serious scanning, use nmap. And the feature set varies between implementations: the OpenBSD variant, traditional netcat, and ncat from nmap each have slightly different flags and capabilities. If a flag does not work, check which variant you have installed.

Also, some security-hardened systems disable or remove nc entirely, or restrict the -e flag (which can execute commands). That is intentional. The same power that makes nc useful for debugging makes it something that security teams watch for.

You may have noticed this guide does not cover reverse shells, which are the use netcat is most infamous for. That is deliberate. The same -e techniques show up far more often in intrusions than in legitimate administration, so there is little reason to spell them out here. Everything above is aimed at testing, transferring, and troubleshooting, which is what most of us actually reach for nc to do.

One more thing worth knowing: everything here works over IPv6 too. Force it with -6 when a host resolves to both:

nc -6 -zv example.com 443

Summary

The nc command earns its place in the toolkit by being genuinely useful across a wide range of tasks without requiring anything special. Port testing, file transfers, service banner grabbing, connectivity debugging. It is not glamorous but it solves real problems fast.

For a broader look at what Linux has to offer for network diagnostics and monitoring, the network troubleshooting guide covers the full stack of tools worth knowing. And if you want to go deeper on benchmarking network performance between machines, the Linux benchmark scripts and tools article covers iperf and others.

Run man nc on your system to check the specific flags available for your installed variant. What you get depends on which implementation is installed, and the differences matter.

Tags: , , ,

Stop Losing Users to Slow Load Times.

Blazing-fast, custom-configured NVMe Linux hosting.

Don't guess if your server is fast enough. Know it. Get a free performance audit of your current setup.

Start Your Free Server Audit

You Write the Code. We'll Manage the Server.

Fully managed Linux hosting built for absolute speed.

Ditch the server maintenance headaches. Our experts custom-configure high-performance NVMe Linux servers specifically for your needs. Try us out. Your first month is entirely on us.

Claim Your 30 Free Days

30 Days of NVMe Linux Hosting. $0 Down.

Risk-free migration and a money-back guarantee.

We are so confident in our high-performance NVMe infrastructure that we'll audit your current server for free, migrate you without downtime, and give you 30 days to see the speed difference yourself.

Deploy Free for 30 Days
Top ↑