How to get client IP address using python bottle framework

user3414814 picture user3414814 · Jul 14, 2015 · Viewed 10.8k times · Source

I need client IP address using python. I have tried below code but its not working in server:

from socket import gethostname, gethostbyname 
ip = gethostbyname(gethostname()) 
print ip

On the server, I get '127.0.0.1' every time. Is there any way to find IP address of the client?

Answer

ron rothman picture ron rothman · Jul 15, 2015

You're getting the IP address of your server, not of your server's clients.

You want to look at the request's REMOTE_ADDR, like this:

from bottle import Bottle, request

app = Bottle()

@app.route('/hello')
def hello():
    client_ip = request.environ.get('REMOTE_ADDR')
    return ['Your IP is: {}\n'.format(client_ip)]

app.run(host='0.0.0.0', port=8080)

EDIT #1: Some folks have observed that, for them, the value of REMOTE_ADDR is always the same IP address (usually 127.0.0.1). This is because they're behind a proxy (or load balancer). In this case, the client's original IP address is typically stored in header HTTP_X_FORWARDED_FOR. The following code will work in either case:

@app.route('/hello')
def hello():
    client_ip = request.environ.get('HTTP_X_FORWARDED_FOR') or request.environ.get('REMOTE_ADDR')
    return ['Your IP is: {}\n'.format(client_ip)]

EDIT #2: Thanks to @ArtOfWarfare's comment, I learned that REMOTE_ADDR is not required per PEP-333. Couple of observations:

  • The CGI spec does require REMOTE_ADDR:

The REMOTE_ADDR variable MUST be set to the network address of the client sending the request to the server.

  • However, PEP-333 does not explicitly require HTTP_REMOTE_ADDR, only going as far as this (emphasis mine):

A server or gateway SHOULD attempt to provide as many other CGI variables as are applicable.

  • All of the (admittedly few) web frameworks that I'm familiar with set HTTP_REMOTE_ADDR. AFAICT, it's a de facto "standard." But technically, YMMV.