localhostly Português

localhostly is a free LocalXpose alternative

If you are leaving LocalXpose, here is what you get instead: one command, one public HTTPS URL and a free account with no paid plan behind it. Run localhostly 3000 and port 3000 answers at https://brave-amber-fox.localhostly.iblabs.io, behind NAT. Sign-up asks only for an e-mail address: 2 tunnels, 1000 requests per minute and 25 GiB a month.

Get your token Install localhostly

$ 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

There is one account and it is free: no paid plan and no card behind it. Its limits are the five numbers below. The traffic limit adds up both directions; the month turns on the 1st, in UTC. When a limit is reached, visitors get a 429 page naming the limit and saying when it ends.

One command, one public URL

localhostly 3000 opens one outgoing WebSocket connection from your computer to the localhostly server and keeps it; nothing is opened on your router or firewall. When a visitor opens your URL, the server reads the name in the address, sends the request down that connection, and the agent replays it on your local port and streams the answer back. HTTP and WebSocket both pass.

  1. Get a token. Enter your e-mail in the sign-up form. The token shows up on the sign-up page; no confirmation e-mail is sent.
  2. Save it. localhostly login <token> keeps it in ~/.localhostly/config.json, readable only by your user.
  3. Open the tunnel. localhostly 3000. The terminal prints the public URL and then one line per request: time, method, path, status and milliseconds.

Your app receives the visitor's method, path, headers and body, with X-Forwarded-For, X-Forwarded-Proto: https and X-Forwarded-Host. Add --host myapp.test:3000 to send it another address and Host. The name is 3 English words drawn at random, adjective, color and animal, and nobody chooses it.

The tunnel stays open as long as the agent answers pings

The tunnel stays open as long as the agent answers the server's pings: one every 30 seconds, and the connection is closed after 60 seconds without an answer. In a measured run, a tunnel idle for 620 seconds did not drop.

If the connection does drop, the agent reconnects on its own, waiting 1 second and doubling up to 60 seconds, and gets the same name back for 10 minutes after the drop; after a longer drop it comes back with a new name and prints name changed. To keep it up across reboots, install it as a system service, below.

Webhooks and API clients skip the warning page

A browser sees a warning page on its first visit, saying the site runs on someone's own computer; the button on it sets a cookie for 24 hours. A webhook call, a curl call or any API client is not a browser and gets no warning page: the request reaches your app directly, and any other client skips it with the X-Localhostly-Skip-Warning header.

Paste https://<name>.localhostly.iblabs.io/<your path> into the provider's webhook settings, and each call shows in your terminal with method, path, status and time.

Streaming responses and big uploads pass through

A request body travels in pieces of up to 64 KiB, in both directions, and is never held whole in memory. The measured run sent a 20 MiB upload with peak memory under 100 MiB and delivered a 20 MiB download to a slow visitor the same way.

Server-Sent Events reach the visitor as your app writes them: in a measured stream, events written at 0, 3 and 6 seconds arrived at 0.6, 3.6 and 6.6 seconds. Your app has 60 seconds to send the first byte; after that there is no time limit, so long downloads pass. A visitor's WebSocket reaches your app, and the upgrade completes only once your app accepts it, with the subprotocol it chose.

Lock the tunnel with a password or an IP list

With --password every visitor must enter a password in the browser's login box; without a value, localhostly generates one of 12 characters and shows it only in your terminal. Your app never sees the visitor's Authorization header.

With --allow 203.0.113.7,10.0.0.0/8 only those IP addresses or ranges get in, IPv4 or IPv6, up to 64 entries; any other address gets a 403 page that shows it, and its WebSocket upgrade gets 403 too. A tunnel with --allow shows no warning page, and with --password as well a visitor needs both.

Keep it running as a system service

localhostly service install 3000 installs the tunnel as a system service: systemd on Linux, launchd on macOS, a Windows service. It reconnects by itself, remembers its name and asks for it again after a reboot, and keeps trying if the server refuses it. localhostly service status reports whether it is running; localhostly service uninstall removes it.

Install

localhostly runs on Node.js 24 or newer.

Then 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, and there is no plan to pick: the token appears on the sign-up page, with no confirmation e-mail, and localhostly login <token> saves it on your computer.

Get your token