When testing webhooks from third-party services (such as GitHub, Stripe, or Twilio) or debugging REST APIs locally, spinning up a full web server stack like Nginx or Node.js just to inspect incoming HTTP payloads is often overkill.

Netcat (nc), often referred to as the "Swiss Army knife of networking," allows backend engineers and system administrators to open a TCP listening socket on any specified port number in seconds. In this article, we demonstrate how to use Netcat to capture HTTP POST messages, log headers and JSON payloads, and return mock HTTP 200 OK responses to clients.

Quick Command Cheatsheet

Start a Netcat TCP listener on port 8080 to capture the next incoming HTTP POST request:

Terminal Commandsbash
# 1. Start Netcat listener on port 8080 (OpenBSD / Ubuntu default)
nc -l 8080
 
# 2. GNU Netcat syntax (if running GNU nc or traditional variant)
nc -lvp 8080
 
# 3. Test sending an HTTP POST request from another terminal using curl
curl -X POST http://localhost:8080/api/webhook \
     -H "Content-Type: application/json" \
     -d '{"event": "user.signup", "id": 1042}'

Method 1: One-Shot HTTP POST Payload Capture

When you run nc -l 8080, Netcat opens a socket, waits for a single TCP connection, prints all incoming HTTP request headers and body payload directly to stdout, and terminates immediately when the client closes the connection.

Netcat Server Console Outputbash
# Terminal Output rendered by Netcat when curl sends the POST request:
POST /api/webhook HTTP/1.1
Host: localhost:8080
User-Agent: curl/7.81.0
Accept: */*
Content-Type: application/json
Content-Length: 35
 
{"event": "user.signup", "id": 1042}

Method 2: Persistent Loop Server for Continuous POST Capture

By default, standard Netcat exits after receiving a single request. Wrap nc inside a Bash while loop to keep the port open for continuous webhook debugging and append incoming requests to a log file:

netcat-persistent-listener.shbash
#!/usr/bin/env bash
# Continuous Netcat HTTP POST Listener
 
PORT=8080
LOG_FILE="incoming_webhooks.log"
 
echo "Listening for HTTP POST requests on port ${PORT}..."
echo "Logging requests to ${LOG_FILE}..."
 
while true; do
  echo "--- Incoming POST Request [$(date '+%Y-%m-%d %H:%M:%S')] ---" | tee -a "${LOG_FILE}"
  nc -l "${PORT}" | tee -a "${LOG_FILE}"
  echo -e "
" | tee -a "${LOG_FILE}"
done

Method 3: Returning Valid HTTP 200 OK Responses

Many webhook providers treat connections as failed if the server hangs or closes the TCP socket without returning a valid HTTP status header. Use a FIFO named pipe to send an immediate HTTP/1.1 200 OK response back to the client:

netcat-http-responder.shbash
#!/usr/bin/env bash
# Netcat HTTP Mock Server with 200 OK Response
 
PORT=8080
PIPE="/tmp/netcat_fifo"
 
# Create named pipe FIFO if it doesn't exist
rm -f "${PIPE}"
mkfifo "${PIPE}"
 
echo "Netcat HTTP Responder active on port ${PORT}..."
 
while true; do
  cat << 'EOF' > "${PIPE}"
HTTP/1.1 200 OK
Content-Type: application/json
Connection: close
 
{"status": "success", "message": "Payload received"}
EOF
 
  nc -l "${PORT}" < "${PIPE}"
done

System Considerations & Privilege Limits

  • Privileged Ports (< 1024): Standard users cannot bind Netcat to port 80 or 443 without sudo privileges or assigning kernel Linux capabilities: sudo setcap cap_net_bind_service=+ep $(which nc).

  • Firewall Configuration (ufw): Ensure the target port is open for inbound connections: sudo ufw allow 8080/tcp.

  • Socket Binding Verification: Check active listeners using ss -tulpn | grep 8080 or lsof -i :8080.