Skip to main content

How to Check if IPv6 is Enabled in Batch Script

IPv6 is the modern standard for internet addressing, and Windows relies on it for many core features like DirectAccess, Nearby Sharing, and modern peer-to-peer networking. However, in some legacy environments, IPv6 is intentionally disabled to avoid compatibility issues. For a system administrator, knowing whether IPv6 is active on a specific network adapter is critical for ensuring application compatibility. A Batch script can query the network interface status to verify if the IPv6 stack is bound to the card and actively communicating.

This guide will explain how to audit IPv6 availability using native Batch and PowerShell.

Method 1: Using Netsh (Quick Status Check)

The netsh command can check if the IPv6 protocol is recognized on a specific interface.

@echo off
setlocal enabledelayedexpansion

set "Adapter=Ethernet"

echo [AUDIT] Checking IPv6 status for: "%Adapter%"...
echo.

:: First verify the adapter name exists
netsh interface show interface "%Adapter%" >nul 2>&1
if !errorlevel! neq 0 (
echo [ERROR] Adapter "%Adapter%" not found.
echo.
echo Available interfaces:
netsh interface show interface
pause
endlocal
exit /b 1
)

:: Check if IPv6 is recognized on this adapter
set "IPv6Found=0"

:: Query IPv6 interface list and look for our adapter
netsh interface ipv6 show interface "%Adapter%" >nul 2>&1
if !errorlevel! equ 0 (
set "IPv6Found=1"
)

:: Also check for an actual fe80: address as confirmation
set "HasAddress=0"
for /f "delims=" %%L in ('ipconfig ^| findstr /i "fe80:"') do (
set "HasAddress=1"
)

if !IPv6Found! equ 1 (
echo [OK] IPv6 is ENABLED on "%Adapter%".
if !HasAddress! equ 1 (
echo [OK] Link-Local address detected - IPv6 is actively working.
) else (
echo [WARN] IPv6 is enabled but no Link-Local address found.
echo The adapter may be disconnected or IPv6 may not be functioning.
)
) else (
echo [ALERT] IPv6 is DISABLED or not recognized on "%Adapter%".
)

pause
endlocal
Why check for both interface recognition AND an address?

An adapter can have IPv6 "enabled" in its properties but not have an active address if the cable is unplugged or the driver is malfunctioning. Checking for an actual fe80: address confirms the protocol is not just enabled but working.

Method 2: Detecting via IPCONFIG (The "Presence" Check)

If an adapter is truly running IPv6, it will always have at least one address (usually starting with fe80:). This method checks all adapters at once.

@echo off
setlocal enabledelayedexpansion

echo [SCAN] Scanning all adapters for IPv6 status...
echo.

set "IPv6Count=0"
set "AdapterCount=0"

:: Count IPv6 addresses found across all adapters
for /f "delims=" %%L in ('ipconfig ^| findstr /i /c:"IPv6 Address" /c:"Link-local IPv6"') do (
set /a IPv6Count+=1
)

:: Count active adapters
for /f "delims=" %%L in ('ipconfig ^| findstr /i /c:"adapter"') do (
set /a AdapterCount+=1
)

echo Active adapters found: !AdapterCount!
echo IPv6 addresses detected: !IPv6Count!
echo.

if !IPv6Count! gtr 0 (
echo [OK] IPv6 is actively running on this system.
echo.
echo --- IPv6 Addresses ---
ipconfig | findstr /i /c:"IPv6 Address" /c:"Link-local IPv6"
echo ----------------------
) else (
echo [WARN] No active IPv6 addresses detected on any adapter.
echo IPv6 may be disabled system-wide or on all active adapters.
)

pause
endlocal

Method 3: Deep Protocol Audit (PowerShell Bridge)

If you need to know if the protocol is technically "enabled" (checked in the adapter properties GUI) versus just having an address, PowerShell's Get-NetAdapterBinding is the most accurate tool.

@echo off
setlocal EnableDelayedExpansion

echo ============================================================
echo Deep IPv6 Protocol Binding Audit
echo ============================================================
echo.
echo Computer: %COMPUTERNAME%
echo Date: %date% %time%
echo.
echo ============================================================
echo.

echo [AUDIT] Analyzing IPv6 configuration across all network adapters...
echo.

:: Create PowerShell script for better readability
set "PSScript=%TEMP%\ipv6_audit_%RANDOM%.ps1"

(
echo try {
echo $adapters = Get-NetAdapter -ErrorAction SilentlyContinue ^|
echo Where-Object { $_.Status -eq 'Up' -or $_.Status -eq 'Disconnected' }
echo
echo if (-not $adapters^) {
echo Write-Host '[ERROR] No network adapters found.' -ForegroundColor Red
echo exit 1
echo }
echo
echo Write-Host "============================================================" -ForegroundColor Cyan
echo Write-Host " Network Adapter IPv6 Status" -ForegroundColor Cyan
echo Write-Host "============================================================" -ForegroundColor Cyan
echo Write-Host ""
echo
echo # Header
echo $header = "{0,-4} {1,-30} {2,-15} {3,-12} {4,-12} {5}" -f
echo 'STAT', 'ADAPTER NAME', 'STATUS', 'IPv6 BOUND', 'HAS ADDRESS', 'IPv6 ADDRESS'
echo Write-Host $header -ForegroundColor White
echo Write-Host ('-' * 100^) -ForegroundColor Gray
echo
echo $warnings = 0
echo $totalAdapters = 0
echo $boundAdapters = 0
echo $activeIPv6 = 0
echo
echo foreach ($a in $adapters^) {
echo $totalAdapters++
echo
echo # Check if IPv6 protocol is bound (enabled in properties^)
echo $binding = Get-NetAdapterBinding -Name $a.Name -ComponentID ms_tcpip6 -ErrorAction SilentlyContinue
echo $isBound = if ($binding^) { $binding.Enabled } else { $false }
echo
echo if ($isBound^) { $boundAdapters++ }
echo
echo # Check for actual IPv6 address
echo $ipv6Addresses = Get-NetIPAddress -InterfaceIndex $a.InterfaceIndex -AddressFamily IPv6 -ErrorAction SilentlyContinue ^|
echo Where-Object { $_.AddressState -eq 'Preferred' }
echo
echo $linkLocal = $ipv6Addresses ^| Where-Object { $_.IPAddress -like 'fe80::*' } ^| Select-Object -First 1
echo $globalAddr = $ipv6Addresses ^| Where-Object { $_.IPAddress -notlike 'fe80::*' -and $_.IPAddress -notlike 'ff*' } ^| Select-Object -First 1
echo
echo $hasAddr = [bool]$linkLocal -or [bool]$globalAddr
echo
echo if ($hasAddr^) { $activeIPv6++ }
echo
echo # Determine address to display
echo if ($globalAddr^) {
echo $addrStr = $globalAddr.IPAddress + " (Global^)"
echo } elseif ($linkLocal^) {
echo $addrStr = $linkLocal.IPAddress + " (Link-Local^)"
echo } else {
echo $addrStr = "None"
echo }
echo
echo # Determine status icon
echo if ($isBound -and $hasAddr^) {
echo $icon = "[OK]"
echo $color = "Green"
echo } elseif ($isBound -and -not $hasAddr^) {
echo $icon = "[!!]"
echo $color = "Yellow"
echo } else {
echo $icon = "[--]"
echo $color = "Gray"
echo }
echo
echo # Display row
echo $row = "{0,-4} {1,-30} {2,-15} {3,-12} {4,-12} {5}" -f
echo $icon,
echo ($a.Name.Substring(0, [Math]::Min(28, $a.Name.Length^)^)^),
echo $a.Status,
echo $isBound,
echo $hasAddr,
echo $addrStr
echo
echo Write-Host $row -ForegroundColor $color
echo
echo # Add warnings
echo if ($isBound -and -not $hasAddr -and $a.Status -eq 'Up'^) {
echo Write-Host " WARNING: IPv6 bound but no address - check connectivity" -ForegroundColor Yellow
echo $warnings++
echo }
echo
echo if (-not $isBound -and $a.Status -eq 'Up'^) {
echo Write-Host " INFO: IPv6 disabled on this active adapter" -ForegroundColor Cyan
echo }
echo }
echo
echo Write-Host ('-' * 100^) -ForegroundColor Gray
echo Write-Host ""
echo
echo # Check for IPv6 tunneling adapters
echo Write-Host "============================================================" -ForegroundColor Cyan
echo Write-Host " IPv6 Transition Technologies" -ForegroundColor Cyan
echo Write-Host "============================================================" -ForegroundColor Cyan
echo Write-Host ""
echo
echo $tunnels = Get-NetAdapter -ErrorAction SilentlyContinue ^|
echo Where-Object { $_.InterfaceDescription -match 'Teredo^|6to4^|ISATAP' }
echo
echo if ($tunnels^) {
echo Write-Host "Detected IPv6 transition adapters:" -ForegroundColor Yellow
echo foreach ($t in $tunnels^) {
echo Write-Host (" - {0}" -f $t.Name^) -ForegroundColor Yellow
echo Write-Host (" Type: {0}" -f $t.InterfaceDescription^) -ForegroundColor Gray
echo Write-Host (" Status: {0}" -f $t.Status^) -ForegroundColor Gray
echo
echo $binding = Get-NetAdapterBinding -Name $t.Name -ComponentID ms_tcpip6 -ErrorAction SilentlyContinue
echo if ($binding -and $binding.Enabled^) {
echo Write-Host " Bound: Yes (providing IPv6 over IPv4^)" -ForegroundColor Gray
echo }
echo }
echo Write-Host ""
echo Write-Host "NOTE: These provide IPv6 over IPv4 tunneling, not native IPv6" -ForegroundColor Cyan
echo } else {
echo Write-Host "No IPv6 transition adapters detected" -ForegroundColor Green
echo }
echo
echo Write-Host ""
echo
echo # Summary statistics
echo Write-Host "============================================================" -ForegroundColor Cyan
echo Write-Host " Summary" -ForegroundColor Cyan
echo Write-Host "============================================================" -ForegroundColor Cyan
echo Write-Host ""
echo Write-Host ("Total Adapters: {0}" -f $totalAdapters^)
echo Write-Host ("IPv6 Bound (Enabled^): {0}" -f $boundAdapters^)
echo Write-Host ("Active IPv6 Addresses: {0}" -f $activeIPv6^)
echo Write-Host ("Warnings: {0}" -f $warnings^)
echo Write-Host ""
echo
echo # Overall assessment
echo if ($warnings -gt 0^) {
echo Write-Host "Assessment: WARNINGS FOUND" -ForegroundColor Yellow
echo Write-Host "Action: Investigate flagged adapters" -ForegroundColor Yellow
echo exit 1
echo } elseif ($activeIPv6 -eq 0 -and $boundAdapters -gt 0^) {
echo Write-Host "Assessment: IPv6 ENABLED BUT NOT FUNCTIONAL" -ForegroundColor Yellow
echo Write-Host "Action: Check network connectivity and router configuration" -ForegroundColor Yellow
echo exit 1
echo } elseif ($boundAdapters -eq 0^) {
echo Write-Host "Assessment: IPv6 DISABLED" -ForegroundColor Cyan
echo Write-Host "Info: IPv6 is not enabled on any adapters" -ForegroundColor Cyan
echo exit 0
echo } else {
echo Write-Host "Assessment: PASS" -ForegroundColor Green
echo Write-Host "Info: IPv6 configuration appears normal" -ForegroundColor Green
echo exit 0
echo }
echo
echo } catch {
echo Write-Host "ERROR: Failed to query network adapters" -ForegroundColor Red
echo Write-Host ("Error: {0}" -f $_.Exception.Message^) -ForegroundColor Red
echo exit 2
echo }
) > "%PSScript%"

:: Execute PowerShell script
powershell -NoProfile -ExecutionPolicy Bypass -File "%PSScript%"
set "AuditResult=!errorlevel!"

:: Cleanup
del "%PSScript%" >nul 2>&1

echo.
echo ============================================================
echo Audit Complete
echo ============================================================
echo.

if !AuditResult! equ 0 (
echo Result: PASS
) else if !AuditResult! equ 1 (
echo Result: WARNING - Review flagged items
) else (
echo Result: ERROR - Unable to complete audit
)

echo.
pause
endlocal
exit /b !AuditResult!
What does "bound" mean?

In Windows networking, a protocol is "bound" to an adapter when the checkbox is checked in the adapter's properties dialog (ncpa.cpl → Right-click → Properties → "Internet Protocol Version 6"). A bound protocol should generate addresses; if it's bound but has no address, something is wrong.

Method 4: Registry-Level Check (System-Wide IPv6 Status)

IPv6 can be disabled system-wide via a registry key. This checks the actual system configuration regardless of individual adapter settings.

@echo off
setlocal EnableDelayedExpansion

echo ============================================================
echo IPv6 System-Wide Registry Configuration Audit
echo ============================================================
echo.
echo Computer: %COMPUTERNAME%
echo Date: %date% %time%
echo.
echo ============================================================
echo.

set "RegKey=HKLM\SYSTEM\CurrentControlSet\Services\Tcpip6\Parameters"
set "RegValue=DisabledComponents"

echo [AUDIT] Checking registry configuration...
echo.
echo Registry Key: %RegKey%
echo Registry Value: %RegValue%
echo.

:: Query the registry for the IPv6 disable flag
set "DisableFlag="
for /f "skip=2 tokens=3" %%a in (
'reg query "%RegKey%" /v "%RegValue%" 2^>nul'
) do (
set "DisableFlag=%%a"
)

if not defined DisableFlag (
echo ============================================================
echo Result: Default Configuration
echo ============================================================
echo.
echo [OK] Registry value "%RegValue%" is NOT set
echo.
echo This is the default Windows configuration.
echo IPv6 is ENABLED at the system level.
echo.
echo What this means:
echo - IPv6 is active on all network adapters
echo - Both native and tunnel interfaces are enabled
echo - System can use IPv6 for network communication
echo.
set "ConfigStatus=ENABLED_DEFAULT"

) else (
echo ============================================================
echo Result: Custom Configuration Detected
echo ============================================================
echo.
echo Registry Value: %RegValue% = !DisableFlag!
echo.

:: Convert hex to decimal for easier comparison
set "DecValue="
for /f %%d in ('powershell -NoProfile -Command "[Convert]::ToInt32('!DisableFlag!'.Replace('0x',''^^), 16)"') do set "DecValue=%%d"

if defined DecValue (
echo Decimal Value: !DecValue!
echo.
)

:: Interpret the value based on Microsoft documentation
:: Reference: https://support.microsoft.com/kb/929852

if /i "!DisableFlag!"=="0xff" (
echo ============================================================
echo IPv6 Status: COMPLETELY DISABLED
echo ============================================================
echo.
echo [CRITICAL] All IPv6 components are DISABLED system-wide
echo.
echo Disabled Components:
echo - All IPv6 interfaces ^(physical and virtual^)
echo - All IPv6 tunnel interfaces ^(Teredo, 6to4, ISATAP^)
echo - IPv6 protocol stack
echo - IPv6 routing
echo.
echo Impact:
echo - No IPv6 connectivity possible
echo - Only IPv4 will be used for all network traffic
echo - Some modern applications may have reduced functionality
echo.
set "ConfigStatus=FULLY_DISABLED"

) else if /i "!DisableFlag!"=="0x20" (
echo ============================================================
echo IPv6 Status: DISABLED ON NON-TUNNEL INTERFACES
echo ============================================================
echo.
echo [WARNING] IPv6 is disabled on physical/native interfaces
echo.
echo Disabled:
echo - IPv6 on Ethernet adapters
echo - IPv6 on Wi-Fi adapters
echo - Native IPv6 connectivity
echo.
echo Still Enabled:
echo - IPv6 tunnel interfaces ^(Teredo, 6to4^)
echo - IPv6 over IPv4 tunneling
echo.
echo Impact:
echo - No native IPv6 connectivity
echo - Tunneled IPv6 may still work
echo - Prefer IPv4 over IPv6
echo.
set "ConfigStatus=NATIVE_DISABLED"

) else if /i "!DisableFlag!"=="0x10" (
echo ============================================================
echo IPv6 Status: TUNNEL INTERFACES DISABLED
echo ============================================================
echo.
echo [INFO] IPv6 tunnel interfaces are disabled
echo.
echo Disabled:
echo - Teredo tunneling
echo - 6to4 tunneling
echo - ISATAP
echo.
echo Still Enabled:
echo - Native IPv6 on physical adapters
echo - Link-local IPv6 addresses
echo - IPv6 routing
echo.
echo Impact:
echo - Native IPv6 works normally
echo - IPv6 over IPv4 tunneling blocked
echo - Improved security ^(tunnels often bypassed^)
echo.
set "ConfigStatus=TUNNELS_DISABLED"

) else if /i "!DisableFlag!"=="0x1" (
echo ============================================================
echo IPv6 Status: TUNNELS DISABLED ^(Alternate Value^)
echo ============================================================
echo.
echo [INFO] IPv6 tunnel interfaces disabled ^(value 0x1^)
echo.
echo Similar to 0x10 - disables IPv6 transition technologies
echo.
set "ConfigStatus=TUNNELS_DISABLED_ALT"

) else if /i "!DisableFlag!"=="0x0" (
echo ============================================================
echo IPv6 Status: EXPLICITLY ENABLED
echo ============================================================
echo.
echo [OK] IPv6 is fully enabled ^(explicitly set to 0^)
echo.
echo All IPv6 components are active:
echo - Native IPv6 on all adapters
echo - Tunnel interfaces enabled
echo - Full IPv6 protocol stack
echo.
set "ConfigStatus=ENABLED_EXPLICIT"

) else if /i "!DisableFlag!"=="0x11" (
echo ============================================================
echo IPv6 Status: PREFER IPv4, TUNNELS DISABLED
echo ============================================================
echo.
echo [INFO] Combined configuration ^(0x10 + 0x01^)
echo.
echo Configuration:
echo - Prefer IPv4 over IPv6
echo - Tunnel interfaces disabled
echo - Native IPv6 still functional
echo.
set "ConfigStatus=PREFER_IPV4"

) else (
echo ============================================================
echo IPv6 Status: CUSTOM CONFIGURATION
echo ============================================================
echo.
echo [INFO] Non-standard DisabledComponents value detected
echo.
echo Value: !DisableFlag! (Decimal: !DecValue!^)
echo.
echo Common values:
echo 0x00 ^(0^) = All enabled
echo 0x01 ^(1^) = Tunnels disabled ^(method 1^)
echo 0x10 ^(16^) = Tunnels disabled ^(method 2^)
echo 0x11 ^(17^) = Prefer IPv4, tunnels off
echo 0x20 ^(32^) = Native IPv6 disabled
echo 0xFF ^(255^) = All IPv6 disabled
echo.
echo Reference: Microsoft KB929852
echo.
set "ConfigStatus=CUSTOM"
)
)

echo.

:: Check IPv6 prefix policy (preference settings)
echo ============================================================
echo IPv6 Prefix Policy Check
echo ============================================================
echo.
echo [CHECK] Analyzing IPv6 preference settings...
echo.

:: Check if IPv4-mapped IPv6 addresses are present (indicates IPv4 preference)
netsh interface ipv6 show prefixpolicy 2>nul | findstr /C:"::ffff:0:0" >nul 2>&1

if !errorlevel! equ 0 (
echo [INFO] IPv4-mapped prefix detected in policy table
echo.
echo This may indicate:
echo - System prefers IPv4 over IPv6 for dual-stack connections
echo - IPv6 has lower priority in DNS resolution
echo.
echo View full policy:
echo netsh interface ipv6 show prefixpolicy
echo.
) else (
echo [OK] No explicit IPv4 preference detected
echo.
)

:: Summary
echo ============================================================
echo Summary
echo ============================================================
echo.
echo Configuration: !ConfigStatus!
echo.

if "!ConfigStatus!"=="ENABLED_DEFAULT" (
echo Assessment: IPv6 is using default Windows configuration
echo Action: No changes needed unless IPv6 is not required
set "ExitCode=0"

) else if "!ConfigStatus!"=="ENABLED_EXPLICIT" (
echo Assessment: IPv6 is explicitly enabled
echo Action: Configuration is clear and intentional
set "ExitCode=0"

) else if "!ConfigStatus!"=="FULLY_DISABLED" (
echo Assessment: IPv6 is completely disabled
echo Action: Enable IPv6 if needed, or document this decision
set "ExitCode=1"

) else if "!ConfigStatus!"=="TUNNELS_DISABLED" (
echo Assessment: Security-focused configuration
echo Action: Tunnels disabled, native IPv6 works
set "ExitCode=0"

) else (
echo Assessment: Custom configuration in use
echo Action: Review and document this setting
set "ExitCode=0"
)

echo.
echo ============================================================
echo.

pause
endlocal
exit /b %ExitCode%
Why check the registry?

Group Policy can disable IPv6 via the DisabledComponents registry value without changing individual adapter bindings. An adapter might show IPv6 as "bound" in its properties, but the system-level registry override prevents it from functioning. This is common in corporate environments.

How to Avoid Common Errors

Wrong Way: Assuming a ::1 Ping Test Is Enough

Pinging ::1 (IPv6 localhost) will work even if your network adapter has IPv6 disabled. This only tests the software stack, not the physical connection.

Correct Way: Use Method 1 or Method 3 to check the specific binding on the network adapter. This tells you if actual traffic can flow out of the computer using IPv6.

Wrong Way: Checking "IPv6 Enabled" Without Checking for an Address

An adapter can have IPv6 enabled in its properties but not have an active address: if the cable is unplugged, the driver is broken, or a registry override is blocking it.

Correct Way: Check both the binding status (is IPv6 enabled?) AND the presence of an fe80: address (is it actually working?). Method 3 does both.

Wrong Way: Hardcoding the Adapter Name

"Ethernet" on your machine might be "Ethernet 2," "Local Area Connection," or "Wi-Fi" on another machine.

Correct Way: Either enumerate all adapters automatically (Methods 2–3) or validate the adapter name before using it:

netsh interface show interface "%Adapter%" >nul 2>&1
if %errorlevel% neq 0 echo Adapter not found.

Problem: Multiple Adapters

Identifying the status of "IPv6" globally is misleading if it's enabled on Ethernet but disabled on the Wi-Fi adapter you're actually using.

Solution: Always either specify the adapter name or enumerate all adapters with their individual status (Method 3).

Best Practices and Rules

1. Verify "Preferred" Protocol

Sometimes IPv6 is enabled but the system prefers IPv4. Check which protocol is used first:

:: If this returns an IPv4 address, your system prefers IPv4
nslookup google.com 2>nul | findstr "Address"

To check the prefix policy (which determines IPv4 vs. IPv6 preference):

netsh interface ipv6 show prefixpolicy

2. Administrator Privileges

Querying adapter bindings (Get-NetAdapterBinding) and deep netsh properties usually requires running the script as an Administrator. Basic ipconfig checks (Method 2) work without elevation.

3. Identify Tunneling Adapters

Watch out for 6to4, Teredo, or ISATAP tunneling adapters. These "virtual" adapters provide IPv6 connectivity over an IPv4 connection. Your report should distinguish between native hardware IPv6 and these transition technologies. Method 3 automatically detects and flags tunneling adapters.

4. Registry Override Awareness

Corporate Group Policy can disable IPv6 system-wide via the DisabledComponents registry key without changing adapter bindings. Always check Method 4 if per-adapter checks show IPv6 as enabled but it's not functioning.

5. Don't Disable IPv6 Without Reason

Microsoft officially states that IPv6 is a mandatory part of Windows and disabling it may cause issues. Features that depend on IPv6 include:

  • DirectAccess VPN
  • Nearby Sharing
  • Windows Peer Name Resolution (PNRP)
  • Some Windows Update scenarios

6. 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.

Conclusions

Checking if IPv6 is enabled is a foundational step in modern network troubleshooting. By moving beyond legacy IPv4 checks and verifying the binding status of the modern protocol stack, you gain the clarity needed to resolve connectivity issues and maintain compatibility with modern applications. This professional auditing ensures that your network infrastructure is fully utilizing the capabilities of the Windows operating system.