Get IP address of visitors using Flask for Python
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
In Flask, the simplest way to get a visitor's IP address is request.remote_addr. That answer is only fully correct when Flask is receiving the client connection directly, though, because reverse proxies and load balancers change what Flask sees as the remote peer.
Direct Requests: Use request.remote_addr
For a basic Flask app running without a proxy in front of it, the client IP is available on the request object:
If you call this app directly from a browser or a local HTTP client, request.remote_addr is usually the address you want to log.
Why Proxies Change the Answer
In production, Flask is often behind Nginx, a cloud load balancer, or another reverse proxy. In that setup, the TCP connection reaching Flask comes from the proxy, not from the original browser.
So if you read request.remote_addr without any proxy configuration, you may get:
- the local reverse proxy address
- the load balancer address
- another internal hop instead of the real visitor IP
That is expected behavior. Flask only sees the immediate peer unless you explicitly tell it which forwarded headers to trust.
The Safe Way Behind a Proxy
Flask applications behind a trusted reverse proxy should use Werkzeug's ProxyFix middleware with the correct number of proxy hops:
After that middleware is configured correctly, request.remote_addr reflects the forwarded client address rather than the local proxy address.
Do Not Trust X-Forwarded-For Blindly
Beginners often read the header directly:
That is unsafe unless you control the proxy chain and configure trust boundaries correctly. Clients can send fake forwarded headers themselves. ProxyFix exists so the application can trust only the expected number of proxy layers instead of treating arbitrary headers as facts.
If you must inspect the raw header for diagnostics, treat it as untrusted input until your deployment setup guarantees who set it.
Logging the IP Address
A common use case is request logging:
That is useful for:
- operational debugging
- rate limiting
- abuse detection
- rough geographic analytics
Be careful, though. IP addresses are sensitive data in many privacy regimes, so only log them when there is a clear purpose.
IPv4, IPv6, and Local Testing
Do not assume every address is IPv4. Flask may return IPv6 loopback or client addresses depending on the network path.
For example, local development can show values such as:
- '
127.0.0.1' - '
::1'
Your code should treat the IP as an address string, not as "always dotted IPv4 text."
A Practical Rule
Use this decision process:
- no proxy in front of Flask: read
request.remote_addr - trusted proxy in front of Flask: configure
ProxyFix, then readrequest.remote_addr - untrusted forwarded headers: do not treat them as the real client IP
That keeps the code simple and avoids accidental spoofing bugs.
Common Pitfalls
The most common mistake is reading request.remote_addr behind a reverse proxy and assuming the returned address is the real browser IP. Often it is only the proxy's address.
Another issue is trusting X-Forwarded-For directly from request headers. Unless the application is configured to trust a known proxy chain, that header can be forged by the client.
People also forget IPv6. Code that assumes every IP contains dots instead of colons eventually breaks in real deployments.
Summary
- '
request.remote_addris the normal way to get the client IP in Flask.' - Behind a reverse proxy, configure
ProxyFixso Flask can trust forwarded address information correctly. - Do not trust forwarded headers blindly from the raw request.
- Treat IP values as generic address strings that may be IPv4 or IPv6.
- Use IP logging carefully and only when it serves a real operational need.

