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 reinstallSome links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
For most new Node.js services, start with the built-in Fetch API. It is promise-based, requires no dependency, and follows the web Request/Response model. Choose Undici when you need its package-level dispatcher controls, node:http for explicit streaming and connection management, or a wrapper such as Got, Axios, Ky, node-fetch, or SuperAgent when its API and integrations match your application. There is no universal fastest client; your runtime, error model, retries, streaming needs, and operational controls should determine the choice.
Quick decision guide
| Option | Best fit | Important qualification |
|---|---|---|
Node.js built-in fetch |
Standard promise-based requests in current Node.js | HTTP 4xx/5xx responses fulfill the promise; inspect response.ok or response.status. |
| Undici | Node-focused Fetch plus dispatcher, client, pool, and agent controls | Its lower-level APIs provide controls that the global Fetch API does not. |
| Axios | Teams already using its recognizable promise-client style | Confirm current runtime support and exact features in the project documentation. |
| Got | Node services needing retries, streams, pagination, HTTP/2, hooks, or detailed timeouts | Retries are enabled by default; make idempotency and rate limits explicit. |
| Ky | A small Fetch-based wrapper | Verify current runtime support and feature details before standardizing. |
| node-fetch | Compatibility or dependency requirements on projects that cannot use built-in Fetch | New projects on current Node releases generally do not need a separate Fetch implementation. |
| SuperAgent | Shared browser/server usage or fluent request building | Choose it for that API style rather than assuming a performance advantage. |
node:http is the lower-level built-in baseline, not an eighth high-level client. Request is a migration concern: its maintainers and Got’s migration notes identify it as unmaintained, so do not select it for new work.
1. Node.js built-in Fetch API
Current Node.js releases expose fetch globally, so a basic request needs no import or package install. Fetch uses familiar web semantics and works well for JSON APIs, cancellation with AbortController, redirects, and ordinary request/response bodies.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Reliable JSON request
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), 10_000);
try {
const response = await fetch('https://api.example.com/users/42', {
headers: { accept: 'application/json' },
signal: controller.signal
});
if (!response.ok) {
const detail = await response.text();
throw new Error(`HTTP ${response.status}: ${detail}`);
}
const user = await response.json();
console.log(user);
} finally {
clearTimeout(timer);
}
A network failure, DNS error, or aborted request rejects the promise. A server response such as 404 does not; always check status before parsing or using the body. For untrusted responses, avoid unbounded buffering: stream the body or enforce an application-specific size limit.
#1 Best Overall
When built-in Fetch is enough
- You target a Node version with global Fetch enabled and want zero dependency overhead.
- Your team prefers standard
Request,Response,Headers, andAbortSignalsemantics. - You can implement retries, timeout policy, response limits, and error classes in application code.
2. Undici
Undici is the project that implements Fetch for Node.js and also exposes Node-focused dispatcher APIs. Its Fetch accepts a custom dispatcher. For more explicit control, a Client targets one origin and connection, a Pool manages connections, and an Agent routes across origins. These layers serve different needs, so do not assume the package API and Node’s global Fetch are interchangeable without checking the same-implementation guidance.
Package-level Fetch with a dispatcher
import { fetch, Agent } from 'undici';
const dispatcher = new Agent({
connections: 10,
keepAliveTimeout: 10_000
});
const response = await fetch('https://api.example.com/data', { dispatcher });
if (!response.ok) throw new Error(`HTTP ${response.status}`);
console.log(await response.json());
await dispatcher.close();
Use a dispatcher when connection limits, pooling, or transport policy are part of your design. For a single origin with intensive traffic, a Client or Pool can make that relationship explicit. Stream large response bodies and enforce limits rather than calling json() on data whose size you do not control.
3. Axios
Axios is a familiar promise-based client used in many JavaScript codebases. It can be a practical choice when your organization already has Axios interceptors, shared configuration, or error-handling conventions. Before adopting it in a new service, check the current documentation for your Node version, module format, adapters, and the exact options you require; the available evidence does not establish a complete feature matrix or a performance ranking.
import axios from 'axios';
try {
const { data } = await axios.get('https://api.example.com/users/42', {
timeout: 10_000,
headers: { accept: 'application/json' }
});
console.log(data);
} catch (error) {
if (error.response) {
console.error('HTTP failure', error.response.status);
} else {
console.error('Transport or setup failure', error.message);
}
}
Keep Axios-specific interceptors and error assumptions at a service boundary so migrating to Fetch later does not spread client details through business code.
4. Got
Got is designed for Node.js and documents Promise and stream APIs, pagination, HTTP/2, retries, advanced timeout phases, caching, proxy support, Unix sockets, hooks, and plugins. Those features can reduce application plumbing in an operationally complex service.
Rank #2
Retry policy is application behavior
Got retries on failure by default. Review the retry limit, methods, status codes, and backoff for every endpoint. Repeating a non-idempotent POST can create duplicate work, and retries can amplify an outage or violate a provider’s rate limit. Disable or narrow retries when the operation is not safe to repeat, and use an idempotency key where the remote API supports one.
import got from 'got';
const response = await got('https://api.example.com/report', {
responseType: 'json',
timeout: { request: 15_000 },
retry: { limit: 2, methods: ['GET'], statusCodes: [408, 429, 500, 502, 503, 504] }
});
console.log(response.body);
Got’s documentation is the project’s own feature account, not an independent benchmark. Select it for the controls you will actually configure.
5. Ky
Ky wraps Fetch rather than replacing its programming model. It may suit teams that want a concise Fetch-style API with wrapper conveniences. Verify its current Node runtime support, release version, retry behavior, and option names in the project documentation before locking a production dependency.
6. node-fetch
node-fetch provides a Fetch API implementation for Node.js. It remains relevant when a project has a compatibility floor below the Node release that supplies global Fetch, when a dependency explicitly expects it, or when you need that package’s release behavior. On current Node versions, adding node-fetch solely to call fetch duplicates a platform feature; document the compatibility reason if you keep it.
7. SuperAgent
SuperAgent describes itself as an HTTP client for Node.js and browsers. Its fluent request-building style and shared server/browser API can be useful for isomorphic code. Compare its body handling, timeout and cancellation behavior, and maintenance policy with your actual targets; do not infer a universal speed advantage from API style.
Rank #3
import request from 'superagent';
const response = await request
.get('https://api.example.com/users/42')
.set('accept', 'application/json')
.timeout({ response: 10_000, deadline: 15_000 });
console.log(response.body);
When the lower-level node:http module is the right tool
Node’s stable node:http API is deliberately low-level. Its interfaces are designed for large, possibly chunk-encoded messages and are careful never to buffer entire requests or responses, allowing you to stream data. Use it for large uploads/downloads, custom backpressure, protocol-level behavior, or integrations that require raw sockets.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Connection reuse and cleanup
http.Agent manages connection persistence and reuse. Configure keep-alive and socket limits deliberately, and destroy an Agent when it is no longer needed; unused sockets consume operating-system resources.
import http from 'node:http';
const agent = new http.Agent({ keepAlive: true, maxSockets: 50 });
http.get('http://example.com/large-file', { agent }, (res) => {
if (res.statusCode < 200 || res.statusCode >= 300) {
res.resume();
throw new Error(`HTTP ${res.statusCode}`);
}
res.pipe(process.stdout);
});
// Call agent.destroy() during shutdown.
How to choose for a real project
Runtime and portability
- Choose built-in Fetch for current Node-only services that need a standard API.
- Choose a browser/server-sharing client when the same request code must run in both environments.
- Check your minimum Node version, ESM/CommonJS mode, and deployment image before installing a package.
Error semantics
Define separate handling for transport failures, non-2xx HTTP statuses, body-parsing failures, cancellation, and timeouts. Fetch-style clients require an explicit status check; wrappers may reject on HTTP errors or expose richer metadata.
Data and protocol needs
Use streaming APIs for large bodies, pagination, or uploads. Consider Undici dispatchers, Got’s documented HTTP/2 and proxy support, or raw node:http when connection and protocol controls matter. Set body-size limits for untrusted input.
Maintenance and dependencies
Prefer the platform when it meets your needs, and otherwise pin and review the package you adopt. Do not start new work on Request, which is unmaintained.
Rank #4
Performance, reliability, and cost notes
No source here supplies a shared benchmark or universal performance winner. If latency or throughput is central, benchmark your own Node version, payload sizes, concurrency, TLS setup, connection reuse, and response-consumption pattern. Measure retries separately from first-attempt latency. In production, set finite timeouts, cap retries, propagate cancellation, log status and duration, and close agents or dispatchers during shutdown.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Common problems and fixes
“Fetch succeeded” but the API returned 404
That is expected Fetch behavior. Check response.ok or response.status before parsing and throw an application error for non-2xx responses.
Requests hang indefinitely
Fetch has no universal request deadline. Use AbortController; with Got or Axios, configure their timeout options. Distinguish connection, response, and total deadlines where the library supports phases.
Memory usage spikes on large responses
Avoid arrayBuffer(), text(), or json() for unbounded bodies. Consume the stream incrementally, enforce a byte limit, and cancel or destroy the connection when the limit is exceeded.
Free tools Windows power users keep installed
One-click scans. No signup required.
Retries duplicate writes
Inspect the client’s defaults (Got retries by default), restrict retries to safe methods or known transient statuses, and use idempotency keys for repeatable writes.
Socket or connection exhaustion
Bound pool or agent connections, reuse them intentionally, and destroy dispatchers and agents during shutdown. Leaked keep-alive sockets consume OS resources.
Or skip the browser setup for screenshot jobs
If your Node service’s HTTP work is collecting website screenshots, ScreenshotNeo removes the browser automation layer. One GET request returns PNG, JPEG, WebP, or PDF. Before capture it accepts cookie/consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be disabled. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers report the page verdict and billing status. Its MCP server lets Claude, Cursor, and other MCP clients call take_screenshot, get_page_info, and capture_pdf.
See the complete options and authentication details in the ScreenshotNeo documentation. cURL:
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Python:
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
Node.js:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
The Free plan includes 1,000 screenshots each month with no card; paid plans start at $5 for 3,000. Create a free ScreenshotNeo account.
Frequently Asked Questions
Should I replace Axios with Fetch immediately?
Not necessarily. Keep Axios when its interceptors, shared configuration, or team conventions provide real value; use built-in Fetch for new code when its standard semantics and your own wrappers are sufficient.
Is Undici the same thing as Node’s global fetch?
Undici implements Fetch for Node, but package-level Undici APIs also expose dispatchers and lower-level clients. Check the implementation guidance before mixing classes or dispatchers from different layers.
When should I use streams instead of JSON helpers?
Use streams for large or untrusted bodies, large uploads/downloads, or when backpressure matters. Buffer JSON only when the response size is bounded and acceptable for your process.
What happened to Request?
Request is unmaintained and should be treated as a migration source, not a new-project recommendation.
The Bottom Line
Start with built-in Fetch, move to Undici or node:http for connection and streaming control, and choose a wrapper only when its documented behavior solves a concrete need.
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.

