What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
A reliable Node.js website check does four things on every run: sends a request to a configured URL, verifies the returned HTTP status (and optionally a content marker), measures elapsed time, and fails explicitly when the request exceeds a deadline or raises a network error. The script below uses Node’s built-in fetch and AbortSignal.timeout(), then repeats at a controlled interval without allowing overlapping checks.
What this monitor actually checks
This is a small availability checker, not a complete synthetic-monitoring platform. It can tell you whether an endpoint responded with an allowed status, how long that response took, and whether DNS, TLS, connection, or timeout errors occurred. Alert delivery, durable history, retries, and deployment are separate decisions that depend on your environment.
- HTTP health: a fulfilled
fetchpromise only means that response headers arrived. A 404 or 500 still fulfills the promise, so inspectresponse.statusorresponse.ok. - Latency: record elapsed milliseconds for successful and failed attempts; a slow 200 response is different from an immediate connection refusal.
- Deadline: abort requests that exceed a finite limit and count the abort as a failed check.
- Content (optional): for a page that must contain a stable phrase, read the body and test that marker in addition to the status.
Prerequisites and configuration
Use a current Node.js release with the built-in Fetch API. AbortSignal.timeout(delay) was added in Node.js 17.3.0 and 16.14.0; verify the runtime selected for production before relying on it. The example is written as an ES module.
- Create a directory and run
npm init -y. - Add
"type": "module"topackage.json, or save the file with an.mjsextension. - Set the target and timing values as environment variables rather than embedding a production URL.
MONITOR_URL=https://example.com
MONITOR_INTERVAL_MS=60000
MONITOR_TIMEOUT_MS=10000
MONITOR_EXPECTED_STATUS=200
node monitor.mjs
On Windows PowerShell, set variables with $env:MONITOR_URL="https://example.com" and run node monitor.mjs. Validate that the URL uses http: or https:; reject credentials or unexpected schemes if untrusted users can edit configuration.
#1 Best Overall
- 3.5 Inch Hot Plug Hard Drive PowerEdge T340 Tower Server Chassis
- Microsoft Windows Server 2019 Standard Operating System
- Processors: Intel Xeon E-2124 Quad-Core 3.3GHz 8MB CPU, Up To 4.3GHz Turbo
- Memory: 32GB (2 x 16GB) DDR4 PC4-21300 2666MHz Unbuffered Memory
- Hard Drive: 8TB (4 x 2TB) 7.2K RPM 6Gb/s SATA 3.5 Inch HDDs in RAID
Complete Node.js monitoring script
Save this as monitor.mjs. It performs one check immediately, then schedules the next run only after the previous one finishes, preventing accidental overlap when a site is slow.
const target = process.env.MONITOR_URL;
const intervalMs = Number(process.env.MONITOR_INTERVAL_MS ?? 60_000);
const timeoutMs = Number(process.env.MONITOR_TIMEOUT_MS ?? 10_000);
const expectedStatuses = new Set(
(process.env.MONITOR_EXPECTED_STATUS ?? "200")
.split(",")
.map(value => Number(value.trim()))
.filter(Number.isInteger)
);
const expectedText = process.env.MONITOR_EXPECTED_TEXT ?? "";
if (!target) throw new Error("MONITOR_URL is required");
let parsed;
try {
parsed = new URL(target);
if (!["http:", "https:"].includes(parsed.protocol)) throw new Error("unsupported protocol");
} catch (error) {
throw new Error(`Invalid MONITOR_URL: ${error.message}`);
}
if (!Number.isFinite(intervalMs) || intervalMs < 1) throw new Error("MONITOR_INTERVAL_MS must be positive");
if (!Number.isFinite(timeoutMs) || timeoutMs < 1) throw new Error("MONITOR_TIMEOUT_MS must be positive");
if (expectedStatuses.size === 0) throw new Error("MONITOR_EXPECTED_STATUS must contain a status code");
let stopping = false;
async function checkOnce() {
const started = performance.now();
let response;
try {
const signal = AbortSignal.timeout(timeoutMs);
response = await fetch(parsed, {
method: "GET",
signal,
redirect: "follow",
headers: { "user-agent": "basic-node-monitor/1.0" }
});
const elapsedMs = Math.round(performance.now() - started);
let contentOk = true;
if (expectedText) {
const body = await response.text();
contentOk = body.includes(expectedText);
}
const statusOk = expectedStatuses.has(response.status);
const ok = statusOk && contentOk;
const result = {
time: new Date().toISOString(),
ok,
status: response.status,
elapsedMs,
contentOk: expectedText ? contentOk : undefined
};
console.log(JSON.stringify(result));
return ok;
} catch (error) {
const elapsedMs = Math.round(performance.now() - started);
const aborted = error?.name === "TimeoutError" || error?.name === "AbortError";
console.error(JSON.stringify({
time: new Date().toISOString(),
ok: false,
elapsedMs,
error: aborted ? "request_timeout" : error?.name ?? "Error",
message: String(error?.message ?? error)
}));
return false;
}
}
async function run() {
await checkOnce();
if (!stopping) setTimeout(run, intervalMs);
}
function stop(signal) {
stopping = true;
console.log(JSON.stringify({ time: new Date().toISOString(), event: "stopping", signal }));
}
process.on("SIGINT", () => stop("SIGINT"));
process.on("SIGTERM", () => stop("SIGTERM"));
run().catch(error => {
console.error(error);
process.exitCode = 1;
});
Set MONITOR_EXPECTED_STATUS=200,204 when an endpoint legitimately returns either code. A redirect is followed by default; if redirects themselves matter, set redirect: "manual" and define the acceptable 3xx statuses explicitly. The optional MONITOR_EXPECTED_TEXT check downloads the body, so use it only for pages with a stable, non-personalized marker.
Why each part matters
Status is a separate decision from transport success
Fetch resolves when it receives a response, including HTTP errors. The script therefore compares the response status with a configured allow-list. This avoids reporting an error page as healthy merely because the server answered.
Elapsed time identifies degradation
performance.now() measures the duration of each attempt. Logging it for failures as well as successes helps distinguish a fast refusal, a slow upstream, and a timeout. It is a measurement for this process, not a browser-rendering metric.
Rank #2
- Dell PowerEdge R730xd 24B SFF 2U Server
- 2x Intel Xeon E5-2690 v4 2.6Ghz 14-Core (28-cores Total)
- 128GB DDR4 RAM – 4x 1.2TB 10K SAS 2.5” 12Gb/s
- Dell H730P mini 2GB 12Gb/s RAID
- 2x 750W PSU - 2x 10Gb SFP+ 2x 1Gb (RJ45) NIC
AbortSignal enforces the deadline
AbortSignal.timeout(timeoutMs) creates a signal that aborts after the selected number of milliseconds. The catch block turns both timeout forms used by Node (TimeoutError or AbortError, depending on runtime) into a failed check. No response status is treated as success.
Content checks catch soft failures
A site can return status 200 while serving a maintenance page or an application error. Set an expected marker only when it is stable. Avoid matching volatile timestamps, user names, or localized text.
Scheduling, retries, and history
The recursive setTimeout starts the next run after the current run completes. That prevents two requests from being in flight at once. A fixed interval measured from wall-clock start would be simpler, but it can create overlap when a request lasts longer than the interval.
Do not turn every transient error into an alert. A common policy is to record every result, retry a failed attempt once with a short backoff, and alert only after consecutive failures. The appropriate interval, retry count, and alert destination are context-specific; keep them configurable rather than presenting one universal value.
Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallRank #3
- MODEL P74439-005: Compact and affordable HPE ProLiant MicroServer Gen11 powered by Intel Pentium Gold G7400 3.7GHz processor, ideal for file sharing, NAS, and basic business workloads
- READY OUT OF THE BOX: Includes 16GB DDR5 UDIMM memory (expandable to 128GB), one 1TB SATA 6G Business Critical HDD, embedded Intel VROC SATA, dedicated iLO-M.2 port kit, 180w external power adapter and 1/1/1 warranty for dependable plug-and-play server operation
- WHISPER-QUIET & SPACE-SAVING: Ultra-compact mini tower design fits easily in small office spaces; supports wall, flat, or vertical placement for deployment flexibility
- INTEGRATED REMOTE MANAGEMENT: Comes with HPE iLO 6 and embedded TPM 2.0 for secure, license-free remote server administration through shared port access
- EXPANDABLE DESIGN: Two PCIe slots (including PCIe 5.0) and four LFF-NHP drive bays provide robust options for storage and component scalability. Features new MR408i-p controller support for enhanced storage performance
For persistent history, write the JSON records to a log collector or database instead of relying on console output. Include a monitor identifier, URL name (not secrets), status, elapsed time, error class, and timestamp. Redact authorization headers and response bodies. A small local process also needs a supervisor such as systemd, a container restart policy, or a scheduled job so it is restarted after a crash.
Fetch versus node:http
| Concern | Built-in fetch | Low-level node:http |
|---|---|---|
| Status handling | Inspect response.status; HTTP errors do not reject automatically. |
Inspect the response object’s status field. |
| Timeout cancellation | Pass AbortSignal.timeout() as signal. |
Pass an AbortSignal or explicitly destroy/abort the request. |
timeout option |
Use an AbortSignal deadline. | timeout and setTimeout() notify or add timeout behavior; they do not by themselves abort the request. |
| Compatibility | Confirm the Node version provides the Fetch API and timeout signal. | Useful when you need lower-level socket, agent, or streaming controls. |
Node’s HTTP documentation explicitly warns: “Setting the timeout option or using the setTimeout() function will not abort the request or do anything besides add a 'timeout' event.” If you choose node:http, attach an AbortSignal and handle the event rather than assuming a timeout ended the request.
Troubleshooting common failures
Every check is reported as healthy for a 404 or 500
Check that the code compares response.status (or response.ok) and that MONITOR_EXPECTED_STATUS is not accidentally set to the failing code.
Requests never finish
Confirm that the signal is passed in the fetch options and that MONITOR_TIMEOUT_MS is a positive number. With node:http, setting only timeout is insufficient; abort or destroy the request explicitly.
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Clear out junk files and repair common Windows errors3Scan for outdated or missing drivers - takes under a minuteRank #4
- Dell PowerEdge T140 Mini Tower Server for Small Businesses, Branch Locations, and Home Offices
- Intel Xeon E-2124 Quad-Core 3.3GHz 8MB CPU, Max Turbo Up To 4.3GHz Memory: 32GB DDR4 PC4-21300 2666MHz Unbuffered Memory
- 8TB (4 x 2TB) 7.2K 6Gb/s SATA 3.5" HDDs for High Capacity Storage; PERC S140 6Gb/s RAID Controller
- iDRAC9 Basic; On-Board Dual Port 1Gb LOM
- iDRAC9 Basic; On-Board Dual Port 1Gb LOM
Timeouts appear as different error names
Handle both TimeoutError and AbortError, as the example does. Log the elapsed time and classify the result as failed whenever no response was received.
DNS, TLS, or connection errors
These occur before an HTTP response exists. Keep the error name and message, verify DNS and certificate validity from the monitor’s network, and avoid logging secrets embedded in a URL.
Content check fails intermittently
The marker may be personalized, localized, loaded by client-side JavaScript, or changed by a deployment. Choose a stable server-rendered token or remove the content assertion and monitor status and latency only.
Checks overlap or consume too many resources
Use the completion-based scheduling shown above, increase the interval, and cap response-body reads. A monitor that checks many URLs should use a bounded worker pool rather than starting unbounded promises.
Best Value
Or skip the browser setup
If your goal is a clean visual capture rather than an HTTP availability result, ScreenshotNeo provides a single request to return a PNG, JPEG, WebP, or PDF. It accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers. It also offers an MCP server with take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients.
See the ScreenshotNeo API documentation for all options. A one-call capture is:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
Every feature is included on every plan: 1,000 screenshots per month are free with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account to get an API key.
Operational checklist
- Keep the URL, allowed statuses, interval, timeout, and marker in configuration.
- Set a timeout shorter than the interval and verify that it actually aborts.
- Record status, elapsed time, error class, and timestamp for every attempt.
- Test from the same network region and identity that matters to your users.
- Redact credentials and avoid storing full response bodies.
- Choose retries and alert thresholds based on the endpoint’s failure tolerance.
- Run the process under a supervisor and monitor the monitor itself.
Frequently Asked Questions
How do I check if a website is up with Node.js?
Send a request, verify that its status is in your configured healthy set, measure elapsed time, and treat network or timeout exceptions as failures. The complete script above implements that flow.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →How do I set a timeout for fetch in Node.js?
Create AbortSignal.timeout(milliseconds) and pass it as the fetch option signal. Catch the resulting timeout or abort error and record a failed check.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




