13

I want to use the name of the country where I am now in a bash script. I can get the external IP using next command:

curl ifconfig.me

But how can I get my country name?

7
  • 3
  • @bhau I prefer not to install any package for doing this. Jul 18, 2013 at 10:44
  • @MichaelKjörling I want to get the country for my particular public IP address. Maybe sound strange, but I exlained why. Jul 18, 2013 at 10:59
  • @Radu What's wrong with installing a package?
    – jobukkit
    Jul 18, 2013 at 11:09
  • 1
    @Jop Just a guess, but maybe the OP doesn't have root access to the system? Installing a package, particularly if it brings in library dependencies which might refer to files by full path, can require root access.
    – user
    Jul 18, 2013 at 11:19

4 Answers 4

18

ipinfo.io has nice JSON API for using from command line:

$ curl ipinfo.io
{
  "ip": "X.X.X.X",
  "hostname": "No Hostname",
  "city": "Hanoi",
  "region": "Ha Noi",
  "country": "VN",
  "loc": "21.0333,105.8500",
  "org": "AS18403 The Corporation for Financing & Promoting Technology"
}
1
  • 7
    Elegantly getting just the country code using jq: curl -s ipinfo.io/ | jq ".country".
    – Pablo A
    Apr 14, 2019 at 2:00
15

You can get somewhat close by querying the public whois database. It'll likely be somewhat difficult to "productify" to handle every possible case, but a reasonable approximation might be:

$ whois a.b.c.d | grep -iE ^country:

where a.b.c.d is the IP address in question.

whois is often installed by default, so this meets a reasonable interpretation of your "I prefer not to install any package for doing this" read as "I don't want to install additional software".

To print only the value of the country field and force it to upper case only (to make comparisons easier, for example), you can do something like:

$ whois a.b.c.d | awk -F':[ \t]+' 'tolower($1) ~ /^country$/ { print toupper($2) }'
2
  • whois $(curl ifconfig.me) | grep -iE ^country: | awk '{print $2}' gives me what I want; thanks! Jul 18, 2013 at 11:32
  • 1
    @Radu You can save yourself one pipe by doing whois $(curl ifconfig.me) | awk 'tolower($1) ~ /^country:/ { print $2 }' instead.
    – user
    Jul 18, 2013 at 11:39
12

Use another IP locator than ifconfig.me that provides with that information like:

Not available anymore as of 2015-03-09

curl -s 'http://geoiplookup.net/geoapi.php?output=countrycode'

or:

curl -s 'http://geoiplookup.net/geoapi.php?output=country'

(see the API for details)

or:

curl -s http://whatismycountry.com/ |
  sed -n 's|.*,\(.*\)</h3>|\1|p'

or:

curl -s http://whatismycountry.com/ |
  sed -n 's|.*> *\(.*\)</h3>|\1|p'

for more precision, or:

curl -s http://whatismycountry.com/ |
  sed -n 's/.*Coordinates \(.*\)<.*/\1/p'

for the coordinates.

That makes assumptions on the HTML formatting of the page. So it may stop working if they decide to change that format in the future.

4
  • This is an excellent illustration of why it's a good idea to wait a little before accepting an answer. +1 from me.
    – user
    Jul 18, 2013 at 16:42
  • @MichaelKjörling ...I can see, but now I think that is not right for you to change the accepted answer. Jul 18, 2013 at 19:00
  • 1
    @Radu It's okay - if you feel this answer is more useful, Stephane deserves the accept (though I hope I'll get or keep an/the upvote from you :)). In general, it's usually a good idea to wait at least some 12-24 hours before accepting an answer, to give multiple people a chance to answer. Accepting an answer basically says "the question has been satisfactorily answered", reducing the incentive for others to add answers.
    – user
    Jul 18, 2013 at 19:06
  • 1
    Stéphane, doesn't work any more, but curl --silent https://whatismycountry.com/ grep --only-matching --perl-regexp 'Your Country is \K[^<]+' does.
    – Fabby
    Apr 26, 2018 at 14:17
2

In addition to ipinfo.io mention in the other answer, you could also use freegeoip.net as well, which seems to be officially using the publicly available code/database (which you can run on your own instance, if needed), and appears to have a higher limit for the number of requests -- 15k/hour, vs. 1k/day on ipinfo.io.

% curl -i ipinfo.io
HTTP/1.1 200 OK
Server: nginx
Date: Sun, 17 Sep 2017 02:17:47 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 240
Vary: Accept-Encoding
x-cloud-trace-context: 86d62d74c999fc62715d7dff810ea16c/9504640995707975809;o=0
Access-Control-Allow-Origin: *
X-Content-Type-Options: nosniff
Via: 1.1 google

{
  "ip": "88.198.54.xx",
  "hostname": "static.88-198-54-xx.clients.your-server.de",
  "city": "Nuremberg",
  "region": "Bavaria",
  "country": "DE",
  "loc": "49.4478,11.0683",
  "org": "AS24940 Hetzner Online GmbH",
  "postal": "90455"
}%
% curl -i freegeoip.net/json/
HTTP/1.1 200 OK
Date: Sun, 17 Sep 2017 02:17:54 GMT
Content-Type: application/json
Content-Length: 230
Connection: keep-alive
Set-Cookie: __cfduid=dacbae017e5ee70d57b251c89c4ba418b1505614674; expires=Mon, 17-Sep-18 02:17:54 GMT; path=/; domain=.freegeoip.net; HttpOnly
Vary: Origin
X-Database-Date: Thu, 07 Sep 2017 04:08:50 GMT
X-Ratelimit-Limit: 15000
X-Ratelimit-Remaining: 14996
X-Ratelimit-Reset: 2697
Server: cloudflare-nginx
CF-RAY: 39f89263d43c6367-FRA

{"ip":"88.198.54.xx","country_code":"DE","country_name":"Germany","region_code":"BY","region_name":"Bavaria","city":"Nuremberg","zip_code":"90455","time_zone":"Europe/Berlin","latitude":49.4478,"longitude":11.0683,"metro_code":0}
%
1
  • freegeoip doesn't seem to be still available: curl -i freegeoip.net/json/ returns HTTP/1.1 301 Moved Permanently.
    – ijoseph
    Jun 23, 2021 at 20:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.