By Shamoon


2011-11-12 21:56:50 8 Comments

How can I determine the IP address of a given request from within a controller? For example (in express):

app.post('/get/ip/address', function (req, res) {
    // need access to IP address here
})

16 comments

@Ben Davies 2015-08-03 20:41:20

request.headers['x-forwarded-for'] || request.connection.remoteAddress

If the x-forwarded-for header is there then use that, otherwise use the .remoteAddress property.

The x-forwarded-for header is added to requests that pass through load balancers (or other types of proxy) set up for HTTP or HTTPS (it's also possible to add this header to requests when balancing at a TCP level using proxy protocol). This is because the request.connection.remoteAddress the property will contain the private IP address of the load balancer rather than the public IP address of the client. By using an OR statement, in the order above, you check for the existence of an x-forwarded-for header and use it if it exists otherwise use the request.connection.remoteAddress.

@user10898116 2019-06-15 22:05:02

Warning:

Don't just blindly use this for important rate-limiting:

let ip = request.headers['x-forwarded-for'].split(',')[0];

It's very easy to spoof:

curl --header "X-Forwarded-For: 1.2.3.4" "https://example.com"

In that case ther user's real IP address will be:

let ip = request.headers['x-forwarded-for'].split(',')[1];

I'm surprised that no other answers have mentioned this.

@Alexandru 2018-12-17 16:29:38

In node 10.14 , behind nginx, you can retrieve the ip by requesting it through nginx header like this:

proxy_set_header X-Real-IP $remote_addr;

Then in your app.js:

app.set('trust proxy', true);

After that, wherever you want it to appear:

var userIp = req.header('X-Real-IP') || req.connection.remoteAddress;

@Misha Nasledov 2018-09-12 01:01:17

I realize this has been answered to death, but here's a modern ES6 version I wrote that follows airbnb-base eslint standards.

const getIpAddressFromRequest = (request) => {
  let ipAddr = request.connection.remoteAddress;

  if (request.headers && request.headers['x-forwarded-for']) {
    [ipAddr] = request.headers['x-forwarded-for'].split(',');
  }

  return ipAddr;
};

The X-Forwarded-For header may contain a comma-separated list of proxy IPs. The order is client,proxy1,proxy2,...,proxyN. In the real world, people implement proxies that may supply whatever they want in this header. If you are behind a load balancer or something, you can at least trust the first IP in the list is at least whatever proxy some request came through.

@Mansi Teharia 2018-03-22 04:34:27

There are two ways to get the ip address :

  1. let ip = req.ip

  2. let ip = req.connection.remoteAddress;

But there is a problem with above approaches.

If you are running your app behind Nginx or any proxy, every single IP addresses will be 127.0.0.1.

So, the best solution to get the ip address of user is :-

let ip = req.header('x-forwarded-for') || req.connection.remoteAddress;

@Edmar Miyake 2013-10-22 17:52:29

var ip = req.headers['x-forwarded-for'] || 
     req.connection.remoteAddress || 
     req.socket.remoteAddress ||
     (req.connection.socket ? req.connection.socket.remoteAddress : null);

Note that sometimes you can get more than one IP address in req.headers['x-forwarded-for']. Also, an x-forwarded-for header will not always be set which may throw an error.

The general format of the field is:

x-forwarded-for: client, proxy1, proxy2, proxy3

where the value is a comma+space separated list of IP addresses, the left-most being the original client, and each successive proxy that passed the request adding the IP address where it received the request from. In this example, the request passed through proxy1, proxy2, and then proxy3. proxy3 appears as remote address of the request.

This is the solution suggested by Arnav Gupta with a fix Martin has suggested below in the comments for cases when x-forwarded-for is not set :

var ip = (req.headers['x-forwarded-for'] || '').split(',').pop() || 
         req.connection.remoteAddress || 
         req.socket.remoteAddress || 
         req.connection.socket.remoteAddress

@Domi 2014-05-27 11:21:56

How to prevent spoofing of these headers though?

@reconbot 2014-07-06 22:22:26

If you're behind a proxy that sets these headers it will append to the end of the list of addresses. The last one will be set by your proxy, the previous ones may come from previous load balancers or "spoofed" from the client. I imagine you could tell your LB to overwrite the header as well.

@Matt Browne 2014-11-14 20:02:40

This usually works well but for some reason I recently got the error "Cannot read property 'remoteAddress' of undefined" because apparently everything was null/undefined, including req.connection.socket. I'm not sure why/what conditions cause that to be the case but it would be good to check that req.connection.socket exists to avoid your server crashing if this happens.

@yAnTar 2014-12-18 16:57:06

Last line req.connection.socket.remoteAddress throwing error. Be carefully.

@Shimon Doodkin 2015-02-12 22:21:43

to log precisely it is a good idea to log everything. i could send forwarded for for myself and not use any proxy and you will delete my address, replace with my value.

@Sanjay 2015-03-02 05:35:20

Very noob I am here, but would like to ask, Im very new here, what is req? What does that req object holds, or how should I initiate req object so that I can use req.headers etc.

@markthethomas 2015-03-05 00:08:06

^ you'll want to learn what the core node web server-related modules are, as well as what express is expressjs.com

@Apha 2015-07-07 16:28:56

To remove the unwanted stuff and just getting the IP address use regular expression. var IP = (req.headers['x-forwarded-for'] || req.connection.remoteAddress).match("[0-9]+.[0-9].+[0-9]+.[0‌​-9]+$")[0];

@Niro 2015-10-23 03:15:52

Heads up: the regexp will only work on IPv4 and should not be used in production.

@Jeffz 2015-10-23 20:29:08

Good answer. Can someone concisely explain, why req.connection.remoteAddress returns something to the tune of :ffff::10.101.214.230 instead of IP? It seems like IPV6 condensed on a priv network IP number.

@Tim 2016-01-26 13:58:27

My way inspired by you guys! var user_ip = false; if (req.headers['x-forwarded-for']) { user_ip = req.headers['x-forwarded-for'].split(', ')[0]; } user_ip = user_ip || req.connection.remoteAddress || req.socket.remoteAddress || req.connection.socket.remoteAddress;

@Bagusflyer 2016-02-11 03:10:48

The returned ip address is ::1. Why?

@Andrei Shostik 2016-06-26 15:49:13

@bagusflyer this is your localhost IP address

@kurumkan 2016-10-30 13:42:27

Please tell me why you use this sequence? ``` req.headers['x-forwarded-for'] || req.connection.remoteAddress || req.socket.remoteAddress || req.connection.socket.remoteAddress;``` I don't understand - why is this particular order?

@Arnav Gupta 2017-01-05 07:34:57

Best case scenario is var ip = req.headers['x-forwarded-for'].split(',').pop() || req.connection.remoteAddress || req.socket.remoteAddress || req.connection.socket.remoteAddress

@Michel 2018-04-11 02:09:19

Looking at the way pop() works, it seems like you are going to get the last proxy and not the client which is what you want. Am I wrong?

@Steve Kehlet 2018-04-19 01:40:29

I agree @Michel I would use shift()

@Martin 2018-05-16 12:29:40

Issue: Error occurs when x-forwarded-for returns undefined. Fix: Add || "" after header reading. So finally: var ip = (req.headers['x-forwarded-for'] || '').split(',').pop() ...

@Kurt Van den Branden 2018-11-20 09:35:29

Surprised no one mentions this one. You need to trim your array results in case x-forwarded-for returns multiple ips. Otherwise you get an invalid ip address with a leading whitespace. Do it like req.headers['x-forwarded-for'] || '').split(',').pop().trim(); or do the split with a comma and space split(, )

@Ruben Serrate 2019-10-21 09:57:03

That's not right, that'll give you the last proxy before it hit your server, not the client's IP, which is the first ip in the array. req.headers['x-forwarded-for'] || '').split(',')[0] is the client's IP

@IT Vlogs 2017-11-05 03:23:46

Simple get remote ip in nodejs:

var ip = req.header('x-forwarded-for') || req.connection.remoteAddress;

@Kirill Chatrov 2017-10-12 15:28:10

If you get multiple IPs , this works for me:

var ipaddress = (req.headers['x-forwarded-for'] || 
req.connection.remoteAddress || 
req.socket.remoteAddress || 
req.connection.socket.remoteAddress).split(",")[0];

@Jason Sebring 2017-03-12 16:10:12

If using express...

req.ip

I was looking this up then I was like wait, I'm using express. Duh.

@topek 2011-11-12 22:07:29

In your request object there is a property called connection, which is a net.Socket object. The net.Socket object has a property remoteAddress, therefore you should be able to get the IP with this call:

request.connection.remoteAddress

See documentation for http and net

EDIT

As @juand points out in the comments, the correct method to get the remote IP, if the server is behind a proxy, is request.headers['x-forwarded-for']

@Shamoon 2011-11-12 22:23:29

This gives me an IP address different from what whatismyip.com gives me. Why would that be?

@topek 2011-11-12 22:34:32

You mean that you are connecting from localhost? What does it give you?

@Shamoon 2011-11-12 22:36:18

I have my API service installed on a no.de instance. When I try to access it from my computer, I get an IP address of "10.2.XXX.YYY" whereas my real world IP is "67.250.AAA.BBB"

@topek 2011-11-12 22:48:16

That means you are behind a proxy. Try to get the HTTP_X_FORWARDED header, which should be sent by the proxy, with req.headers['HTTP_X_FORWARDED']

@topek 2011-11-12 23:00:24

That's bad. Still you may want to investigate the headers, maybe there is another useful one. If this does not help, I would ask the no.de support.

@SuitedSloth 2011-11-13 00:42:27

it's request.headers['X-Forwarded-For']

@monsur 2013-03-01 05:02:28

Note that net.Stream is now net.Socket, and the documentation lives here: nodejs.org/api/net.html#net_class_net_socket

@FueledPublishing 2014-10-22 10:51:56

For anyone whose interested, for Heroku it's: request.headers['x-forwarded-for']

@Pier-Luc Gendreau 2015-01-13 08:28:35

@FueledPublishing This is true for all hosts behind a load balancer. Which is pretty much every single Node.js host out there.

@knutole 2015-03-27 18:45:07

is it possible to spoof request.connection.remoteAddress, or is this safe to use as guard for accepting IP connections?

@ninjaneer 2015-05-03 22:37:29

doesn't seem to work sometimes. I'm getting undefined for some clients (mostly from web crawlers/bots/exploit scanners). why?

@Didier68 2018-09-11 16:40:58

Try the "request-ip" module written by @pbojinov ! It takes care of several cases: 'x-client-i, x-cluster-client-ip, x-forwarded,...

@Sergei Kovalenko 2019-10-21 19:59:35

By the standards, request.headers['x-forwarded-for'] should be filled by the proxies in the following format: <client-ip>, <proxy-ip>, <proxy-ip>, ... So, the first one in the list is the required address. But some proxies do not follow the standards, and then you have to investigate. Some (most of them) add another custom header, containing the client ip. I'd recommend to parse X-Forwarded-For in your app, and analyze custom header afterwards. And only if they didn't give you a valid IP, use request.connection.remoteAddress || '127.0.0.1'

@Ahmad Agbaryah 2017-02-07 14:27:41

function getCallerIP(request) {
    var ip = request.headers['x-forwarded-for'] ||
        request.connection.remoteAddress ||
        request.socket.remoteAddress ||
        request.connection.socket.remoteAddress;
    ip = ip.split(',')[0];
    ip = ip.split(':').slice(-1); //in case the ip returned in a format: "::ffff:146.xxx.xxx.xxx"
    return ip;
}

@Ahmad Agbaryah 2017-09-14 08:29:18

You are right, if you want the ip as string, then you can replace the last line with: ip = ip.split(':').slice(-1)[0]

@ashishyadaveee11 2016-06-08 08:25:47

Following Function has all the cases covered will help

var ip;
if (req.headers['x-forwarded-for']) {
    ip = req.headers['x-forwarded-for'].split(",")[0];
} else if (req.connection && req.connection.remoteAddress) {
    ip = req.connection.remoteAddress;
} else {
    ip = req.ip;
}console.log("client IP is *********************" + ip);

@ThomasReggi 2016-10-06 00:15:40

Note the ips are have a , between for me.

@aCo 2016-01-11 20:56:24

Had the same problem...im also new at javascript but i solved this with req.connection.remoteAddress; that gave me th IP address (but in ipv6 format ::ffff.192.168.0.101 ) and then .slice to remove the 7 first digits.

var ip = req.connection.remoteAddress;

if (ip.length < 15) 
{   
   ip = ip;
}
else
{
   var nyIP = ip.slice(7);
   ip = nyIP;
}

@Radek 2016-01-12 12:50:31

this is not a good method, as ipv6 is NOT just 7 digits + IPv4, but can be totally different.

@unsynchronized 2016-07-22 01:10:10

@Radek if you validate the start of the address, it conforms to spec(see en.wikipedia.org/wiki/IPv6_address ctrl-f search for "IPv4-mapped") ip= (ip.length<15?ip:(ip.substr(0,7)==='::ffff:'?ip.substr(7):un‌​defined)) would replace the if... in above code

@unsynchronized 2016-07-22 01:15:39

i personally wrap getClientIp() from npm request-ip to create function getClientIp4(req){ var ip=typeof req==='string'?req:getClientIp(req); return (ip.length<15?ip:(ip.substr(0,7)==='::ffff:'?ip.substr(7):un‌​defined)); } which accepts either a previously fetched ip, or a request object as input and gives ip or undefined as a result

@un33k 2014-10-11 02:14:28

You can stay DRY and just use node-ipware that supports both IPv4 and IPv6.

Install:

npm install ipware

In your app.js or middleware:

var getIP = require('ipware')().get_ip;
app.use(function(req, res, next) {
    var ipInfo = getIP(req);
    console.log(ipInfo);
    // { clientIp: '127.0.0.1', clientIpRoutable: false }
    next();
});

It will make the best attempt to get the user's IP address or returns 127.0.0.1 to indicate that it could not determine the user's IP address. Take a look at the README file for advanced options.

@Nepoxx 2015-03-13 13:15:05

" or returns 127.0.0.1 to indicate that it could not determine the user's IP address" There is quite a big difference between 127.0.0.1 and unknown...

@Nilloc 2015-04-11 05:15:59

It returned something weird for me :ffff:(not my IP address) when tested from Heroku. @edmar-miyake's answer is working properly for me.

@un33k 2015-04-15 20:54:44

I wonder what the would IP be if you were to use the right2left lookup in the 'x-forwarded-for' case. var ip_info = get_ip(req, right_most_proxy=True), as in some setup, the client IP might be the right most IP.

@JamEngulfer 2016-01-11 11:48:28

That method is returning clientIp: '::1' for me. It doesn't seem to work.

@un33k 2016-03-01 16:33:03

@JamEngulfer - ipware only works if the ip address is properly passed down to your app via request.headers[ ]. example: AWS LBS send the Ip address in 'x-forwarded-for' while custom NginX many use other variables. ipware makes the best attempt to figure the IP address out, but only if the IP has been passed down in the headers.

@JamEngulfer 2016-03-02 09:35:37

Oh. That's a shame. My application was receiving the web traffic directly, so I guess that's not possible.

@Giorgio 2017-10-19 11:37:50

checking the source code of the package request-ip at github.com/pbojinov/request-ip/blob/master/index.js it seems more complete than the package ipware since it checks x-forwarded-for and all sorts of other headers

@pbojinov 2015-06-09 20:44:05

You can use request-ip, to retrieve a user's ip address. It handles quite a few of the different edge cases, some of which are mentioned in the other answers.

Disclosure: I created this module

Install:

npm install request-ip

In your app:

var requestIp = require('request-ip');

// inside middleware handler
var ipMiddleware = function(req, res, next) {
    var clientIp = requestIp.getClientIp(req); // on localhost > 127.0.0.1
    next();
};

Hope this helps

@Giorgio 2017-10-19 11:39:45

checking the source code of the package request-ip at github.com/pbojinov/request-ip/blob/master/index.js it checks x-forwarded-for and all sorts of other headers for popular load balancers like AWS ELB, Cloudflare, Akamai, nginx, Rackspace LB and Riverbed's Stingray

@S.M_Emamian 2019-06-18 10:00:02

it returns null for me.

@Prathamesh More 2020-01-24 07:35:02

The same thing instead use request.headers['x-forwarded-for']

@Michael Lang 2015-02-10 20:10:26

If you're using express version 3.x or greater, you can use the trust proxy setting (http://expressjs.com/api.html#trust.proxy.options.table) and it will walk the chain of addresses in the x-forwarded-for header and put the latest ip in the chain that you've not configured as a trusted proxy into the ip property on the req object.

Related Questions

Sponsored Content

23 Answered Questions

[SOLVED] How to uninstall npm modules in node js?

  • 2012-10-25 10:23:26
  • Manish Kumar
  • 980868 View
  • 983 Score
  • 23 Answer
  • Tags:   node.js npm

38 Answered Questions

[SOLVED] How do I debug Node.js applications?

32 Answered Questions

[SOLVED] How do I update each dependency in package.json to the latest version?

  • 2013-04-18 02:39:04
  • Raine Revere
  • 841041 View
  • 1908 Score
  • 32 Answer
  • Tags:   node.js npm

31 Answered Questions

8 Answered Questions

18 Answered Questions

[SOLVED] How to exit in Node.js

  • 2011-03-10 21:30:05
  • Bryan Field
  • 863144 View
  • 1801 Score
  • 18 Answer
  • Tags:   node.js

10 Answered Questions

[SOLVED] Proper way to return JSON using node or Express

12 Answered Questions

[SOLVED] What is the purpose of Node.js module.exports and how do you use it?

  • 2011-03-15 11:56:10
  • mrwooster
  • 472760 View
  • 1408 Score
  • 12 Answer
  • Tags:   javascript node.js

17 Answered Questions

[SOLVED] How to decide when to use Node.js?

20 Answered Questions

[SOLVED] nodejs vs node on ubuntu 12.04

Sponsored Content