25
\$\begingroup\$

I'm surprised this hasn't come up in a challenge yet.

Output the IP address of the machine you're running on. You are required to output both the local and external IP addresses.

Local IP address, ie along the default format of 192.168.x.x

Public IP address can be verified by using google https://www.google.co.uk/search?source=hp&q=whats+my+ip

Output can be in any format. IPv4 or IPv6 or any mix of each is allowed, however they must be the only output. Code can be a full program or a function.

rules apply so shortest code wins.

Standard Loopholes are forbidden.

EDIT: As per @Peter Taylor's comment, in the case where multiple of either type of address are present, you can choose to either output the first one, or as many as you can access. So long as at least one local and one public are present.

\$\endgroup\$
17
  • 3
    \$\begingroup\$ I think the 0/1 thing adds in unnecessary fluff to the challenge. \$\endgroup\$
    – Mr. Xcoder
    Aug 18, 2017 at 9:48
  • 5
    \$\begingroup\$ This is underspecified. In particular, it doesn't clearly address cases where there are multiple local IP addresses and/or multiple public IP addresses. Furthermore, there's no reliable way of telling whether I have multiple public IP addresses, and if so what they are. \$\endgroup\$ Aug 18, 2017 at 11:08
  • 5
    \$\begingroup\$ What if the host doesn't have any RFC 1918 addresses? It looks like there's no reliable answer to this, except on machines that have at least one private network. \$\endgroup\$ Aug 18, 2017 at 12:12
  • 4
    \$\begingroup\$ ... and even one network interface can have multiple IP addresses. \$\endgroup\$
    – Kaz
    Aug 18, 2017 at 13:26
  • 14
    \$\begingroup\$ Actually, I don't see how you could solve half of this without fetching from an external source, which is one of the standard loopholes you have expressly forbidden. \$\endgroup\$
    – Octopus
    Aug 18, 2017 at 16:50

21 Answers 21

18
\$\begingroup\$

Bash + curl + iproute2, 54 50 49 48 33 bytes

ip r g 1|awk '$0=$7'
curl eth0.me

Thanks @DomHastings for golfing off 1 byte!

Thanks @Sisyphus for coming up with a shorter URL!

Thanks @zeppelin for golfing off 9 bytes!

\$\endgroup\$
10
  • \$\begingroup\$ @DomHastings Your last golf attempts returns some garbage along with the ip address, at least on Ubuntu 16.04.3 LTS \$\endgroup\$
    – Ferrybig
    Aug 18, 2017 at 13:05
  • \$\begingroup\$ @Ferrybig Yeah, the 1/0 part outputs an error to STDERR, but that is ignored by default, if you get different output for ip route though, that could just be the version I was running on my machine. Shame! \$\endgroup\$ Aug 18, 2017 at 16:19
  • \$\begingroup\$ The first line prints 1000 for me... ip route get 1 output: ptpb.pw/pixx \$\endgroup\$
    – Majora320
    Aug 18, 2017 at 22:04
  • \$\begingroup\$ When I run that code I get this output: RTNETLINK answers: Network is unreachable \$\endgroup\$
    – kasperd
    Aug 18, 2017 at 23:51
  • 1
    \$\begingroup\$ You can also optimize your AWK expression a bit: awk 'NR<2&&$0=$7' \$\endgroup\$
    – zeppelin
    Aug 19, 2017 at 6:59
9
\$\begingroup\$

Bash 37 31 27 bytes

This is inspired by the answer by Bruce Forte. That answer only works with IPv4 which means it doesn't work for me. I have rewritten it into a version that (only) works with IPv6:

ip r g b::|awk '$0=$9" "$9'

This is tested on Ubuntu 14.04.5 connected through PPPoE and since IPv6 is designed to be used without any NAT it will output the same IP address twice.

-6 bytes thanks to zeppelin, -2 bytes thanks to Ferrybig, -2 bytes thanks to Markasoftware.

\$\endgroup\$
6
  • \$\begingroup\$ On my Ubuntu 16.04.3 LTS, I had to change '{print$11,$11}' to '{print$9,$9}' to make the command work, your command returned 1024 2 times, Your command works on my Ubuntu 16.04.2 machine \$\endgroup\$
    – Ferrybig
    Aug 19, 2017 at 15:46
  • \$\begingroup\$ @Ferrybig Probably depends on network configuration then. I tested this on a network where addresses are auto-configured from router advertisements. \$\endgroup\$
    – kasperd
    Aug 19, 2017 at 15:55
  • \$\begingroup\$ For machines where the ip address is manually configured (static), ip route doesn't output the proto ra part, you could use this as a feature to golf your answer further \$\endgroup\$
    – Ferrybig
    Aug 19, 2017 at 16:00
  • \$\begingroup\$ @Ferrybig At the moment I am pondering whether I can find a way to make it work in both cases without the size blowing up. Btw. on my 16.04.3 machine which received its configuration using router advertisements it says proto static not proto ra, though that difference doesn't matter to this code. \$\endgroup\$
    – kasperd
    Aug 19, 2017 at 16:37
  • \$\begingroup\$ To golf it a bit, use awk '$0=$9" "$9' instead of {print$11,$11}. Many systems (including my Arch one) use the 9th word, so it's shorter than 11, and also using this syntax is smaller than print$9,$9 \$\endgroup\$ Aug 24, 2017 at 21:06
7
\$\begingroup\$

AutoIt, 56 53 bytes

#include<Inet.au3>
ConsoleWrite(@IPAddress1&_GetIP())

@IPAddress1 is a macro that returns

IP address of first network adapter

_GetIP() returns

the public IP address.


-3 bytes thanks to @mınxomaτ

\$\endgroup\$
2
  • 3
    \$\begingroup\$ Neat, a fellow AutoIt (not IT) -er. You can delete the spaces in this code. \$\endgroup\$
    – user42643
    Aug 18, 2017 at 13:22
  • \$\begingroup\$ @mınxomaτ Thanks for the correction :) \$\endgroup\$
    – Daniel
    Aug 18, 2017 at 16:45
7
\$\begingroup\$

Mathematica, 17 bytes

Mathematica has a builtin for everything

$MachineAddresses

As described in the documentation, this builtin command lists all IP addresses (both local and external) associated with your device.

\$\endgroup\$
5
  • \$\begingroup\$ The documentation doesn't say anything about external addresses. \$\endgroup\$
    – kasperd
    Aug 19, 2017 at 12:04
  • \$\begingroup\$ If this command also lists the ipv6 address, then you can say the ipv6 address is the expected result \$\endgroup\$
    – Ferrybig
    Aug 19, 2017 at 15:57
  • 5
    \$\begingroup\$ This produces a list of several IP addresses for me, but none of them seem to be my external address; I may not be interpreting things correctly, though. I can get my external IP address from something like WolframAlpha["ip address", {{"IPAddress:InternetData", 1}, "ComputableData"}][[1,2]] but I don't know how to get at that more directly. \$\endgroup\$
    – Mark S.
    Aug 19, 2017 at 16:17
  • \$\begingroup\$ @MarkS. That is odd; I get my external IP address when I run the command (the last entry seems to be it). This command won't work on Wolfram Sandbox, though. Perhaps this is a bug; what OS and Mathematica version are you using? \$\endgroup\$ Aug 20, 2017 at 19:14
  • \$\begingroup\$ @JungHwanMin 11.1.1.0 Student Edition gives me 6 things that I assume are IPv6, then 192.168.0.104, and three addresses beginning with 169.254. But my external address begins with 69. \$\endgroup\$
    – Mark S.
    Aug 21, 2017 at 23:13
6
\$\begingroup\$

C#, 196 194 188 163 bytes

namespace System.Net.Sockets{using Linq;_=>Dns.GetHostEntry("").AddressList.First(i=>(int)i.AddressFamily==2)+" "+new WebClient().DownloadString("http://eth0.me")}

Saved 2 bytes thanks to @Xynos.
Saved 25 bytes thanks to @Nick.

Full/Formatted Version:

namespace System.Net.Sockets
{
    using Linq;

    class P
    {
        static void Main()
        {
            Func<object, string> f = _ =>
                Dns.GetHostEntry(Dns.GetHostName())
                    .AddressList
                    .First(i => (int)i.AddressFamily == 2) + " " + new WebClient().DownloadString("http://eth0.me");

            Console.WriteLine(f(null));

            Console.ReadLine();
        }
    }
}
\$\endgroup\$
4
  • \$\begingroup\$ cant you save two bytes by removing the whitespace around the == ? \$\endgroup\$ Aug 18, 2017 at 10:54
  • \$\begingroup\$ @Xynos Of course, didn't realise I hadn't removed it. \$\endgroup\$ Aug 18, 2017 at 10:58
  • \$\begingroup\$ The golfed version does not compile and is not a standalone function. It doesn't seem fair to mix a standalone function with the shortcut of using the Sockets namespace, so I'd suggest picking one option and going with it. That said, you can save some bytes by casting i.AddressFamily to int instead of casting 2 to AddressFamily, and you can replace Dns.GetHostName() with the empty string. \$\endgroup\$
    – Nick
    Aug 18, 2017 at 22:42
  • \$\begingroup\$ @Nick I will try that when I get a chance and the namespace trick is fairly common for C#. If you think it shouldn't be allowed you can post on meta about it but at the moment it is fair game and a neat trick in shortening usings. \$\endgroup\$ Aug 19, 2017 at 15:58
6
\$\begingroup\$

PowerShell v4+, 40 36 bytes

NetIPAddress|% IPA*
iwr eth0.me|% C*

(Only works on Server 2012 R2 or above, or Windows 8.1 or above. Doesn't work on TIO.)

Does exactly what it says on the tin. Gets the local network IP addresses and selects just the IPAddress portion thereof (e.g., filters out the subnet mask, the gateway, etc.).

The second is a Invoke-WebRequest to http://eth0.me which simply gets the Content thereof; i.e., just the public IP address.


Ungolfed version:

(Get-NetIPAddress).IPAddress
(Invoke-WebRequest eth0.me).content
\$\endgroup\$
2
  • \$\begingroup\$ An anonymous user suggests removing Get- \$\endgroup\$
    – Stephen
    Aug 18, 2017 at 22:16
  • \$\begingroup\$ @StepHen Indeed. Works great. \$\endgroup\$ Aug 21, 2017 at 12:39
4
\$\begingroup\$

#Unix Shell + stunclient, 40 bytes

stunclient stun.vo.lu|cut -d: -f2|sed 1d

Makes use of a STUN protocol:

Session Traversal Utilities for NAT (STUN) is a protocol that serves as a tool for other protocols in dealing with Network Address Translator (NAT) traversal. It can be used by an endpoint to determine the IP address and port allocated to it by a NAT

The STUN server name is from the Public STUN server list.

The output format is:

 LOCAL IPV4 ADDRESS
 PUBLIC IPV4 ADDRESS

Note that both lines will be indented with a single space, but I believe this does not break the output rules as written.

Sample output:

  192.168.1.100    
  209.85.233.147
\$\endgroup\$
4
\$\begingroup\$

curl (bash one-liner): 27 bytes

curl -w%{local_ip} eth0.me

The result is printed on stdout and looks like this:

1.2.3.4
192.168.0.10
# no trailing newline, use "curl -w%{local_ip}\\n eth0.me" for it

curl should be at least of version 7.29.0 (from Feb 6, 2013).

The answer is based on https://codegolf.stackexchange.com/a/139538/66016.

\$\endgroup\$
4
\$\begingroup\$

Go, MacOS only, 10 bytes

In macOS this killswitch could be used, it can print current private active IP and public IP:

$ killswitch 
Interface  MAC address         IP
en1        bc:34:36:d2:81:ba   192.168.2.10

Public IP address: 179.43.176.99

No VPN interface found, verify VPN is connected

This is not a built-in tool but tries to simplify the process of finding the proper IP's.

The output could get by using commands like:

$ route get 0.0.0.0

$ ifconfig | pcregrep -M -o '^[^\t:]+:([^\n]|\n\t)*status: active'

$ networksetup -listnetworkserviceorder

$ scutil --dns

Public IP:

$ dig o-o.myaddr.l.google.com @ns.google.com txt +short
\$\endgroup\$
1
  • 2
    \$\begingroup\$ Hi! Welcome to PPCG! This question is tagged code-golf. Could you provide golfed code with a language and a byte count? \$\endgroup\$
    – Stephen
    Aug 21, 2017 at 12:48
3
\$\begingroup\$

Python 3, 124 133 bytes

from urllib2 import urlopen
import socket
a=urlopen('http://eth0.me').read()
b=socket.gethostbyname(socket.gethostname())
print a,b
\$\endgroup\$
5
  • \$\begingroup\$ Don't you also need to print a,b? Interestingly, this does output two IPs on my system (Win7), but neither one of them is my actual local IP address. b is actually the IP of a virtual adapter and not my Local Area Connection. \$\endgroup\$
    – Octopus
    Aug 18, 2017 at 16:31
  • \$\begingroup\$ Arguably though, that is still a local Ip address. I left a comment on the Question to ask for clarification on that. \$\endgroup\$
    – Octopus
    Aug 18, 2017 at 16:43
  • \$\begingroup\$ @Octopus you're right about printing, updated \$\endgroup\$
    – Teo
    Aug 18, 2017 at 17:22
  • \$\begingroup\$ In a suggested edit, @David suggested this: 113 bytes (Review here) \$\endgroup\$
    – Stephen
    Aug 18, 2017 at 17:48
  • \$\begingroup\$ You can print without () in Python 3?? \$\endgroup\$
    – Gotoro
    Feb 17, 2021 at 22:36
3
\$\begingroup\$

PowerShell v3+ (alternative answer for windows 7+)

((ipconfig) -match "v4").split(":")[1]
Invoke-RestMethod eth0.me
\$\endgroup\$
2
  • 2
    \$\begingroup\$ Welcome to PPCG! \$\endgroup\$
    – Stephen
    Aug 18, 2017 at 21:06
  • 1
    \$\begingroup\$ You can remove the spaces surrounding -match to save a couple bytes. \$\endgroup\$ Aug 21, 2017 at 12:42
3
\$\begingroup\$

Bash + Awk + Curl, 43 bytes

using only built in tools for Mac and Linux

ifconfig|awk '/bro/{print $2}';curl eth0.me
\$\endgroup\$
12
  • 1
    \$\begingroup\$ *bash you mean . \$\endgroup\$
    – Suici Doga
    Aug 19, 2017 at 4:42
  • \$\begingroup\$ bash + awk + curl \$\endgroup\$ Aug 19, 2017 at 8:18
  • \$\begingroup\$ i edited the question to say bash since it works on my linux laptop not just macos \$\endgroup\$
    – Suici Doga
    Aug 19, 2017 at 8:48
  • \$\begingroup\$ thx, I improved since bash is a shell per se (should work on tcsh, sh and any other shell), you need to have ifconfig, awk and curl also \$\endgroup\$ Aug 19, 2017 at 9:35
  • 1
    \$\begingroup\$ This isn't "MacOS/Linux", it's Bash. Just mark it as such. \$\endgroup\$
    – LyricLy
    Aug 19, 2017 at 10:31
2
\$\begingroup\$

Node.js (JavaScript) 224 223 194 175 173 130 bytes

r=require,l=console.log,r('dns').lookup(r('os').hostname(),(a,b)=>l(b));r('http').get('http://eth0.me',a=>a.on('data',c=>l(c+"")))

Ungolfed version:

require('dns').lookup(require('os').hostname(), (err, loc, fam) => console.log(loc));
require('http').get('http://eth0.me', res => {
    res.on('data', chunk => console.log(chunk + ""));
});

  • Saved 1 byte (due to unnecessary semicolon).
  • Saved 29 bytes thanks to @AndrewLi (used arrow functions for shorter code).
  • Saved 19 bytes thanks to @MiniGod (used .get() instead of .request() - .end(); removed).
  • Saved 2 bytes thanks to @Zacharý (parentheses not needed around a lone parameter of an arrow function).
  • Saved 43 bytes thanks to @Birjolaxew (stored require and console.log in single-letter variables, passed url directly to require('http').get, logged output directly from data event).
\$\endgroup\$
11
  • \$\begingroup\$ Can't you use arrow functions for shorter code? \$\endgroup\$
    – Andrew Li
    Aug 18, 2017 at 17:11
  • \$\begingroup\$ @AndrewLi Great suggestion, thanks. :) \$\endgroup\$
    – user73540
    Aug 18, 2017 at 17:48
  • \$\begingroup\$ You can use .get() instead of .request(). Then you also don't need the .end();. \$\endgroup\$
    – MiniGod
    Aug 18, 2017 at 17:56
  • 1
    \$\begingroup\$ You don't need parens around a lone parameter of an arrow function. ((a)=> => a=>), IIRC. \$\endgroup\$
    – Adalynn
    Aug 18, 2017 at 18:37
  • 1
    \$\begingroup\$ @AndrewLi Hmm, the problem is that when the code is run in the REPL, it prints out extra info (e.g. the request information), which is prohibited in the question. I could add extra code to hide this output, but it might counteract the reduction of bytes which result from leaving out the require calls, so I'll leave it for now. Thanks for the suggestion anyway. \$\endgroup\$
    – user73540
    Aug 18, 2017 at 20:48
2
\$\begingroup\$

Python 2.7.13 128 bytes

print __import__("urllib").urlopen("http://eth0.me").read(),__import__("socket").gethostbyname(__import__("socket").getfqdn())
\$\endgroup\$
1
\$\begingroup\$

Windows' Batch File, 116 bytes

@for /f "tokens=1-2 delims=:" %%a in ('ipconfig^|find "v4"')do @echo%%b
@powershell -Command "(iwr eth0.me).content"

The first line iterates through the results of running ipconfig and gets your local IPv4 address.

For the public IP part, I had to steal a bit from the marvelous Powershell answer because, as far as I know, there is no way to get the machine's public IP using solely batch scripting.

We start with an @ sign, to suppress echoing the prompt (C:\...\path>), then run the Powershell command Invoke-WebRequest (with its alias, iwr) and extract the content part of that.

I experimented with not using (...).content and, instead, only running the command and extracting the actual information from the complete output, using batch. But that proved to be way longer than this solution, so I kept it.

Tested on Windows 10.0.15063.

\$\endgroup\$
1
\$\begingroup\$

R, 142, 140, 137 bytes

library(magrittr);system("ipconfig",int=T)%>%regmatches(.,regexpr("v4.+",.))%>%{a=nchar(.);substr(.,a-14,a)};readLines("http://eth0.me")

Tested on win10 and R (3.4.1).
Thanks for @Bruce-Forte for short URL.

Ungolfed version:

library(magrittr)
system("ipconfig",int=T) %>% 
     regmatches(.,regexpr("v4.+",.)) %>% 
      {a <- nchar(.)
       substr(., a - 14, a)}
readLines("http://eth0.me")
\$\endgroup\$
3
  • \$\begingroup\$ Down to 120 bytes Try it online! \$\endgroup\$
    – BLT
    Aug 23, 2017 at 20:21
  • \$\begingroup\$ @BLT nice solution. You can save 3 bytes, by replacing a <- nchar(x) with a=nchar(x) \$\endgroup\$
    – AndriusZ
    Aug 24, 2017 at 11:30
  • \$\begingroup\$ @AndruisZ thanks, but it's really your solution -- I just de-magrittr'd it. \$\endgroup\$
    – BLT
    Aug 24, 2017 at 15:37
1
\$\begingroup\$

Bash + Curl, 24 bytes

hostname -i;curl eth0.me
\$\endgroup\$
4
  • \$\begingroup\$ This doesn't work.. From the man page: "This option enumerates all configured addresses on all network interfaces. [...] Do not make any assumptions about the order of the output." \$\endgroup\$ Dec 19, 2017 at 8:13
  • \$\begingroup\$ Doesn't -I (capital) have a different use than -i (lowercase). The bit you quoted was from the -I section. \$\endgroup\$
    – Probably
    Dec 19, 2017 at 13:50
  • \$\begingroup\$ True, sorry about that. But even worse it says "Avoid using this option", either way this doesn't work (at least on my machines).. \$\endgroup\$ Dec 19, 2017 at 20:29
  • \$\begingroup\$ Right, admittedly I did not read the full documentation before posting. Oddly enough it seems to work fine on a few of my machines. But this inconsistency would make this solution unreliable at best. \$\endgroup\$
    – Probably
    Dec 20, 2017 at 13:38
1
\$\begingroup\$

MS-SQL, 59 bytes

SELECT TOP 1 local_net_address
FROM sys.dm_exec_connections

Returns the client-facing IP address of the SQL instance executing the query.

\$\endgroup\$
1
\$\begingroup\$

VBA, 58 Bytes

Whoops, does not handle local address - fix in progress

Note: Uses reference to

Microsoft Internet Controls

Anonymous VBE immediate window function that takes no input and outputs the user's IP address via an Internet Explorer window

Set i=New InternetExplorer:i.Visible=1:i.Navigate"eth0.me"
\$\endgroup\$
1
\$\begingroup\$

Bash — 29 bytes (linux)

curl ipinfo.io/ip
hostname -i
\$\endgroup\$
0
\$\begingroup\$

Python 3, 97 bytes

from socket import*
from requests import*
gethostbyname(gethostname()),get('http://eth0.me').text

returns tuple with ('LOCAL_IP', 'PUBLIC_IP'), as apparently

x = 2,3
type(x)
>>> tuple

Python 3, 103 bytes

from socket import*
from requests import*
gethostbyname(gethostname()),get('http://api.ipify.org').text

ditto, read below.


Python 3, 107 bytes

First solution

from socket import*
from requests import*
gethostbyname(gethostname())+" "+get('http://api.ipify.org').text

The +" "+ part is for joining strings together.

If you leave just the + sign, 103 bytes are possible, but would yield the strings without spaces which could lead to results like this "5.5.5.111222.222.222.222" and they should still be readable, as there are only 3 digits at max in every ip part.

But there are edge cases like "5.5.5.11111.222.222.222" where it would be impossible to distinguish the local vs public part.

Other possible savings are in the public ip grabber tool. I used this site, as it was the first thing I found on the Internet and it returns html with just text in it, which is super nice. I saw other people using http://eth0.me, but it doesn't load for me on my machine and my antivirus has it blacklisted, thus Python raises a ConnectionError. It loads through Tor though, so I don't know whether I should use it.

Python 3, 101 bytes

from socket import*
from requests import*
gethostbyname(gethostname())+" "+get('http://eth0.me').text
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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