Am I Online?

4 months ago 2

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.

Read Entire Article