A request to http://localhost or http://127.0.0.1 never touches a network card: both point to the loopback interface inside the operating system, which only programs on the same machine can use. A phone on the same Wi-Fi needs the machine's LAN address, and the server must be listening on it.
| Address | Meaning | Who can connect |
|---|---|---|
| localhost, 127.0.0.1, ::1 | Loopback | This machine only |
| 0.0.0.0, :: | "All interfaces" (listening only) | Not a destination |
| 192.168.x.x, 10.x.x.x, 172.16-31.x.x | Private (RFC 1918) | Your LAN |
| 100.64.0.0/10 | Carrier-grade NAT (RFC 6598) | Your ISP's network |
| 169.254.x.x | Link-local: DHCP failed | Same link only |
The bind address decides who gets in. A server bound to 127.0.0.1 refuses LAN connections even when the firewall allows them; one bound to 0.0.0.0 accepts connections on every IPv4 address the machine has. This script starts one of each and calls both through the LAN address:
import http from 'node:http';
import os from 'node:os';
const lan = Object.values(os.networkInterfaces()).flat()
.find((a) => a.family === 'IPv4' && !a.internal).address;
const hello = (req, res) => res.end('hello');
const listen = (port, host) =>
new Promise((ok) => http.createServer(hello).listen(port, host, ok));
await listen(3000, '127.0.0.1'); // loopback only
await listen(3001, '0.0.0.0'); // every IPv4 interface
for (const url of ['http://127.0.0.1:3000', `http://${lan}:3000`, `http://${lan}:3001`]) {
const reply = await fetch(url).then((r) => r.text(), (err) => err.cause.code);
console.log(url, '->', reply);
}
process.exit();http://127.0.0.1:3000 -> hello http://192.168.0.10:3000 -> ECONNREFUSED http://192.168.0.10:3001 -> hello
Development tools choose differently. Vite 25,978 listens on localhost unless you run npx vite --host; Python's python -m http.server listens on all interfaces unless you add --bind 127.0.0.1. On café Wi-Fi, "all interfaces" exposes your work to strangers. And since 0.0.0.0 is only a listening address, type localhost or the LAN address into the browser.
To find the LAN address, run ipconfig on Windows (look for IPv4 Address), ip -4 addr or hostname -I on Linux, and ipconfig getifaddr en0 on macOS. The router hands these addresses out by DHCP, so they can change after a reboot, which breaks bookmarks and the port forwarding rules of Port Forwarding. The cleanest fix is a DHCP reservation in the router's admin page, which ties an address to the machine's MAC address. Alternatively, set a static address outside the router's DHCP pool on the machine itself, for example netsh interface ipv4 set address name="Wi-Fi" static 192.168.0.10 255.255.255.0 192.168.0.1 (address, subnet mask, gateway) in an administrator terminal on Windows.