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


2 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"