How to Programmatically Retrieve Your Public IP Address in Linux Shell Scripts


12 views

When working with network configurations in Linux, it's crucial to distinguish between private and public IP addresses. Private IPs (like those shown by ifconfig or hostname -i) are used within local networks, while public IPs are what the internet sees.

Here are several reliable methods to fetch your public IP address in shell scripts:


# Using curl with common IP lookup services
curl ifconfig.me
curl icanhazip.com
curl ipinfo.io/ip
curl api.ipify.org

# Using wget alternative
wget -qO- ifconfig.me/ip

# DNS-based method (works without internet tools)
dig +short myip.opendns.com @resolver1.opendns.com

For production scripts, you should implement fallback mechanisms when one service is unavailable:


#!/bin/bash

get_public_ip() {
  local services=(
    "ifconfig.me"
    "icanhazip.com"
    "ipinfo.io/ip"
    "api.ipify.org"
  )
  
  for service in "${services[@]}"; do
    if ip=$(curl -s --connect-timeout 5 $service); then
      echo "$ip"
      return 0
    fi
  done
  
  return 1
}

public_ip=$(get_public_ip)
if [[ -n "$public_ip" ]]; then
  echo "Public IP: $public_ip"
else
  echo "Failed to retrieve public IP" >&2
  exit 1
fi

Consider these scenarios in your implementation:

  • Network connectivity issues
  • Rate limiting from IP services
  • IPv6 vs IPv4 addresses
  • Proxy or VPN configurations

For scripts that run frequently, you might want to cache the IP address:


#!/bin/bash

CACHE_FILE="/tmp/public_ip_cache"
CACHE_TIME=300 # 5 minutes in seconds

get_cached_ip() {
  if [[ -f "$CACHE_FILE" ]]; then
    local now=$(date +%s)
    local modified=$(stat -c %Y "$CACHE_FILE")
    if (( now - modified < CACHE_TIME )); then
      cat "$CACHE_FILE"
      return 0
    fi
  fi
  return 1
}

if ! cached_ip=$(get_cached_ip); then
  if new_ip=$(curl -s ifconfig.me); then
    echo "$new_ip" > "$CACHE_FILE"
    echo "$new_ip"
  else
    exit 1
  fi
else
  echo "$cached_ip"
fi

If you're on a cloud provider, you might have access to instance metadata:


# AWS EC2
curl http://169.254.169.254/latest/meta-data/public-ipv4

# Google Cloud
curl -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip

# Azure
curl -H "Metadata: true" http://169.254.169.254/metadata/instance/network/interface/0/ipv4/ipAddress/0/publicIpAddress?api-version=2021-02-01&format=text

While ifconfig and hostname -i display local network interfaces, they don't reveal your public-facing IP address. This becomes crucial when:

  • Configuring remote access solutions
  • Setting up dynamic DNS
  • Network troubleshooting
  • Security auditing

Here are reliable methods to fetch your public IP from various external services:

Using cURL with Public API Services


# Most reliable option (supports both IPv4/IPv6)
curl -s https://api.ipify.org

# Alternative services
curl -s https://checkip.amazonaws.com
curl -s https://ifconfig.me/ip
curl -s https://icanhazip.com

DNS-Based Approach


# Using Google's DNS service
dig +short myip.opendns.com @resolver1.opendns.com

# Alternative using Cloudflare
dig +short txt ch whoami.cloudflare @1.1.1.1

Here's a production-ready script with error handling:


#!/bin/bash

# Function to get public IP with fallback options
get_public_ip() {
  local services=(
    "https://api.ipify.org"
    "https://checkip.amazonaws.com"
    "https://ifconfig.me/ip"
  )
  
  for service in "${services[@]}"; do
    if ip=$(curl -s --connect-timeout 5 "$service"); then
      if [[ "$ip" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
        echo "$ip"
        return 0
      fi
    fi
  done
  
  # Fallback to DNS method
  if command -v dig &> /dev/null; then
    ip=$(dig +short myip.opendns.com @resolver1.opendns.com 2>/dev/null)
    if [[ "$ip" ]]; then
      echo "$ip"
      return 0
    fi
  fi
  
  echo "ERROR: Could not determine public IP" >&2
  return 1
}

# Usage example
public_ip=$(get_public_ip) || exit 1
echo "Public IP: $public_ip"

For environments with strict firewall rules or proxy configurations:


# Using proxy configuration
https_proxy=http://your.proxy:port curl -s https://api.ipify.org

# With explicit timeout settings
curl -s --connect-timeout 10 --max-time 15 https://api.ipify.org

Some services return IPv6 addresses by default. For IPv4-only requests:


curl -4s https://api.ipify.org

For scripts that run frequently, implement caching to avoid rate limits:


#!/bin/bash

CACHE_FILE="/tmp/public_ip.cache"
CACHE_TIME=300 # 5 minutes in seconds

get_cached_ip() {
  if [[ -f "$CACHE_FILE" ]]; then
    local now=$(date +%s)
    local modified=$(stat -c %Y "$CACHE_FILE")
    if (( now - modified < CACHE_TIME )); then
      cat "$CACHE_FILE"
      return 0
    fi
  fi
  return 1
}

if ! cached_ip=$(get_cached_ip); then
  if new_ip=$(curl -s https://api.ipify.org); then
    echo "$new_ip" > "$CACHE_FILE"
    cached_ip="$new_ip"
  else
    echo "Failed to refresh IP cache" >&2
    exit 1
  fi
fi

echo "Current public IP: $cached_ip"