Of course! The getaddrinfo function is a cornerstone of network programming in Python. It's a powerful and versatile tool that translates a human-friendly hostname (like google.com) and service name (like http) into a list of network addresses that your program can actually use to connect.

Here’s a comprehensive guide covering what it is, how to use it, and practical examples.
What is getaddrinfo?
getaddrinfo is a Python wrapper around the C library function of the same name. Its main job is to perform hostname resolution. It takes a host and a service and returns a list of tuples, where each tuple contains the information needed to create a socket connection.
Why is it so useful?
- Abstraction: You don't need to worry about whether an address is an IPv4 address (like
8.8.8) or an IPv6 address (like2001:4860:4860::8888).getaddrinfohandles both. - Service Resolution: You don't need to remember that port 80 is for
httpand port 443 is forhttps. You can just pass the service name ('http','https'). - Protocol Agnostic: It can find addresses for different socket types, like
SOCK_STREAM(TCP) andSOCK_DGRAM(UDP).
The Function Signature
import socket socket.getaddrinfo(host, port, family=0, type=0, proto=0, flags=0)
Parameters:

host: The hostname (e.g.,"www.google.com") or IP address (e.g.,"127.0.0.1"or"::1"). Can beNoneto use the local host.port: The port number (e.g.,80) or service name (e.g.,"http").family: The address family. The most common are:socket.AF_INET: For IPv4 addresses.socket.AF_INET6: For IPv6 addresses.socket.AF_UNSPEC: The default. It means "any family," so it will return both IPv4 and IPv6 addresses if available.
type: The socket type. The most common are:socket.SOCK_STREAM: For TCP (reliable, connection-oriented).socket.SOCK_DGRAM: For UDP (unreliable, connectionless).0: The default. It means "any type," so it will return results for both TCP and UDP.
proto: The protocol. Usually0(default), which means any protocol. Can besocket.IPPROTO_TCPorsocket.IPPROTO_UDP.flags: Optional flags to modify the behavior. The most common issocket.AI_ADDRCONFIG, which ensures you only get addresses for your machine's configured IP types (e.g., won't return IPv6 if you have no IPv6).
Return Value:
A list of 5-tuples. Each tuple contains the following information:
family: The address family (e.g.,socket.AF_INET).type: The socket type (e.g.,socket.SOCK_STREAM).proto: The protocol (e.g.,socket.IPPROTO_TCP).canonname: The canonical name of the host (often empty).sockaddr: A tuple containing the address and port. ForAF_INET, this is(address, port). ForAF_INET6, it's(address, port, flow_info, scope_id).
Basic Examples
Let's start with some simple, practical examples.
Example 1: Get IPv4 and TCP addresses for Google's homepage
This is the most common use case. We want to find the address to connect to google.com on the http port.

import socket
# Get address info for google.com on port 80 (http)
results = socket.getaddrinfo("google.com", "http")
print(f"Found {len(results)} potential addresses.\n")
for result in results:
family, socktype, proto, canonname, sockaddr = result
# We are only interested in TCP stream sockets
if socktype == socket.SOCK_STREAM:
print(f"Family: {family}, Type: {socktype}, Protocol: {proto}")
print(f" Socket Address: {sockaddr}")
print("-" * 20)
Typical Output:
Found 6 potential addresses.
Family: AddressFamily.AF_INET, Type: SocketKind.SOCK_STREAM, Protocol: 6
Socket Address: ('142.250.199.100', 80)
--------------------
Family: AddressFamily.AF_INET, Type: SocketKind.SOCK_STREAM, Protocol: 6
Socket Address: ('142.250.199.102', 80)
--------------------
Family: AddressFamily.AF_INET, Type: SocketKind.SOCK_STREAM, Protocol: 6
Socket Address: ('142.250.199.101', 80)
--------------------
Family: AddressFamily.AF_INET6, Type: SocketKind.SOCK_STREAM, Protocol: 6
Socket Address: ('2a00:1450:4001:81a::200e', 80, 0, 0)
--------------------
Family: AddressFamily.AF_INET6, Type: SocketKind.SOCK_STREAM, Protocol: 6
Socket Address: ('2a00:1450:4001:81a::2006', 80, 0, 0)
--------------------
Family: AddressFamily.AF_INET6, Type: SocketKind.SOCK_STREAM, Protocol: 6
Socket Address: ('2a00:1450:4001:81a::2004', 80, 0, 0)
--------------------
Notice how it returned both IPv4 and IPv6 addresses because we used the default AF_UNSPEC.
Example 2: Get only IPv4 addresses
What if you specifically want to connect using IPv4? You can specify the family.
import socket
# Get only IPv4 TCP addresses for google.com
results = socket.getaddrinfo("google.com", "http", family=socket.AF_INET, type=socket.SOCK_STREAM)
print(f"Found {len(results)} IPv4 TCP addresses.\n")
for result in results:
family, socktype, proto, canonname, sockaddr = result
print(f"Family: {family}, Type: {socktype}")
print(f" Socket Address: {sockaddr}")
print("-" * 20)
Typical Output:
Found 3 IPv4 TCP addresses.
Family: AddressFamily.AF_INET, Type: SocketKind.SOCK_STREAM
Socket Address: ('142.250.199.100', 80)
--------------------
Family: AddressFamily.AF_INET, Type: SocketKind.SOCK_STREAM
Socket Address: ('142.250.199.102', 80)
--------------------
Family: AddressFamily.AF_INET, Type: SocketKind.SOCK_STREAM
Socket Address: ('142.250.199.101', 80)
--------------------
How to Use the Result: A Practical Example
The real power of getaddrinfo is using it to create a socket connection. The sockaddr from the tuple is exactly what the socket.connect() method needs.
Here is a function that tries to connect to a host using the first available address from getaddrinfo. This is a robust way to handle connections.
import socket
def connect_to_host(hostname, port):
"""
Tries to connect to a host using the first available address from getaddrinfo.
"""
print(f"Attempting to connect to {hostname}:{port}...")
try:
# Get all possible addresses
addr_info_list = socket.getaddrinfo(hostname, port, family=socket.AF_UNSPEC, type=socket.SOCK_STREAM)
# Try each address until one works
for addr_info in addr_info_list:
family, socktype, proto, canonname, sockaddr = addr_info
print(f" Trying address: {sockaddr}")
s = None
try:
s = socket.socket(family, socktype, proto)
s.connect(sockaddr)
print(f" Successfully connected to {sockaddr}!")
return s # Return the connected socket object
except socket.error as e:
print(f" Failed to connect to {sockaddr}: {e}")
if s:
s.close()
# If we get here, no address worked
print("Could not connect to any address.")
return None
except socket.gaierror as e:
print(f"getaddrinfo error: {e}")
return None
except Exception as e:
print(f"An unexpected error occurred: {e}")
return None
# --- Usage ---
# Connect to a non-existent service to see it try multiple addresses
# sock = connect_to_host("google.com", "nonexistent-service")
# Connect to a real service
sock = connect_to_host("google.com", "http")
if sock:
print("\nConnection established. Sending a simple HTTP request...")
request = "GET / HTTP/1.1\r\nHost: google.com\r\nConnection: close\r\n\r\n"
sock.send(request.encode('utf-8'))
response = sock.recv(4096)
print("\n--- First 500 bytes of response ---")
print(response.decode('utf-8', errors='ignore')[:500])
sock.close()
Handling Errors
getaddrinfo can raise exceptions, so it's important to handle them.
-
socket.gaierror(Get Address Info Error): This is the most common error. It occurs when the hostname cannot be resolved.- Causes: Hostname doesn't exist, DNS server is down, typo in hostname.
- Example:
socket.gaierror: [Errno 8] nodename nor servname provided, or not known
-
socket.errororOSError: This can occur during the socket creation or connection phase, even ifgetaddrinfosucceeded.Causes: Connection refused, host is unreachable, network is down.
Summary
| Feature | Description |
|---|---|
| Purpose | Resolve a hostname/service into network addresses for socket connections. |
| Key Strength | Abstraction. Handles IPv4, IPv6, TCP, UDP, and service names automatically. |
| Return Value | A list of 5-tuples, where the last element (sockaddr) is used for socket.connect(). |
| Common Use Case | Use socket.getaddrinfo(host, port) and then iterate through the results to try connecting to each address until one succeeds. |
| Error Handling | Always wrap calls in a try...except socket.gaierror block to catch resolution failures. |
