localhost vs 127.0.0.1

localhost vs 127.0.0.1

October 6, 2023

Every web developer is familiar with localhost. It’s what you see when you run npm run dev or similar commands to start a local HTTP server. You might also know that 127.0.0.1 is the IP address of localhost. But what’s the difference, and why might you encounter Connection refused when trying to reach your localhost by IP? This post will shed light on these questions.

127.0.0.1

In a network, each device can be identified by an IP address. The IP address 127.0.0.1 belongs to a virtual network interface. This special interface represents the device itself and is only accessible to programs running on this device.

localhost

localhost is a hostname, which is a human-friendly representation of a device in a network.

Like any other hostname or domain, this text should be resolved into an IP address. When you open any domain in a browser, the browser retrieves one or more IP addresses associated with that domain.

localhost typically corresponds to two IP addresses:

  1. 127.0.0.1 - the well-known IPv4 address (IP address version 4).
  2. [::1] - the newer IPv6 address (IP address version 6).

Connection refused

You might encounter this issue when testing API, for instance.

Let’s delve into why http://localhost:3000 works perfectly in the browser, but http://127.0.0.1:3000 doesn’t. To illustrate, start web app in the console:

$ npm run dev

Nuxt 3.7.4 with Nitro 2.6.3

  ➜ Local:    http://localhost:3000/
  ➜ Network:  use --host to expose

Make request with curl in the console:

$ curl -v 'http://127.0.0.1:3000/'

*   Trying 127.0.0.1:3000...
* connect to 127.0.0.1 port 3000 failed: Connection refused
...

As we learned earlier, localhost stands for 127.0.0.1, but direct request fails. This happens because the dev server is bound to the IPv6 address [::1]. Make the same request, but to the IPv6 address:

$ curl -v 'http://[::1]:3000/'

*   Trying [::1]:3000...
* Connected to ::1 (::1) port 3000 (#0)

There you have it. Finally, let’s see what happens when we use the hostname:

$ curl -v 'http://localhost:3000/'

curl -v 'http://localhost:3000/'
*   Trying 127.0.0.1:3000...
* connect to 127.0.0.1 port 3000 failed: Connection refused
*   Trying [::1]:3000...
* Connected to localhost (::1) port 3000 (#0)

localhost is resolved into two addresses, and curl tries both.

Solution

In light of this, there are two potential solutions. The first is to consistently use localhost wherever your dev server’s address is required, such as in testing tools, scripts, and so on.

The second solution is to configure your web application to start the dev server on 127.0.0.1. In this case, localhost will continue to work as well.

By understanding the difference between localhost and 127.0.0.1, and knowing how to handle potential connection issues, you can ensure a smoother development process.