Tutorials Logic, IN info@tutorialslogic.com
Navigation
Home About Us Contact Us Blogs FAQs
Tutorials
All Tutorials
Services
Academic Projects Resume Writing Website Development
Practice
Quiz Challenge Interview Questions Certification Practice
Tools
Online Compiler JSON Formatter Regex Tester CSS Unit Converter Color Picker
Compiler Tools

Node.js HTTP Module Create Web Server: Tutorial, Examples, FAQs & Interview Tips

HTTP Module in Node.js

The http module is one of Node.js's most important built-in modules because it allows you to create web servers and handle HTTP requests directly. Since Node.js is widely used for APIs, back-end services, and real-time applications, understanding the http module gives you a clear picture of how a server actually works before you move to frameworks like Express.

At a high level, the HTTP module helps a Node.js program listen for incoming requests, inspect request information such as the URL and method, and send a response back to the client. This means that when a browser, mobile app, or another service calls your server, the http module is one of the core tools that can receive that request and decide what to return.

Importing the HTTP Module

The HTTP module is built into Node.js, so you do not need to install it with npm. You can load it immediately using require() in CommonJS.

Import HTTP
const http = require("http");

Once the module is imported, you can create a server using http.createServer(). This method returns a server object and takes a callback function that runs every time a client connects.

Creating a Basic Web Server

The simplest use of the HTTP module is to create a server that responds with plain text or HTML. The callback function receives two important objects:

  • req or request - contains information sent by the client.
  • res or response - used to send data back to the client.
Basic HTTP Server
const http = require("http");

const server = http.createServer((req, res) => {
    res.write("Hello from Node.js HTTP server!");
    res.end();
});

server.listen(8080, () => {
    console.log("Server is running on http://localhost:8080");
});

This server listens on port 8080. Whenever someone visits http://localhost:8080, the callback runs, the server writes a response, and res.end() closes the response. It is very important to call res.end(), because without it the client may wait indefinitely for the response to finish.

Understanding Request and Response Objects

The request object contains information about what the client asked for. It includes values like the request URL, HTTP method, headers, and body data. The response object is used to set headers, choose status codes, and send the final response body. Together, these two objects form the core of basic Node.js server logic.

For example, if the browser requests /about, the request object lets you inspect that path. If the client sends a POST request to /users, the request object tells you the method is POST. On the response side, you might send back HTML, JSON, or a plain text message depending on what the client needs.

Sending Headers and Status Codes

A good HTTP response should include the right status code and content type. The status code tells the client whether the request was successful, redirected, invalid, or failed. The Content-Type header tells the client how to interpret the returned data, such as plain text, HTML, or JSON.

Headers and HTML Response
const http = require("http");

http.createServer((req, res) => {
    res.writeHead(200, { "Content-Type": "text/html" });
    res.write("<h1>Welcome to Tutorials Logic</h1>");
    res.end();
}).listen(8080);

In this example, 200 means success, and text/html tells the browser to render the response as HTML. If you omit the correct content type, the browser may treat the response as plain text instead of rendering it as intended.

Common Status Codes

Status CodeMeaning
200Request succeeded
201Resource created successfully
400Bad request from the client
404Requested resource not found
500Internal server error

Using the correct status code makes APIs and web applications easier to debug and easier for clients to understand. A response body may look correct, but if the status code is wrong, consumers of the API may still behave incorrectly.

Routing with req.url and req.method

Before using frameworks, basic routing in Node.js is often done manually with req.url and req.method. This lets you return different responses depending on the path or request type.

Manual Routing
const http = require("http");

http.createServer((req, res) => {
    if (req.url === "/" && req.method === "GET") {
        res.writeHead(200, { "Content-Type": "text/plain" });
        res.end("Home page");
    } else if (req.url === "/about" && req.method === "GET") {
        res.writeHead(200, { "Content-Type": "text/plain" });
        res.end("About page");
    } else {
        res.writeHead(404, { "Content-Type": "text/plain" });
        res.end("Page not found");
    }
}).listen(8080);

This style works well for learning and small examples. In large projects, however, manual routing becomes hard to maintain, which is one reason frameworks like Express are so popular.

Reading the URL and Query String

The request object contains a url property that includes the path and query string. If a client visits /search?q=node, the req.url value contains that URL fragment. To work with query parameters properly, developers usually combine the HTTP module with the URL class or the url module.

Read Query Parameters
const http = require("http");

http.createServer((req, res) => {
    const url = new URL(req.url, "http://localhost:8080");
    const keyword = url.searchParams.get("q");

    res.writeHead(200, { "Content-Type": "text/plain" });
    res.end(`Search keyword: ${keyword}`);
}).listen(8080);

If the browser requests http://localhost:8080/?q=nodejs, this server returns Search keyword: nodejs. Query parameters are very common in search pages, filters, pagination, and API endpoints.

Returning JSON from the HTTP Module

Modern APIs often respond with JSON rather than HTML. To send JSON correctly, you should set the Content-Type header to application/json and convert the JavaScript object to a string using JSON.stringify().

JSON API Response
const http = require("http");

http.createServer((req, res) => {
    const data = {
        success: true,
        message: "Data fetched successfully",
        users: [
            { id: 1, name: "Aman" },
            { id: 2, name: "Riya" }
        ]
    };

    res.writeHead(200, { "Content-Type": "application/json" });
    res.end(JSON.stringify(data));
}).listen(8080);

This kind of response is common in REST APIs. A front-end application can call the endpoint and parse the JSON result to display users, products, posts, or any other resource.

Handling POST Data

When the client sends data to the server using POST, the request body does not arrive all at once in simple Node.js HTTP handling. Instead, it arrives as a stream of chunks. You need to collect the chunks, combine them, and then parse the final result. This is one of the reasons raw Node.js HTTP handling feels more low-level than frameworks like Express.

Read POST Body
const http = require("http");

http.createServer((req, res) => {
    if (req.method === "POST" && req.url === "/users") {
        let body = "";

        req.on("data", chunk => {
            body += chunk;
        });

        req.on("end", () => {
            const user = JSON.parse(body);

            res.writeHead(201, { "Content-Type": "application/json" });
            res.end(JSON.stringify({
                message: "User created",
                user
            }));
        });
    } else {
        res.writeHead(404, { "Content-Type": "text/plain" });
        res.end("Route not found");
    }
}).listen(8080);

This example introduces event-driven request handling. The server listens for data events while chunks arrive and then waits for the end event before using the complete body. This is a good demonstration of why Node.js is often described as asynchronous and event-driven.

Serving Different Content Types

The HTTP module can return different types of content depending on the need of the application. For example, a server may return HTML to a browser, JSON to a front-end application, or plain text for a simple status endpoint. Choosing the correct content type is important because the client uses that header to decide how the data should be interpreted.

  • text/plain for plain text.
  • text/html for HTML content.
  • application/json for JSON APIs.
  • text/css for CSS files.
  • application/javascript for JavaScript files.

Raw HTTP Module vs Express

Learning the raw HTTP module is valuable because it shows you what happens underneath a framework. However, real applications often use Express or similar libraries because they provide easier routing, middleware support, body parsing, and a cleaner structure. For example, instead of manually checking req.url and assembling request bodies yourself, Express gives dedicated methods like app.get(), app.post(), and built-in middleware patterns.

Still, understanding the HTTP module makes Express easier to learn because you can see what the framework is abstracting away. Express does not replace the concept of HTTP requests and responses; it simply provides a more convenient API on top of them.

Common Beginner Mistakes

One common mistake is forgetting to call res.end(), which leaves the connection open and causes the browser or client to keep waiting. Another is returning JSON without using JSON.stringify(). A third mistake is not setting the correct content type, which can lead to incorrect rendering or parsing on the client side. Beginners also often expect POST request bodies to appear instantly in one variable, not realizing that body data usually arrives as chunks when working with the raw HTTP module.

Another frequent issue is using port numbers inconsistently. If your code listens on port 8080, the browser must open the same port. If another app is already using that port, the server will fail to start. Reading the error messages and logging startup output with console.log() is a good habit.

A Practical Mental Model

You can think of the HTTP module as the lowest everyday layer of web server programming in Node.js. The client sends a request, your server reads that request, decides what to do, and sends a response. Every route, API endpoint, HTML page, and JSON response eventually follows that same core pattern. Once this model is clear, it becomes much easier to understand frameworks, middleware, REST APIs, and server architecture in general.

Key Takeaways
  • The http module is built into Node.js and is used to create web servers.
  • http.createServer() receives a request object and a response object for each incoming connection.
  • Always finish the response with res.end().
  • Use res.writeHead() to set status codes and response headers such as Content-Type.
  • Manual routing can be done with req.url and req.method.
  • JSON responses should use application/json and JSON.stringify().
  • POST request bodies are usually read as streams of chunks in the raw HTTP module.

Ready to Level Up Your Skills?

Explore 500+ free tutorials across 20+ languages and frameworks.