LocalTunnel Not Working? Alternatives
Full troubleshooting: For 503s, session limits, and tool-agnostic fixes, start with Tunnel Not Working?. This page focuses on localtunnel-specific issues and alternatives.
Why localtunnel breaks
localtunnel is a popular npm package that exposes localhost through a shared public server (localtunnel.me). It works well for quick one-off shares, but developers frequently hit reliability issues — especially under load or during long sessions.
These problems are not unique bugs in your setup. Free shared tunnel infrastructure trades reliability for zero configuration.
Common localtunnel problems
| Symptom | Typical cause |
|---|---|
| 503 Tunnel Unavailable | Shared public server overloaded or tunnel expired |
| Connection refused | Local app not running on expected port |
| Slow or flaky connections | Shared infrastructure with variable load |
| Subdomain already taken | Custom subdomain collision on shared server |
| Tunnel disconnects silently | Network instability; no reconnect grace documented |
| WebSocket failures | localtunnel is HTTP-focused; WebSocket support is unreliable (issue #297) |
Community reports of 503 errors are common in the localtunnel GitHub issues. The maintainers note there are no documented bandwidth caps, but reliability varies with shared server load.
Quick fix checklist
Before switching tools, verify your local setup:
1. Confirm your app is running:
curl http://localhost:5173
2. Specify the correct port explicitly:
npx localtunnel --port 5173
3. Check firewall and VPN — outbound connections to the tunnel server must be allowed.
4. Try a fresh tunnel — subdomains can get stuck on the shared server. Omit --subdomain to get a random one.
5. Retry after a few minutes — 503 errors often resolve when server load drops.
If problems persist across multiple attempts on different days, consider an alternative.
LocalToLink as an alternative
LocalToLink runs via npm with no global install — similar workflow to localtunnel, but on dedicated infrastructure with enforced policy limits:
npx localtolink --port 5173
| Feature | LocalToLink (free tier) |
|---|---|
| Install | npx localtolink (Node ≥ 22.14) |
| Account | No signup required |
| HTTPS | Automatic |
| WebSocket | Supported |
| Auto port detection | Yes (omit --port if one app runs) |
| Terminal QR code | Yes (--no-qr to hide) |
| Reconnect grace | Same URL for 10 minutes after disconnect |
| Subdomain | Random 10-char (custom subdomains not on free tier yet) |
| Session limit | 2 hours, 1 GB, 10 req/s |
| Request inspector | No (unlike ngrok) |
Side-by-side workflow
# localtunnel
npx localtunnel --port 5173
# Optional: npx localtunnel --port 5173 --subdomain myapp
# LocalToLink
npx localtolink --port 5173
# Auto-detects port if omitted; prints QR code
Both require Node.js. Neither requires a global install.
When localtunnel is still fine
localtunnel remains a reasonable choice when:
- You need a one-off quick share with no reliability requirements
- You want a specific custom subdomain on the free tier (
--subdomain myapp) and accept collision risk - You already have it working and the session is short
- You do not need WebSocket support (HMR, real-time apps)
When to consider other tools
| Need | Consider |
|---|---|
| Request inspection / replay | ngrok (requires account on free tier) |
| Production-grade ingress | Cloudflare Tunnel |
| WebSocket / Vite HMR | LocalToLink or Cloudflare Tunnel |
| Zero npm (no Node) | ngrok binary or cloudflared — still requires installing a tool |
| Custom subdomain (free) | localtunnel --subdomain (LocalToLink custom subdomains not on free tier yet) |
| Anonymous tunnel, no account | LocalToLink |
Migration from localtunnel to LocalToLink
Switching takes about 30 seconds:
- Stop your localtunnel process (Ctrl+C)
- Run
npx localtolink --port YOUR_PORT - Copy the new public URL
- Update webhook URLs, OAuth redirect URIs, or share links with the new subdomain
Your local app code does not change — only the external URL.
Troubleshooting LocalToLink (if you switch)
| Problem | Fix |
|---|---|
| Tunnel limit message | Only one tunnel per IP on free tier — stop other tunnels |
| Wrong app loads | Use --port explicitly |
| Browser warning page | Visitor interstitial when enabled — Continue once per subdomain |
| Session expired after 2 hours | Restart tunnel; update external URLs |
FAQ
Is localtunnel abandoned?
The project is maintained but relies on shared public infrastructure. Reliability depends on server load, not your code.
Does LocalToLink cost money?
Anonymous tunnels on the free tier require no payment. Paid plans are not available yet.
Can I run both tools simultaneously?
Only one LocalToLink tunnel per IP. You can run localtunnel and LocalToLink on different ports if needed, but one tunnel per IP for LocalToLink.
For tool-agnostic fixes (session limits, port mismatches, Docker), see Tunnel Not Working?. For a one-command alternative, see Expose Localhost in One Command.
When localtunnel is still the right choice
localtunnel remains useful when you want a custom subdomain on the free tier (--subdomain) and your test is a short HTTP demo without WebSockets. If you hit repeated 503 errors or need reliable HMR, switch to an npm-based tunnel with reconnect grace and documented WebSocket support rather than retrying the same shared endpoint.
Try it now
Start a tunnel from your project directory — no account required.
$ npx --yes localtolink@latest