Skip to content

How to Get Open TCP and UDP Ports in Batch Script

Use Batch scripts with netstat to scan, audit, and map open TCP/UDP ports to processes for security monitoring and troubleshooting on Windows.

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

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

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

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

Port Service Notes
80 HTTP Web server. Should only be open if intentional
443 HTTPS Secure web server
3389 RDP Remote Desktop. High security risk if exposed
445 SMB File sharing. Frequent malware target
3306 MySQL Database. Should never face the internet
5432 PostgreSQL Database

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.

Navigation