Let’s see how to find visitor’s country by ip with koa 2 framework. We will be using https://ip-api.io to simplify the task.

Then we will stop web scrapers.

Please note, that latest Koa requires at least Node v7.6.0.

1
$ npm install --save koa request request-promise-native
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const request = require('request-promise-native');
const Koa = require('koa');
const app = new Koa();
app.use(ctx => {
try {
const geoData = JSON.parse(await request(`http://ip-api.io/json/${ ctx.ip }`));
ctx.body = geoData.country;
} catch(e) {
console.log('Error', e);
}
});
app.proxy = true; // set app.proxy to true if you have Nginx in front of Node
app.listen(3000);

That’s it. This allows you to show different pages to visitors from different countries.

Here we set app.proxy to true as I usually have Nginx in front of Node.js. I recommend it as Node is single-threaded and any slow client will block the event loop.

On the other hand Nginx in front of Node will deal with slow clients easily.

But https://ip-api.io can do so much more! For example it’s possible to prevent webscraping.

As you know, scrapers usually use TOR and public proxies. Ip-api.io checks TOR, public proxy and spammer databases and provides this information as well.

Full ip-api.io response looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
"ip": "89.174.100.189",
"country_code": "DE",
"country_name": "Germany",
"region_code": "BE",
"region_name": "Land Berlin",
"city": "Berlin",
"zip_code": "10249",
"time_zone": "Europe/Berlin",
"latitude": 52.5238,
"longitude": 13.4428,
"metro_code": 0,
"suspicious_factors": {
"is_proxy": false,
"is_tor_node": false,
"is_spam": false,
"is_suspicious": false
}
}

is_proxy, is_tor_node, is_spam are self-explanatory. is_suspicious is true when either of aforementioned fields is true.

So let’s also stop scrapers:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const request = require('request-promise-native');
const Koa = require('koa');
const app = new Koa();
app.use(ctx => {
try {
const geoData = JSON.parse(await request(`http://ip-api.io/json/${ ctx.ip }`));
if(geoData.suspicious_factors.is_suspicious) { // thou shalt not pass
ctx.status = 403;
} else {
ctx.body = geoData.country;
}
} catch(e) {
console.log('Error', e);
}
});
app.proxy = true;
app.listen(3000);