Getting the public IP in Python — scripts, Django, FastAPI
Did you know that more than 70 % of developers never check the public IP their code is reaching out from? Whether you’re debugging a Jupyter notebook, deploying a Django app, or building a FastAPI micro‑service, knowing the external address of the machine can save you hours of mystery‑solving and keep your network security airtight.
1️⃣ Why Knowing Your Public IP Matters
Security & compliance – Detect unexpected NAT, VPN, or cloud‑provider IP changes that could break firewall rules. Geolocation & analytics – Tailor content or logging based on the server’s outward‑facing location. Debugging remote services – Quickly verify that third‑party APIs see the IP you expect (useful for rate‑limit whitelists).
2️⃣ Quick‑and‑Dirty One‑Liner Scripts
Sometimes you just need a quick check. The python community loves requests for its simplicity. If you don’t have it, pip install requests will get you going in seconds.
import requests, json, sys, os, time
try:
ip = requests.get("https://api.ipify.org?format=json", timeout=5).json()["ip"]
print(f"Your public IP is {ip}")
except Exception as e:
print(f"Could not fetch IP: {e}", file=sys.stderr)
And if you’re in an environment where requests is a no‑no, urllib.request is a solid fallback.
import urllib.request, json, sys
try:
with urllib.request.urlopen("https://api.ipify.org?format=json", timeout=5) as resp:
ip = json.loads(resp.read().decode())["ip"]
print(f"Your public IP is {ip}")
except Exception as e:
print(f"Could not fetch IP: {e}", file=sys.stderr)
Sound familiar? The same pattern repeats across scripts, Jupyter notebooks, and even simple automation tools. Just remember: a bare try/except keeps your script from crashing when the world goes down.
3️⃣ Integrating IP Retrieval into a Django Project
In my experience, a reusable utils/ip.py keeps things tidy. Below is a snippet that caches the result for the duration of a request, preventing multiple external calls.
# utils/ip.py
import asyncio
import httpx
from functools import lru_cache
IP_SERVICE = "https://api.ipify.org?format=json"
@lru_cache(maxsize=1)
def get_public_ip_sync():
try:
response = httpx.get(IP_SERVICE, timeout=3)
response.raise_for_status()
return response.json()["ip"]
except Exception:
return None
async def get_public_ip_async():
async with httpx.AsyncClient(timeout=3) as client:
try:
resp = await client.get(IP_SERVICE)
resp.raise_for_status()
return resp.json()["ip"]
except Exception:
return None
Now expose it via a view:
# views.py
from django.http import JsonResponse
from .utils.ip import get_public_ip_sync
def public_ip_view(request):
return JsonResponse({"public_ip": get_public_ip_sync()})
And add a tiny middleware to log the server’s outward address on every request:
# middleware.py
from .utils.ip import get_public_ip_sync
class PublicIPLoggingMiddleware:
def __init__(self, get_response):
self.get_response = get_response
self.server_ip = get_public_ip_sync()
def __call__(self, request):
print(f"[{request.path}] Server IP: {self.server_ip}")
return self.get_response(request)
Middleware is handy for audit trails, but keep it light. If your IP changes often (e.g., in a containerized environment), invalidate the cache or use a per‑request lookup instead.
4️⃣ Real‑World FastAPI Implementation (Step‑by‑Step Walkthrough)
FastAPI loves async. Let’s build a small service that returns the public IP and demonstrates dependency injection.
# main.py
from fastapi import FastAPI, Depends
import httpx
from functools import lru_cache
app = FastAPI()
@lru_cache(maxsize=1)
def get_httpx_client():
return httpx.AsyncClient(timeout=4)
async def fetch_ip(client: httpx.AsyncClient = Depends(get_httpx_client)):
try:
resp = await client.get("https://api.ipify.org?format=json")
resp.raise_for_status()
return resp.json()["ip"]
except Exception:
return None
@app.get("/ip")
async def read_ip():
ip = await fetch_ip()
return {"public_ip": ip}
Now spin it up in Docker for a quick test:
# Dockerfile
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
Build and run:
docker build -t ip-demo .
docker run --rm -p 8000:8000 ip-demo
When the container attaches to a bridge network, the IP returned will be the bridge’s gateway. If you switch to host network mode, the IP will match the host’s external address. Handy for testing network isolation.
5️⃣ Actionable Takeaways & Best Practices
- Cache vs. real‑time – If your infrastructure rarely changes IP (e.g., a static server), cache for life. If you run in a dynamic cloud environment, refresh on each request or every few minutes.
- Choosing a reliable IP‑service provider – ipify, ifconfig.me, and ipinfo.io all provide JSON endpoints. Compare uptime, rate limits, and response times.
- Security checklist – Never log the IP in a publicly accessible log file. Use HTTPS for all external requests. Respect rate limits; add exponential backoff if you hit a 429.
- Use environment variables – Keep service URLs in
.envfiles so you can switch providers without touching code. - Handle proxies – If your app sits behind a corporate proxy, use the
proxiesargument inhttpxorrequeststo forward the request correctly.
Frequently Asked Questions
How can I get my public IP address in a Jupyter notebook?
Install requests (!pip install requests) and run a one‑liner: !curl https://api.ipify.org. The cell will output the external IP, which you can store in a variable for later pandas or numpy analysis.
What Python library works best for async IP lookups in FastAPI?
httpx is the go‑to async HTTP client; it integrates smoothly with FastAPI’s async endpoints and supports connection pooling, timeouts, and HTTP/2 out of the box.
Is it safe to expose my server’s public IP in a Django admin view?
Only expose it to authenticated staff users and always serve the page over HTTPS. Mask the IP in logs or use a rate‑limited third‑party service to avoid enumeration attacks.
Why does requests.get('https://api.ipify.org') sometimes return a private IP?
If your environment sits behind a NAT or corporate proxy, the external service may see the proxy’s address. Use a service that returns the origin header or query the proxy directly if you need the true public IP.
Can I retrieve the public IP without an external service?
Purely local methods (e.g., socket.gethostbyname(socket.gethostname())) return only internal addresses. For a reliable public IP you need to ask an external endpoint, or use cloud‑provider metadata APIs (AWS, GCP, Azure).
Related reading: Original discussion
Related Articles
What do you think?
Have experience with this topic? Drop your thoughts in the comments - I read every single one and love hearing different perspectives!
Comments
Post a Comment