localhostly Português

localhostly is a free localtunnel alternative

If you are leaving localtunnel, here is what you get instead: the same npm install, one public HTTPS URL and a name that comes back after a short drop. Run npx localhostly 3000 and port 3000 answers at https://brave-amber-fox.localhostly.iblabs.io, behind NAT. The free account asks only for an e-mail: 2 tunnels, 1000 requests per minute and 25 GiB a month.

Get your token Install localhostly

$ npx localhostly 3000

https://brave-amber-fox.localhostly.iblabs.io → http://127.0.0.1:3000
Ctrl+C to stop. Requests:

21:14:03  GET     /                                        200 12ms
21:14:05  POST    /api/webhook                             201 31ms

The free account in numbers

The free account is the only account, with no paid plan and no card behind it. Its limits are the five numbers below: the traffic limit counts both directions and the month turns on the 1st, in UTC. Past a limit, visitors get a 429 page that says which limit was reached and when the tunnel works again.

One command, one public URL

The localhostly agent runs on your computer and keeps one outgoing WebSocket connection to the localhostly server, so nothing is opened on your router or firewall. A visitor opens your URL, the server reads the name in it, passes the request down that connection, and the agent replays it on your local port and streams the answer back. HTTP requests and WebSocket connections both pass.

  1. Get a token. Type your e-mail in the sign-up form; the token appears on the page, with no confirmation e-mail.
  2. Save it. localhostly login <token> writes it to ~/.localhostly/config.json, readable only by your user.
  3. Open the tunnel. npx localhostly 3000 with nothing installed, or localhostly 3000 after npm i -g localhostly. The terminal prints the public URL and one line per request: time, method, path, status and milliseconds.

Your app sees the visitor's method, path, headers and body, with X-Forwarded-For, X-Forwarded-Proto: https and X-Forwarded-Host added. --host myapp.test:3000 sends a different address and Host to it. The name is drawn at random from 3 English words, adjective, color and animal; nobody picks it.

The URL comes back after a drop

When the connection drops, the agent reconnects on its own: it waits 1 second, doubles the wait on each try up to 60 seconds, and asks for the same name. The name stays reserved for 10 minutes after a drop, so within that time the same URL answers again and nothing that points to it has to change.

After a longer drop the name is released: the agent comes back with a new one and prints name changed. The reservation lives in the server's database and survives a new release of the server, so a deploy on our side does not change your URL.

Webhooks and API clients reach your app directly

A webhook call or an API client is not a browser, so it gets no warning page: the request goes straight to your app. Paste https://<name>.localhostly.iblabs.io/<your path> into the provider's webhook settings; every call shows up in your terminal with method, path, status and time. If your local app is down, the visitor gets a 502 page that says so.

Browsers see a warning page on their first visit, saying the site runs on someone's own computer; the button on it sets a cookie that skips it for 24 hours. A client that cannot click can send the X-Localhostly-Skip-Warning header instead, and a tunnel opened with --allow shows no warning page at all.

Streaming responses and big uploads pass through

Bodies travel in pieces of up to 64 KiB in both directions and never sit whole in memory: in the measured run, a 20 MiB upload went through with peak memory under 100 MiB, and a 20 MiB download reached a slow visitor the same way.

Your app has 60 seconds to start answering; after the first byte there is no time limit, so long downloads and Server-Sent Events pass. In a measured stream, events written at 0, 3 and 6 seconds reached the visitor at 0.6, 3.6 and 6.6 seconds. A visitor's WebSocket reaches your app too, and the upgrade completes only after your app accepts it, with the subprotocol it chose.

Lock the tunnel with a password or an IP list

--password makes every visitor type a password in the browser's login box; without a value, localhostly generates a 12-character password and prints it only in your terminal. The visitor's Authorization header never reaches your app.

--allow 203.0.113.7,10.0.0.0/8 lets only those IP addresses or ranges in, IPv4 or IPv6, up to 64 entries; everyone else gets a 403 page showing their address, and their WebSocket upgrade gets 403 too. With both options, a visitor needs the right address and the password.

Keep it running as a system service

localhostly service install 3000 turns the tunnel into a system service: systemd on Linux, launchd on macOS, a Windows service. The service reconnects by itself, keeps the name it was given and asks for it again after a reboot, and does not give up if the server refuses it. localhostly service status tells you whether it is running and localhostly service uninstall removes it.

Install

localhostly runs on Node.js 24 or newer.

The npm package holds only the agent, not the server. Save your token with localhostly login <token> and localhostly 3000 opens the tunnel.

Get your token

Sign-up asks for an e-mail address and nothing else; the token appears on the sign-up page, with no confirmation e-mail. localhostly login <token> saves it on your computer; then localhostly 3000 opens the tunnel.

Get your token