Explain Codes LogoExplain Codes Logo

Finding local IP addresses using Python's stdlib

python
networking
stdlib
ip-address
Nikita BarsukovbyNikita Barsukov·Dec 29, 2024
TLDR

A quick solution to get your local IP address leveraging Python's in-built socket library:

import socket def get_local_ip(): with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s: s.connect(('10.255.255.255', 1)) # The IP equivalent of "the middle of nowhere" IP = s.getsockname()[0] return IP print(get_local_ip()) # Voila! Here's your local IP.

This piece of wonder is actually using a non-routable meta-address to trick your system's network stack into reveaing the local IP address. No packets are sent during this manoeuvre.

Making it foolproof: Handling edge cases and exceptions

Network's down? Here's a fallback

In spaceships where an internet connection isn't available or during apocalyptic scenarios where a local proxy intercepts all traffic, the code above might hiccup. For such adventures, let's wear an exception handling belt:

def get_local_ip_safe(): try: return get_local_ip() except Exception: # When there's no IP, we return to the comfort of home return '192.168.1.1' # Put your default local IP here print(get_local_ip_safe())

Party for all: Finding all local IPs

In machines that are throwing a LAN party with multiple local IPs, here's a nifty trick to get them all to the dance floor:

def get_all_local_ips(): ips = socket.gethostbyname_ex(socket.gethostname())[2] # We don't invite the loopback; he always talks to himself return [ip for ip in ips if not ip.startswith("127.")] print(get_all_local_ips())

This will send out an exclusive invite to all non-loopback IPs.

Who am I? Retrieving network hostnames

Knowing your home (hostname) is as important as knowing your name (IP address).

def get_hostname(): # It's not vanity, it's necessity return socket.getfqdn() print(get_hostname())

For those wondering, this gives you the fully qualified domain name of your machine.

Unplugged but not forgotten: Working without internet

Sometimes, you just need to know your local IP, even when you are offline. Here's how to get that:

def get_local_ip_offline(): # Using the loopback as a mirror to see ourselves local_ip = '127.0.0.1' for ip in socket.getaddrinfo(socket.gethostname(), None): if ip[0] == socket.AddressFamily.AF_INET: local_ip = ip[4][0] break return local_ip print(get_local_ip_offline())

Leveling up: Handling IPv6

You're not going to stay on IPv4 forever, are you? Jump into the modern era with IPv6 addresses:

def get_local_ipv6(): with socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) as s: s.connect(('2001:db8::', 1)) # Ask for the postman's (IPv6) address, get your own instead ip_v6 = s.getsockname()[0] return ip_v6 print(get_local_ipv6())

A word of caution - this needs IPv6 connectivity.

All in one: Combining for a complete view

The Swiss Army Knife of IP address lookup. This one provides a comprehensive outlook:

def get_complete_local_ips(): # Why have one when you can have them all? ip_info = { "IPv4": get_all_local_ips(), "IPv6": get_local_ipv6() } return ip_info print(get_complete_local_ips())

This could be your go-to method if you need both IPv4, IPv6 and multiple local addresses.

Address limitations and other considerations

Understanding reliability across different environments

Remember, just like a good joke, these methods could vary in reliability. Depending on factors like VPN usage, virtual network interfaces, OS-level nuances, the results could be inconsistent. Keep your wits about you!

When to consult external wisdom

While stdlib is great, sometimes you need to consult the elders. External libraries like netifaces might be necessary for complex network configurations, though it compromises our independence.

The outer world: Checking public IP addresses

If you are more of an extrovert and want to find your public-facing IP (as seen by the world), you need different tools, either a web service or router configurations. Unfortunately, Python's stdlib can only get you so far.