Am I online?
Recently, I was working on an application that needed to know if it was connected to the internet. A common way to do this is to ping DNS servers like 8.8.8.8
(Google) or 1.1.1.1
(Cloudflare). However, this uses the ICMP protocol (which only checks for basic network connectivity), while I wanted to exercise the full stack used by real HTTP clients: DNS, TCP, and HTTP.
Generate 204
After some research, I found this URL that Google itself seems to use in Chrome to check for connectivity:
http://google.com/generate_204
https://google.com/generate_204
The URL returns a 204 No Content
HTTP status (a successful response without a body). It's super fast, relies only on the core Google infrastructure (so it's unlikely to fail), and supports both HTTP and HTTPS. So I went with it, and it turned out to be sufficient for my needs.
There are also http://www.gstatic.com/generate_204
and http://clients3.google.com/generate_204
. As far as I can tell, they are served by the same backend as the one on google.com.
Other companies provide similar URLs to check for connectivity:
http://cp.cloudflare.com/generate_204
(Cloudflare)http://edge-http.microsoft.com/captiveportal/generate_204
(Microsoft)http://connectivity-check.ubuntu.com
(Ubuntu)http://connect.rom.miui.com/generate_204
(Xiaomi)
200 OK
Some companies provide 200 OK
endpoints instead of 204 No Content
:
http://spectrum.s3.amazonaws.com/kindle-wifi/wifistub.html
(Amazon)http://captive.apple.com/hotspot-detect.html
(Apple)http://network-test.debian.org/nm
(Debian)http://nmcheck.gnome.org/check_network_status.txt
(Gnome)http://www.msftncsi.com/ncsi.txt
(Microsoft)http://detectportal.firefox.com/success.txt
(Mozilla)
They are all reasonably fast and return compact responses.
Implementation
Finally, here's a simple internet connectivity check implemented in several programming languages. It uses Google's URL, but you can replace it with any of the others listed above.
Python:
import datetime as dt
import http.client
def is_online(timeout: dt.timedelta = dt.timedelta(seconds=1)) -> bool:
"""Checks if there is an internet connection."""
try:
conn = http.client.HTTPConnection(
"google.com",
timeout=timeout.total_seconds(),
)
conn.request("GET", "/generate_204")
response = conn.getresponse()
return response.status in (200, 204)
except Exception:
return False
finally:
conn.close()
JavaScript:
// isOnline checks if there is an internet connection.
async function isOnline(timeoutMs) {
try {
const url = "http://google.com/generate_204";
const response = await fetch(url, {
signal: AbortSignal.timeout(timeoutMs ?? 1000),
});
return response.status === 200 || response.status === 204;
} catch (error) {
return false;
}
}
Shell:
#!/usr/bin/env sh
# Checks if there is an internet connection.
is_online() {
local url="http://google.com/generate_204"
local timeout=${1:-1}
local response=$(
curl \
--output /dev/null \
--write-out "%{http_code}" \
--max-time "$timeout" \
--silent \
"$url"
)
if [ "$response" = "200" ] || [ "$response" = "204" ]; then
return 0
else
return 1
fi
}
Go:
package main
import (
"context"
"net/http"
)
// isOnline checks if there is an internet connection.
func isOnline(ctx context.Context) bool {
const url = "http://google.com/generate_204"
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return false
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return false
}
defer resp.Body.Close()
return resp.StatusCode == http.StatusOK || resp.StatusCode == http.StatusNoContent
}
Final thoughts
I'm not a big fan of Google, but I think it's nice of them to provide a publicly available endpoint to check internet connectivity. The same goes for Cloudflare and the other companies mentioned in this post.
Do you know of other similar endpoints? Let me know! @ohmypy (Twitter/X) or @antonz.org (Bluesky)
★ Subscribe to keep up with new posts.