JavaScript
Fetch API
Resource Checking
Network Requests
Web Development

JavaScript checking if resource is reachable with fetch

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

Checking whether a resource is reachable with fetch sounds simple, but "reachable" can mean different things. The request might fail at the network level, succeed with a 404, or be blocked by CORS even though the server is up, so a useful check has to distinguish those cases.

Decide What Reachable Means

Before writing code, define the outcome you care about:

  • The server responded at all
  • The response status was successful
  • The exact file or endpoint exists
  • The browser is allowed to read the response

These are different checks. A 404 means the host answered, but the specific resource was not available. A CORS error means the browser blocked access, not necessarily that the remote server is down.

Basic fetch Reachability Check

The simplest browser-side check is to call fetch and inspect response.ok.

javascript
1async function isReachable(url) {
2  try {
3    const response = await fetch(url, { method: "GET" });
4    return {
5      reachable: response.ok,
6      status: response.status
7    };
8  } catch (error) {
9    return {
10      reachable: false,
11      status: null,
12      error: error.message
13    };
14  }
15}
16
17isReachable("https://jsonplaceholder.typicode.com/posts/1")
18  .then(result => console.log(result));

This works, but it mixes multiple failure modes together. A good production check should be a little more explicit.

Use HEAD When You Only Need Metadata

If the server supports it, HEAD is often better than GET because it avoids downloading the response body.

javascript
1async function checkWithHead(url) {
2  try {
3    const response = await fetch(url, { method: "HEAD" });
4    return {
5      reachable: response.ok,
6      status: response.status
7    };
8  } catch (error) {
9    return {
10      reachable: false,
11      status: null,
12      error: error.message
13    };
14  }
15}

That said, not every server implements HEAD correctly. If you get inconsistent behavior, try the same endpoint with GET and compare the result before assuming the server is unavailable.

Add a Timeout with AbortController

fetch does not have a built-in timeout option. If a slow server should count as unreachable for your use case, add an abort signal.

javascript
1async function checkReachability(url, timeoutMs = 3000) {
2  const controller = new AbortController();
3  const timer = setTimeout(() => controller.abort(), timeoutMs);
4
5  try {
6    const response = await fetch(url, {
7      method: "HEAD",
8      signal: controller.signal
9    });
10
11    return {
12      reachable: response.ok,
13      status: response.status,
14      timedOut: false
15    };
16  } catch (error) {
17    return {
18      reachable: false,
19      status: null,
20      timedOut: error.name === "AbortError",
21      error: error.message
22    };
23  } finally {
24    clearTimeout(timer);
25  }
26}

This makes the behavior predictable when the destination hangs instead of returning quickly.

Understand Browser Limits

In browser JavaScript, you do not get raw socket-level reachability. You only get the browser's view of the request. That means:

  • DNS or TLS failures show up as rejected promises
  • CORS restrictions may hide response details
  • offline mode can make every request fail immediately

If the browser logs a CORS error, the remote site may still be up. Your script just is not allowed to inspect the response. That is why health checks for third-party services often belong on the server side instead of in front-end code.

Example: Differentiate Success, HTTP Failure, and Network Failure

javascript
1async function classifyResource(url) {
2  try {
3    const response = await fetch(url, { method: "GET" });
4
5    if (response.ok) {
6      return "success";
7    }
8
9    return `http-error-${response.status}`;
10  } catch (error) {
11    return `network-error-${error.name}`;
12  }
13}
14
15(async () => {
16  console.log(await classifyResource("https://jsonplaceholder.typicode.com/posts/1"));
17  console.log(await classifyResource("https://jsonplaceholder.typicode.com/posts/999999"));
18})();

This is often better than returning a single Boolean because operations teams and UI code usually need a more specific outcome.

When a Server-Side Probe Is Better

If you need reliable diagnostics for third-party resources, do the check from your own backend. A server process avoids most browser CORS limitations and can log deeper failure details. Front-end checks are useful for user-facing fallbacks, but they are not a complete monitoring strategy.

Common Pitfalls

The most common mistake is treating fetch rejection and non-ok status as the same problem. A network failure and a 404 are operationally different.

Another issue is using HEAD against servers that do not implement it properly. In those cases, GET may succeed while HEAD gives a misleading result.

A third problem is ignoring CORS. A browser-side "failed fetch" can reflect a policy restriction rather than an unreachable resource.

Summary

  • Decide whether you mean network reachability, successful status, or resource existence.
  • Use response.ok for success checks and catch for network-level failures.
  • Add AbortController when slow responses should count as failures.
  • Prefer HEAD only when the server supports it reliably.
  • Move strict health checks to the backend when browser limitations get in the way.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.