Skip to main content

How to Get Open TCP and UDP Ports in Batch Script

Monitoring open network ports is a critical task for both security and troubleshooting. An unexpected open port could indicate a misconfigured server, a forgotten background service, or even malicious software (a "Backdoor"). Conversely, if you're trying to set up a web server or database but it won't connect, you need to verify if the port is actually "Listening." A Batch script can use the netstat command to list every active port, identifying which ones are TCP, which are UDP, and which specific application ID (PID) is using them.

This guide will explain how to audit local network ports.

Method 1: The Fast Port Audit (Netstat)

The netstat command with the -a (all), -n (numeric), and -o (owning PID) flags is the most efficient way to see your port status.

@echo off
setlocal

echo [PORT AUDIT] Scanning active TCP/UDP ports...
echo.

:: -a = All ports
:: -n = Numerical form (faster, doesn't resolve hostnames)
:: -o = Include the Process ID (PID)

echo === LISTENING TCP PORTS ===
echo.
echo PROTO LOCAL ADDRESS STATE PID
echo --------------------------------------------------
netstat -ano | findstr "LISTENING"
echo --------------------------------------------------

echo.
echo === ACTIVE UDP PORTS ===
echo.
echo PROTO LOCAL ADDRESS PID
echo --------------------------------------------------
netstat -ano | findstr "^ UDP"
echo --------------------------------------------------

pause
endlocal
Why list UDP separately?

UDP is connectionless, it has no "LISTENING" state. If you only filter for LISTENING, you will miss every UDP port on the system. The ^ UDP pattern matches lines that start with UDP (with leading spaces from netstat formatting).

Method 2: Finding a Specific Port

If you want to know if Port 80 (HTTP) or Port 3389 (Remote Desktop) is open, you can filter the results.

@echo off
setlocal

set "TargetPort=3389"
set "TempFile=%TEMP%\port_check.tmp"

echo [SCAN] Checking for activity on port %TargetPort%...
echo.

:: Use word boundary matching with \b to avoid false positives
:: e.g., searching for :80 would also match :8080, :800, :8000
:: Capture to temp file so we can both display and check the result
netstat -ano | findstr /R ":%TargetPort%[^0-9]" > "%TempFile%" 2>&1

:: Check if anything was found (findstr sets errorlevel BEFORE the pipe, not after)
:: Instead, check if the temp file has content
for %%F in ("%TempFile%") do set "FileSize=%%~zF"

if %FileSize% gtr 0 (
echo [FOUND] Port %TargetPort% is active:
echo.
type "%TempFile%"
) else (
echo [INFO] Port %TargetPort% is not currently in use.
)

:: Clean up
del "%TempFile%" >nul 2>&1

pause
endlocal
Why not just findstr ":%TargetPort%"?

Searching for :3389 would also match :33890, :33891, etc. The regex pattern :%TargetPort%[^0-9] ensures the port number is followed by a non-digit character (like a space), preventing false matches against longer port numbers.

Method 3: Mapping Ports to Application Names

Finding a PID like 1420 is only half the story. You want to know if that's Chrome, a system service, or an unknown process.

@echo off
setlocal enabledelayedexpansion

echo [REPORT] Mapping Listening Ports to Applications...
echo.
echo ADDRESS:PORT PID PROCESS NAME
echo =================================================================

:: Track seen PIDs to avoid duplicate tasklist lookups
set "seen_pids="

for /f "tokens=2,5" %%a in ('netstat -ano ^| findstr "LISTENING"') do (
set "addr=%%a"
set "pid=%%b"

:: Skip if PID is 0 (System Idle) or empty
if "!pid!" neq "0" if defined pid (
:: Look up the process name for this PID
for /f "tokens=1" %%n in ('tasklist /fi "pid eq !pid!" /fo table /nh 2^>nul ^| findstr /v "INFO:"') do (
rem Dynamically pad the address up to 36 spaces for a perfect visual column
set "padAddr=!addr! "
set "padAddr=!padAddr:~0,36!"

rem Dynamically pad the PID up to 11 spaces
set "padPid=!pid! "
set "padPid=!padPid:~0,11!"

echo !padAddr!!padPid!%%n
)
)
)

echo ================================================================
echo.
echo [TIP] Run as Administrator to see protected system service names.

pause
endlocal
note

Some system-level PIDs will show "INFO: No tasks are running which match the specified criteria" if you don't run the script as Administrator. The findstr /v "INFO:" filter suppresses these messages for cleaner output.

Method 4: Full Audit with Log File

For security monitoring, save a complete port snapshot to a timestamped file for later comparison.

@echo off
setlocal

:: Generate a timestamp for the filename
for /f "tokens=2 delims==" %%a in ('wmic os get localdatetime /value 2^>nul') do (
for /f "delims=" %%b in ("%%a") do set "dt=%%b"
)
set "timestamp=%dt:~0,4%-%dt:~4,2%-%dt:~6,2%_%dt:~8,2%%dt:~10,2%%dt:~12,2%"

set "LogDir=%USERPROFILE%\PortAudits"
set "LogFile=%LogDir%\ports_%timestamp%.txt"

:: Create log directory if it doesn't exist
if not exist "%LogDir%" mkdir "%LogDir%"

echo [AUDIT] Saving full port snapshot to:
echo %LogFile%
echo.

(
echo ========================================
echo PORT AUDIT - %date% %time%
echo Computer: %COMPUTERNAME%
echo ========================================
echo.
echo --- TCP PORTS ---
echo Proto Local Address Foreign Address State PID
netstat -ano | findstr "TCP"
echo.
echo --- UDP PORTS ---
echo Proto Local Address Foreign Address State PID
netstat -ano | findstr "UDP"
echo.
echo ========================================
) > "%LogFile%"

echo [OK] Snapshot saved. Compare with previous audits to detect changes.
echo.

:: If a previous audit exists, offer a quick comparison
set "PrevFile="
for /f "delims=" %%f in ('dir /b /o-d "%LogDir%\ports_*.txt" 2^>nul') do (
if defined PrevFile goto :compare
set "PrevFile=%%f"
:: Skip the first file (it's the one we just created)
set "PrevFile="
)
for /f "delims=" %%f in ('dir /b /o-d "%LogDir%\ports_*.txt" 2^>nul ^| more +1') do (
set "PrevFile=%%f"
goto :compare
)

:compare
if defined PrevFile (
echo [INFO] Previous audit found: %PrevFile%
echo [TIP] Use "fc %LogFile% %LogDir%\%PrevFile%" to compare changes.
) else (
echo [INFO] No previous audit found. This is your baseline.
)

pause
endlocal

How to Avoid Common Errors

Wrong Way: Using netstat -a Without -n

If you omit the -n flag, netstat will try to reverse-lookup every IP address into a domain name. This creates a massive amount of DNS traffic and can make your script hang for several minutes.

Correct Way: Always use -n. It makes the command instantly fast by keeping everything in numeric format.

Wrong Way: Only Filtering for "LISTENING"

UDP is connectionless, it never shows a "LISTENING" state. If you only search for LISTENING, you will completely miss all UDP ports on the system.

Correct Way: Filter for LISTENING to find TCP servers, and filter separately for UDP to find UDP services:

:: TCP listening ports
netstat -ano | findstr "LISTENING"

:: UDP active ports
netstat -ano | findstr "^ UDP"

Wrong Way: Searching for a Port Without Boundary Matching

Searching for :80 will also match :8080, :800, :8000, and any other port starting with 80.

Correct Way: Use a regex pattern that ensures the port number is followed by a non-digit:

netstat -ano | findstr /R ":80[^0-9]"

Problem: %errorlevel% After Piped Commands

When you pipe commands (netstat | findstr), the %errorlevel% reflects the last command in the pipe (findstr), not netstat. However, in some edge cases with FOR /F loops and pipes, errorlevel behavior can be inconsistent.

Solution: Redirect output to a temp file and check whether the file has content, rather than relying on errorlevel.

Best Practices and Rules

1. Administrative Privileges

While basic netstat works for everyone, only an Administrator can see the process names and full details for protected system services using netstat -b. Method 3 works for most processes but may show incomplete results without elevation.

2. Identify "0.0.0.0" vs "127.0.0.1"

  • 127.0.0.1: The port is only open to your own computer (localhost). Generally safe.
  • 0.0.0.0: The port is listening on all network interfaces, accessible from other machines on the network. Be extremely careful with these.

3. Log Changes Over Time

Periodically save your port list to a file for comparison. This allows you to spot "new" open ports that shouldn't be there. Method 4 provides a complete implementation of this approach.

4. Always Use setlocal / endlocal

Without setlocal, every variable your script creates persists in the parent shell session, causing potential conflicts when running multiple scripts in sequence.

5. Common Ports to Watch

PortServiceNotes
80HTTPWeb server. Should only be open if intentional
443HTTPSSecure web server
3389RDPRemote Desktop. High security risk if exposed
445SMBFile sharing. Frequent malware target
3306MySQLDatabase. Should never face the internet
5432PostgreSQLDatabase

Conclusions

Auditing open TCP and UDP ports is a foundational skill for maintaining a secure and functional Windows environment. By combining netstat with PID-to-task mapping, you gain deep visibility into how your machine interacts with the network. This automated monitoring ensures that you can quickly resolve connectivity bottlenecks and identify potential security vulnerabilities before they can be exploited.