44

Sometimes I need to download data from the internet. On occasions this has failed either because the website is down or because my computer has lost its internet connection.

Question: Is there some function in R which will return TRUE/FALSE as to whether I am connected to the internet?

Rupesh Yadav
  • 12,096
  • 4
  • 53
  • 70
Clair Crossupton
  • 1,332
  • 2
  • 10
  • 16
  • 2
    What operating system? In Windows I think you'd have to run ipconfig from a shell, and on Linux it would be ifconfig. You'd then have to parse the output and test. – Spacedman Feb 22 '11 at 10:15
  • 7
    The ability to download data from a remote machine depends on so many factors which are outside of the control of your code, and whose state may change at any time. The only 100% certain way to know if you can download the file is to attempt to download it, and succeed. Even if you can start a transfer, it doesn't guarantee that the net connection won't go down part way through, so you need to write code to cope with this situation anyway. So just write that code, and ditch trying to detect beforehand whether you'll succeed. – Damien_The_Unbeliever Feb 22 '11 at 10:24
  • 1
    A more elegant method is testing dns via `utils::nsl` (unix only) or `curl::nslookup` (cross-platform). – Jeroen Ooms Jan 23 '16 at 23:12

9 Answers9

35

The curl package has a function has_internet which tests by performing a nslookup:

curl::has_internet
## function(){
##    !is.null(nslookup("google.com", error = FALSE))
## }

Testing DNS is faster and may be more reliable than retrieving a URL because the latter might fail for unrelated reasons (e.g. firewall, server down, etc).

Jeroen Ooms
  • 31,998
  • 35
  • 134
  • 207
29

A dirty work around would be using RCurl::getURL function.

if (is.character(getURL("www.google.com"))) {
    out <- TRUE
} else {
    out <- FALSE
}
aL3xa
  • 35,415
  • 18
  • 79
  • 112
Roman Luštrik
  • 69,533
  • 24
  • 154
  • 197
20

Here is an attempt at parsing the output from ipconfig/ifconfig, as suggested by Spacedman.

havingIP <- function() {
  if (.Platform$OS.type == "windows") {
    ipmessage <- system("ipconfig", intern = TRUE)
  } else {
    ipmessage <- system("ifconfig", intern = TRUE)
  }
  validIP <- "((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)[.]){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"
  any(grep(validIP, ipmessage))
}

With a simple TRUE/FALSE output

> havingIP()
[1] TRUE
eyjo
  • 1,180
  • 6
  • 8
  • 1
    I don't suppose i[pf]config return a useful return value if the interface isn't up? It's not mentioned in the ifconfig man page, and I don't want to take my box's network down to test because I'm logging on remotely and I'd probably kill my connection :) – Spacedman Feb 22 '11 at 18:24
  • If the return value from the system is not containing a valid IP the function returns FALSE. Thus, f.e.x. now home using Linux I get FALSE due to the fact that I need to be root to use ifconfig. I get "sh: ifconfig: not found" is echoed to the R terminal before the FALSE return value. – eyjo Feb 22 '11 at 18:56
  • 2
    At least on my computer (Mint based on linux 3.13) , this can return TRUE when no internet connection. – cmbarbu Jul 24 '15 at 14:02
  • 2
    This does not check if you have an active internet connection. It checks if you have a valid IP Address. I just turned off my wifi and this still returns TRUE. – Jonathan Hill Sep 14 '17 at 01:02
  • AFAI understand this correctly, ifconfig returns useful information (a character string) regardless of connection (Being on a macbook osx 10.14) – Janhoo Aug 30 '19 at 11:28
11

Just another one to add to the pot, inspired by @romans answer, this works only on Windows I'd assume, not sure about other platforms:

canPingSite <- function(test.site) {
    !as.logical(system(paste("ping", test.site)))
}

Which we test as follows:

> t1 <- canPingSite("www.yahoo.com")
[...]

> t2 <- canPingSite(";lkjsdflakjdlfhasdfhsad;fs;adjfsdlk")
[...]

> t1; t2
[1] TRUE
[1] FALSE
Tony Breyal
  • 5,338
  • 3
  • 29
  • 49
  • 4
    I got two downvotes for this, but I can't work out why? I don't care about reputation points (they are meaningless to me), but I would like to understand what's bad about this solution. My reasoning for the downvotes would be because this solution will only work on windows, which I guess is sort of fair enough :) – Tony Breyal Feb 28 '11 at 09:50
  • 1
    Like this one, on Linux just adapt to: `canPingSite <- function(test.site) { !as.logical(system(paste("ping -c 1", test.site))) }` – cmbarbu Jul 24 '15 at 14:00
  • I'd suggest adding `ping -n 1` because we don't need to do the standard 4 pings. I'm not patient enough to wait for 4 separate responses ;) – Jonathan Hill Sep 14 '17 at 01:07
7

Do it with just two lines of code:

install.packages('pingr')
pingr::is_online()
BroVic
  • 979
  • 9
  • 26
TPArrow
  • 1,518
  • 18
  • 25
7

All these answers use packages or code outside of base R. Here's how to do it with just base R:

# IANA's test website
is_online <- function(site="http://example.com/") {
  tryCatch({
    readLines(site,n=1)
    TRUE
  },
  warning = function(w) invokeRestart("muffleWarning"),
  error = function(e) FALSE)
}
Zeke
  • 617
  • 1
  • 6
  • 15
5

Bioconductor's Biobase package has a function for testing internet connection.

Biobase::testBioCConnection()

Below is a heavily modified version of this function for testing ability to read lines from a URL.

can_internet <- function(url = "http://www.google.com") {

    # test the http capabilities of the current R build
    if (!capabilities(what = "http/ftp")) return(FALSE)

    # test connection by trying to read first line of url
    test <- try(suppressWarnings(readLines(url, n = 1)), silent = TRUE)

    # return FALSE if test inherits 'try-error' class
    !inherits(test, "try-error")
}

can_internet()
Eric
  • 3,403
  • 1
  • 19
  • 18
1

As the function above from eyjo

havingIP <- function() {
 if (.Platform$OS.type == "windows") {
   ipmessage <- system("ipconfig", intern = TRUE)
 } else {
   ipmessage <- system("ifconfig", intern = TRUE)
 }
 validIP <- "((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)[.]){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"
 any(grep(validIP, ipmessage))
}

also returns true for localhost ip "127.0.0.1" it needs to be removed to prevent false positives. For example as shown below:

 havingIP <- function() {
 if (.Platform$OS.type == "windows") {
   ipmessage <- system("ipconfig", intern = TRUE)
 } else {
   ipmessage <- system("ifconfig", intern = TRUE)
 }
 validIP <- "((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)[.]){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"
 any(grep(validIP, ipmessage[-grep("127.0.0.1", ipmessage)]))
}

But even better would be a solution that prevents localhosts by modifying the regex of validIP.

0

This is a version of eyjo's answer which sacrifices accuracy for speed.

IPavailable <- function() {
  cmd <- switch(.Platform$OS.type, "windows" = "ipconfig", "ifconfig")
  any(grep("(\\d+(\\.|$)){4}", system(cmd, intern = TRUE)))
}
Agriculturist
  • 521
  • 9
  • 20