How to Get the External (Public) IP Address in Batch Script
Commands like ipconfig show your Local IP (the one your router assigned you), but they cannot see your Public IP (the one the internet sees). Your public IP is assigned by your ISP and is essential for setting up remote access, verifying VPN connectivity, or identifying your network's location. Since your computer doesn't "know" its public IP natively, a Batch script must "ask" an external server to report back what it sees. With modern Windows including curl, this task has become a simple one-line operation.
This guide will explain how to retrieve your public IP address using Batch.
Method 1: Using CURL (Fastest and Recommended)
curl is built into Windows 10/11 and can fetch data from "IP Echo" services instantly.
@echo off
setlocal
echo [NET] Querying public IP address...
echo.
set "PublicIP="
:: Check if curl is available
where curl >nul 2>&1
if %errorlevel% neq 0 (
echo [ERROR] curl is not available on this system. Use Method 2 ^(PowerShell^) instead.
pause
endlocal
exit /b 1
)
:: Try primary service with a timeout to prevent hanging
for /f "tokens=*" %%a in ('curl -s --connect-timeout 5 --max-time 10 https://ifconfig.me 2^>nul') do set "PublicIP=%%a"
if defined PublicIP goto :PrintIP
:: If primary fails, try a fallback service
echo [WARN] Primary service unavailable. Trying fallback...
for /f "tokens=*" %%a in ('curl -s --connect-timeout 5 --max-time 10 https://api.ipify.org 2^>nul') do set "PublicIP=%%a"
if defined PublicIP goto :PrintIP
:: If fallback also fails, try a third service
echo [WARN] Fallback unavailable. Trying third service...
for /f "tokens=*" %%a in ('curl -s --connect-timeout 5 --max-time 10 https://ident.me 2^>nul') do set "PublicIP=%%a"
:PrintIP
:: Validate final result
if not defined PublicIP (
echo [ERROR] Could not retrieve public IP. Check your internet connection.
) else (
echo Your Public IP is: %PublicIP%
)
pause
endlocal
--connect-timeout and --max-time?Without timeouts, curl will hang indefinitely if you lose internet connectivity or the service is down. --connect-timeout 5 gives up connecting after 5 seconds, and --max-time 10 caps the entire operation at 10 seconds.
Method 2: Using PowerShell (The Fallback)
If curl isn't available (older Windows versions), PowerShell can make a web request to retrieve the same information.
@echo off
setlocal
echo [QUERY] Calling external provider...
echo.
set "PublicIP="
:: -NoProfile speeds up PowerShell startup
:: UseBasicParsing avoids dependency on Internet Explorer engine
:: TimeoutSec prevents hanging on network issues
for /f "delims=" %%a in ('powershell -NoProfile -Command ^
"try { (Invoke-WebRequest -Uri 'https://api.ipify.org' -UseBasicParsing -TimeoutSec 10).Content.Trim() } catch { try { (Invoke-WebRequest -Uri 'https://ident.me' -UseBasicParsing -TimeoutSec 10).Content.Trim() } catch { Write-Output 'ERROR' } }"') do set "PublicIP=%%a"
:: Validate the result
if not defined PublicIP (
echo [ERROR] PowerShell returned no output.
pause
endlocal
exit /b 1
)
if /i "%PublicIP%"=="ERROR" (
echo [ERROR] Could not retrieve public IP. Check your internet connection.
pause
endlocal
exit /b 1
)
echo Detected IP: %PublicIP%
pause
endlocal
-UseBasicParsing?Without this flag, Invoke-WebRequest tries to use the Internet Explorer DOM parsing engine. On systems where IE has been removed (Windows 11) or on Server Core installations, this causes the command to fail. -UseBasicParsing makes it work everywhere.
Method 3: The "Log and Alert" Pattern
If you have a dynamic IP that changes often, you can run this script daily (via Task Scheduler) to track changes and alert on unexpected shifts.
@echo off
setlocal enabledelayedexpansion
set "LogFile=%USERPROFILE%\ip_history.log"
:: Get current IP with timeout
set "current_ip="
for /f "tokens=*" %%a in ('curl -s --connect-timeout 5 --max-time 10 https://api.ipify.org 2^>nul') do set "current_ip=%%a"
:: Fallback service
if not defined current_ip (
for /f "tokens=*" %%a in ('curl -s --connect-timeout 5 --max-time 10 https://ident.me 2^>nul') do set "current_ip=%%a"
)
:: Validate
if not defined current_ip (
echo [%date% %time%] ERROR: Could not retrieve public IP. >> "%LogFile%"
echo [ERROR] Could not retrieve public IP. Check internet connection.
endlocal
exit /b 1
)
:: Read the last known IP from the log file
set "last_ip="
if exist "%LogFile%" (
for /f "tokens=4 delims=- " %%L in ('type "%LogFile%" ^| findstr /v "ERROR" ^| more +0') do (
set "last_ip=%%L"
)
)
:: Append to log with timestamp
echo [%date% %time%] - %current_ip% >> "%LogFile%"
:: Compare and alert if changed
if defined last_ip (
if /i "!current_ip!" neq "!last_ip!" (
echo [ALERT] IP has CHANGED!
echo Previous: !last_ip!
echo Current: !current_ip!
) else (
echo [OK] IP unchanged: !current_ip!
)
) else (
echo [INFO] First run. IP recorded: !current_ip!
)
echo [DONE] IP logged to: %LogFile%
endlocal
Method 4: IPv4 vs. IPv6 Specific Queries
Some ISPs assign both IPv4 and IPv6 addresses. This method retrieves both explicitly.
@echo off
setlocal
echo [NET] Querying both IPv4 and IPv6 addresses...
echo.
set "IPv4="
set "IPv6="
:: Query IPv4 specifically
for /f "tokens=*" %%a in ('curl -s -4 --connect-timeout 5 --max-time 10 https://api.ipify.org 2^>nul') do set "IPv4=%%a"
:: Query IPv6 specifically
for /f "tokens=*" %%a in ('curl -s -6 --connect-timeout 5 --max-time 10 https://api64.ipify.org 2^>nul') do set "IPv6=%%a"
echo --- Results ---
echo.
if defined IPv4 (
echo [IPv4] %IPv4%
) else (
echo [IPv4] Not available or not supported by your ISP.
)
if defined IPv6 (
echo [IPv6] %IPv6%
) else (
echo [IPv6] Not available or not supported by your ISP.
)
echo.
pause
endlocal
How to Avoid Common Errors
Wrong Way: Using ipconfig
Running ipconfig will never show your public IP. It only shows the addresses on your local network cards (usually starting with 192.168... or 10.0...).
Correct Way: Always query an external API. Your computer exists behind a NAT (Network Address Translation) wall in your router, and you must step outside that wall to see your true public address.
Wrong Way: Using curl Without Timeouts
Without timeout flags, curl will hang indefinitely if the internet connection drops or the API service is down, freezing your entire script.
Correct Way: Always add both connection and total timeouts:
curl -s --connect-timeout 5 --max-time 10 https://ifconfig.me
Wrong Way: Using a Single API Service
Any external service can go down. If your script depends on a single provider, it becomes a single point of failure.
Correct Way: Build fallback logic that tries a second (and third) service if the first one fails. Method 1 demonstrates this pattern.
Problem: API Downtime
If the service you are querying is down, your script will hang or return an error.
Solution: Use services known for high uptime (api.ipify.org, ident.me, ifconfig.me), add timeouts, and implement fallback chains as shown in Methods 1 and 2.
Problem: Invoke-WebRequest Fails on Windows 11 / Server Core
Without -UseBasicParsing, PowerShell's Invoke-WebRequest tries to use the Internet Explorer DOM engine, which may not exist on modern systems.
Solution: Always include -UseBasicParsing:
powershell -Command "(Invoke-WebRequest -Uri 'https://api.ipify.org' -UseBasicParsing).Content"
Best Practices and Rules
1. Privacy Warning
Every time you run this script, you are sending a request to an external server. That server now has a record of your IP and the time you checked it. For most users, this is harmless, but for high-security environments, you should use an internal corporate IP check service if available.
2. IPv4 vs. IPv6
Some services return your newer IPv6 address if your ISP supports it. If you specifically need the older IPv4 format, use curl -4 or a dedicated IPv4 endpoint like https://api.ipify.org (IPv4 only) vs. https://api64.ipify.org (may return IPv6). Method 4 demonstrates querying both explicitly.
3. Handle Timeouts
When using curl, always add timeouts to prevent your script from freezing:
curl -s --connect-timeout 5 --max-time 10 https://ifconfig.me
4. Use HTTPS
Always query API services over https:// rather than http://. An unencrypted HTTP request could be intercepted or modified by a man-in-the-middle, returning a spoofed IP address.
5. Log File Location
Avoid using %CD% for log files, it depends on where the script is launched from and may point to a system directory or a read-only location. Use %USERPROFILE% or %TEMP% instead for reliable write access.
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
Getting your external public IP address is a fundamental task for remote management and network verification. By leveraging the power of curl and public IP APIs, you transform your Batch scripts into network-aware tools that can adapt to changing ISP assignments. This automated visibility ensures that you always know your machine's identity on the global internet, allowing for seamless remote connectivity and reliable network auditing.