Create HTTP Web Server in Node.js with Code Example
โก Smart Summary
Node.js builds a working web server in a few lines using the built-in http module. The server listens on a chosen port and answers each request with a status code and body, while separate code fetches data from other sites.

The Node.js framework is mostly used to create server-based applications. It can easily be used to build web servers that serve content to users.
Several modules handle server-related requests, the built-in http module chief among them. We will look at how to create a basic web server application using Node.js, and then at how to request data from another site.
Node as a web server using HTTP
Let us look at an example of how to create and run a first Node.js application.
The application creates a simple server module that listens on port 7000. When a request is made through the browser on that port, the server sends a Hello World response to the client.
Code Explanation
- The
requirefunction reads a JavaScript file, executes it, and returns its exports object. Here it loads thehttpmodule so its functionality is available in the application. - A server application is created from a simple function. That function runs every time a request reaches the server.
- When a request is received, the response is sent with a status of 200. This is the standard status code in an HTTP header for a successful response.
- The response body itself is the string Hello World.
server.listenmakes the application listen for client requests on port 7000. Any available port may be used.
If the command runs successfully, the following output appears in the browser.
Output
From the output:
- Browsing to the localhost URL on port 7000 displays the string Hello World in the page.
- Because the code specifies port 7000, the output is visible only when browsing to that port.
Here is the code for reference:
var http = require('http'); var server = http.createServer(function(request, response) { response.writeHead(200, { "Content-Type": "text/plain" }); response.end("Hello World\n"); }); server.listen(7000);
Handling GET Requests in Node.js
Making a GET request to retrieve data from another site is straightforward in Node.js. Historically this needed the request module, installed from the command line:
npm install request
That command asks the Node package manager to download the required module and install it. When installation succeeds, the command line shows the installed module name and version in the form <name>@<version>.
In the snapshot above, the request module and its version number were downloaded and installed.
Code Explanation
- The
requestmodule installed in the previous step provides the functions needed to make GET requests to websites. - A GET request is made to a site, and a callback runs once a response arrives. The callback receives three parameters:
- Error โ records any error raised while making the request.
- Response โ carries the HTTP headers returned with the response.
- Body โ contains the entire content of the response.
- The content received in the
bodyparameter is written to the console.
Here is the code for reference:
var request = require("request"); request("https://example.com", function(error, response, body) { // Always check the error parameter before using the body if (error) { console.error("Request failed:", error.message); return; } console.log(body); });
โ ๏ธ Deprecation notice: the request module was fully deprecated in February 2020 and receives no further updates. It still installs and runs, so the example above remains valid for existing projects, but npm install request now prints a deprecation warning. New code should use the built-in fetch function shown in the next section.
How to Make HTTP Requests with Native fetch in Node.js
Node has included a global fetch function since version 18, matching the API browsers already provide. No package installation is required, and the function returns a promise, so it works directly with async/await.
// No require and no npm install needed on Node 18 or later async function getData() { try { const response = await fetch("https://example.com"); // fetch does NOT reject on 404 or 500 โ check ok yourself if (!response.ok) { throw new Error("HTTP status " + response.status); } const body = await response.text(); console.log(body); } catch (err) { // Network failures and the throw above both land here console.error("Request failed:", err.message); } } getData();
Three differences from the callback style are worth noting. First, fetch rejects only on a network-level failure; an HTTP 404 or 500 still resolves successfully, which is why the response.ok check exists and why omitting it is the most common mistake when moving from request. Second, the body is not delivered with the response โ it must be read explicitly with response.text() for plain text or response.json() for JSON, and each of those returns a promise of its own. Third, because the whole call is promise-based, a single try/catch covers both the request and the body read, replacing the error-first callback parameter entirely.
For scripts that must run on Node 16 or earlier, install node-fetch or axios instead, since both expose a comparable promise-based interface and require only a change to the import line once the runtime is upgraded.
request vs fetch vs axios: Which to Use
Three HTTP clients appear across most Node material, and only one of them is a sensible default for new work. They differ in maintenance status, in whether a dependency is needed at all, and in how each one signals an error status, so the table below sets them side by side.
| Aspect | request | fetch (built in) | axios |
|---|---|---|---|
| Status | Deprecated since 2020 | Maintained in core | Actively maintained |
| Installation | npm package | None on Node 18+ | npm package |
| Style | Error-first callback | Promise | Promise |
| JSON parsing | Manual, or a json option | Manual via response.json() | Automatic |
| Rejects on 404 or 500 | No | No | Yes |
Use fetch for new projects on a current Node version, since it adds no dependency and matches the browser API developers already know. Choose axios when automatic JSON handling, request interceptors, or rejection on error statuses would save real code. Keep request only inside legacy applications that already depend on it, and plan to replace it.
Common Node.js Server Errors and How to Fix Them
Most failures when starting a first Node server come from ports, paths, or a missing response rather than from the server code itself.
- EADDRINUSE: another process already holds the port. Run
netstat -ano | findstr :7000on Windows, orlsof -i :7000on macOS and Linux, then stop that process or pick a different port. - EACCES on a low port: ports below 1024 need elevated privileges. Use a port above 1024 during development, such as 3000 or 7000.
- The browser hangs and never loads: the handler never called
response.end(). The connection stays open until it times out, so every path through the handler must end the response. - Cannot find module ‘http’: the filename was misspelled, or the script is running in a browser rather than Node. Core modules need no installation.
- Changes do not appear: Node loads the file once at startup. Restart the process after each edit, or run it under a watcher such as
node --watch server.js.




