How can I get my external IP address in a shell script?

I'd recommend getting it directly from a DNS server.

Most of the other answers below all involve going over HTTP to a remote server. Some of them required parsing of the output, or relied on the User-Agent header to make the server respond in plain text. Those change quite frequently (go down, change their name, put up ads, might change output format etc.).

  1. The DNS response protocol is standardised (the format will stay compatible).
  2. Historically, DNS services (Akamai, Google Public DNS, OpenDNS, ..) tend to survive much longer and are more stable, more scalable, and generally more looked-after than whatever new hip whatismyip dot-com HTTP service is hot today.
  3. This method is inherently faster (be it only by a few milliseconds!).

Using dig with an OpenDNS resolver:

$ dig @resolver4.opendns.com myip.opendns.com +short

Perhaps alias it in your bashrc so it's easy to remember

# https://unix.stackexchange.com/a/81699/37512
alias wanip='dig @resolver4.opendns.com myip.opendns.com +short' 
alias wanip4='dig @resolver4.opendns.com myip.opendns.com +short -4'
alias wanip6='dig @resolver1.ipv6-sandbox.opendns.com AAAA myip.opendns.com +short -6'

Responds with a plain ip address:

$ wanip # wanip4, or wanip6
80.100.192.168 # or, 2606:4700:4700::1111

Syntax

(Abbreviated from https://ss64.com/bash/dig.html):

usage:  dig [@global-dnsserver] [q-type] <hostname> <d-opt> [q-opt]

    q-type   one of (A, ANY, AAAA, TXT, MX, ...). Default: A.

    d-opt    ...
             +[no]short          (Display nothing except short form of answer)
             ...

    q-opt    one of:
             -4                  (use IPv4 query transport only)
             -6                  (use IPv6 query transport only)
             ...

The ANY query type returns either an AAAA or an A record. To prefer IPv4 or IPv6 connection specifically, use the -4 or -6 options accordingly.

To require the response be an IPv4 address, replace ANY with A; for IPv6, replace it with AAAA. Note that it can only return the address used for the connection. For example, when connecting over IPv6, it cannot return the A address.

Alternative servers

Various DNS providers offer this service, including OpenDNS, Akamai, and Google Public DNS:

# OpenDNS (since 2009)
$ dig @resolver3.opendns.com myip.opendns.com +short
$ dig @resolver4.opendns.com myip.opendns.com +short
80.100.192.168

# OpenDNS IPv6
$ dig @resolver1.ipv6-sandbox.opendns.com AAAA myip.opendns.com +short -6
2606:4700:4700::1111

# Akamai (since 2009)
$ dig @ns1-1.akamaitech.net ANY whoami.akamai.net +short
80.100.192.168

# Akamai approximate
# NOTE: This returns only an approximate IP from your block,
# but has the benefit of working with private DNS proxies.
$ dig +short TXT whoami.ds.akahelp.net
"ip" "80.100.192.160"

# Google (since 2010)
# Supports IPv6 + IPv4, use -4 or -6 to force one.
$ dig @ns1.google.com TXT o-o.myaddr.l.google.com +short
"80.100.192.168"

Example alias that specifically requests an IPv4 address:

# https://unix.stackexchange.com/a/81699/37512
alias wanip4='dig @resolver4.opendns.com myip.opendns.com +short -4'

$ wanip4
80.100.192.168

And for your IPv6 address:

# https://unix.stackexchange.com/a/81699/37512
alias wanip6='dig @ns1.google.com TXT o-o.myaddr.l.google.com +short -6'

$ wanip6
"2606:4700:4700::1111"

Troubleshooting

If the command is not working for some reason, there may be a network problem. Try one of the alternatives above first.

If you suspect a different issue (with the upstream provider, the command-line tool, or something else) then run the command without the +short option to reveal the details of the DNS query. For example:

$ dig @resolver4.opendns.com myip.opendns.com

;; Got answer: ->>HEADER<<- opcode: QUERY, status: NOERROR

;; QUESTION SECTION:
;myip.opendns.com.      IN  A

;; ANSWER SECTION:
myip.opendns.com.   0   IN  A   80.100.192.168

;; Query time: 4 msec

NOTE: This is about external IP address (the one that the servers on the Internet see when you connect to them) - if you want internal IP address (the one that your own computer is using for connections, which may be different) see this answer.

TL;DR - Fastest methods in 2015

The fastest method using DNS:

dig +short myip.opendns.com @resolver4.opendns.com

or using externalip:

externalip dns

The fastest using HTTP:

curl -s http://whatismyip.akamai.com/

or using externalip:

externalip http

The fastest using HTTPS with a valid cert:

curl -s https://4.ifcfg.me/

or using externalip:

externalip https

Using telnet:

With nc command:

nc 4.ifcfg.me 23 | grep IPv4 | cut -d' ' -f4

or using externalip:

externalip telnet

With telnet command:

telnet 4.ifcfg.me 2>&1 | grep IPv4 | cut -d' ' -f4

Using FTP:

echo close | ftp 4.ifcfg.me | awk '{print $4; exit}'

or using externalip:

externalip ftp

All of the above can be run using my externalip script as:

externalip dns
externalip http
externalip https
externalip telnet
externalip ftp

Now a long story...

There are a lot of options of different servers providing the external IP especially via HTTP posted here or elsewhere.

I made a benchmark to see if any of them are better than the others and I was surprised by the results. E.g. one of the most widely recommended ifconfig.me was almost always the slowest for me, sometimes taking many seconds to respond. Many don't work over HTTPS, or do work but have invalid certificates. Some have very inconsistent response times.

Benchmarks

HTTP and HTTPS

This is the source of my externalip-benchmark script that I used:

  • https://raw.githubusercontent.com/rsp/scripts/master/externalip-benchmark

You can run it yourself to see which services mentioned here are worth using:

wget https://raw.githubusercontent.com/rsp/scripts/master/externalip-benchmark
chmod a+x externalip-benchmark
./externalip-benchmark

My results that I got on 2015-04-03 from Warsaw - the addresses have been changed to protect the innocent:

Best http response times:

0.086s http://ip.tyk.nu/ - answer='172.31.133.7'
0.089s http://whatismyip.akamai.com/ - answer='172.31.133.7'
0.091s http://tnx.nl/ip - answer='172.31.133.7'
0.117s http://ifcfg.me/ - answer='172.31.133.7'
0.156s http://l2.io/ip - answer='172.31.133.7'
0.317s http://ip.appspot.com/ - answer='172.31.133.7'
0.336s http://ident.me/ - answer='172.31.133.7'
0.338s http://ipof.in/txt - answer='172.31.133.7'
0.347s http://icanhazip.com/ - answer='172.31.133.7'
0.496s http://curlmyip.com/ - answer='172.31.133.7'
0.527s http://wgetip.com/ - answer='172.31.133.7'
0.548s http://curlmyip.com/ - answer='172.31.133.7'
0.665s http://bot.whatismyipaddress.com/ - answer='172.31.133.7'
0.665s http://eth0.me/ - answer='172.31.133.7'
1.041s http://ifconfig.me/ - answer='172.31.133.7'
1.049s http://corz.org/ip - answer='172.31.133.7'
1.598s http://ipecho.net/plain - answer='172.31.133.7'

Best https response times:

0.028s https://curlmyip.com/ - answer=''
0.028s https://curlmyip.com/ - answer=''
0.029s https://l2.io/ip - answer=''
0.029s https://tnx.nl/ip - answer=''
0.072s https://whatismyip.akamai.com/ - answer=''
0.113s https://ipecho.net/plain - answer=''
0.117s https://ident.me/ - answer=''
0.207s https://ip.tyk.nu/ - answer='172.31.133.7'
0.214s https://ipof.in/txt - answer='172.31.133.7'
0.259s https://ifcfg.me/ - answer='172.31.133.7'
0.289s https://corz.org/ip - answer=''
0.436s https://ip.appspot.com/ - answer='172.31.133.7'
0.448s https://bot.whatismyipaddress.com/ - answer=''
0.454s https://eth0.me/ - answer=''
0.673s https://icanhazip.com/ - answer='172.31.133.7'
5.255s https://ifconfig.me/ - answer=''
10.000s https://wgetip.com/ - answer=''

(Note: there are some fast responses with empty content - those are invalid.)

Best average ping times:

10.210 //whatismyip.akamai.com/
36.820 //tnx.nl/ip
37.169 //ip.tyk.nu/
39.412 //ipof.in/txt
40.967 //ident.me/
41.257 //ipecho.net/plain
43.918 //ifcfg.me/
45.720 //l2.io/ip
64.749 //ip.appspot.com/
123.412 //corz.org/ip
134.245 //wgetip.com/
157.997 //icanhazip.com/
161.613 //curlmyip.com/
162.100 //curlmyip.com/
268.734 //ifconfig.me/
999999 //bot.whatismyipaddress.com/
999999 //eth0.me/

Here are the results that I got on 2015-04-03 from Amsterdam:

Best http response times:

0.021s http://ipecho.net/plain - answer='172.31.13.37'
0.027s http://tnx.nl/ip - answer='172.31.13.37'
0.035s http://whatismyip.akamai.com/ - answer='172.31.13.37'
0.039s http://ifcfg.me/ - answer='172.31.13.37'
0.045s http://l2.io/ip - answer='172.31.13.37'
0.142s http://ident.me/ - answer='172.31.13.37'
0.144s http://ipof.in/txt - answer='172.31.13.37'
0.150s http://ip.appspot.com/ - answer='172.31.13.37'
0.150s http://ip.tyk.nu/ - answer='172.31.13.37'
0.170s http://icanhazip.com/ - answer='172.31.13.37'
0.190s http://eth0.me/ - answer='172.31.13.37'
0.191s http://wgetip.com/ - answer='172.31.13.37'
0.301s http://curlmyip.com/ - answer='172.31.13.37'
0.330s http://bot.whatismyipaddress.com/ - answer='172.31.13.37'
0.343s http://curlmyip.com/ - answer='172.31.13.37'
0.485s http://corz.org/ip - answer='172.31.13.37'
3.549s http://ifconfig.me/ - answer='172.31.13.37'

Best https response times:

0.004s https://curlmyip.com/ - answer=''
0.012s https://curlmyip.com/ - answer=''
0.012s https://tnx.nl/ip - answer=''
0.016s https://ipecho.net/plain - answer=''
0.071s https://whatismyip.akamai.com/ - answer=''
0.096s https://ifcfg.me/ - answer='172.31.13.37'
0.097s https://ident.me/ - answer=''
0.187s https://corz.org/ip - answer=''
0.187s https://ip.appspot.com/ - answer='172.31.13.37'
0.189s https://ip.tyk.nu/ - answer='172.31.13.37'
0.195s https://eth0.me/ - answer=''
0.253s https://l2.io/ip - answer=''
0.300s https://ipof.in/txt - answer='172.31.13.37'
0.324s https://bot.whatismyipaddress.com/ - answer=''
0.512s https://icanhazip.com/ - answer='172.31.13.37'
1.272s https://ifconfig.me/ - answer=''
10.002s https://wgetip.com/ - answer=''

Best average ping times:

1.020 //ipecho.net/plain
1.087 //whatismyip.akamai.com/
5.011 //ip.appspot.com/
6.942 //ident.me/
7.017 //ipof.in/txt
8.209 //tnx.nl/ip
11.343 //ip.tyk.nu/
12.647 //ifcfg.me/
13.828 //l2.io/ip
81.642 //icanhazip.com/
85.447 //wgetip.com/
91.473 //corz.org/ip
102.569 //curlmyip.com/
102.627 //curlmyip.com/
247.052 //ifconfig.me/
999999 //bot.whatismyipaddress.com/
999999 //eth0.me/

(The 999999 pings mean 100% packet loss.)

DNS

For a comparison here are times that other methods take - tested on 2015-06-16 from Warsaw and Amsterdam.

Using:

time dig +short myip.opendns.com @resolver1.opendns.com

usually takes (real wall clock time) about:

  • 0.035s from Warsaw
  • 0.015s from Amsterdam

There are actually four resolvers that can be used this way:

  • resolver1.opendns.com
  • resolver2.opendns.com
  • resolver3.opendns.com
  • resolver4.opendns.com

They all give the same response times in Warsaw and Amsterdam but this may not be the case in other locations.

Using 208.67.222.222 - the IP of resolver1.opendns.com instead of its domain name is faster:

  • 0.023s from Warsaw
  • 0.009s from Amsterdam

but may not work in the future if the IP ever changes (though it may be unlikely for a well known DNS resolver - maybe I should use the IP in my externalip script - please comment).

Telnet

Telnet with nc or telnet command (see above) usually takes:

  • 0.103s from Warsaw
  • 0.035s from Amsterdam

(There is no noticeable difference between nc and telnet commands.)

FTP

  • 0.104s from Warsaw
  • 0.036s from Amsterdam

Domain names

All of the methods will be faster (especially when run for the first time) when IP addresses will be used instead of the domain names of the given services (except with HTTP that can use host-based virtual servers and not work with bare IP - not tested) but will stop working when the services change the IP address so it may be faster but less future-proof.

Comments

If you see some interesting results from your location, or if you think that some other hosts should be recommended instead of those that I've chosen, please post a comment. If there is any important service missing, please comment or post an issue on GitHub. I'd like to keep this post updated with a current choice of best-performing services.


 curl -s http://whatismijnip.nl |cut -d " " -f 5

Replaced site with dutch working one.