localtunnel exposes your localhost to the world for easy testing and sharing! No need to mess with DNS or deploy just to have others test out your changes.
Great for working with browser testing tools like browserling or external api callback services like twilio which require a public url for callbacks.
npx localtunnel --port 8000
ATTENTION: installation methods mentioned below refer to the official localtunnel client, not our updated version.
npm install -g localtunnel
yarn add localtunnel
brew install localtunnelWhen localtunnel is installed globally, just use the lt command to start the tunnel.
lt --port 8000
That's it! It will connect to the tunnel server, setup the tunnel, and tell you what url to use for your testing. This url will remain active for the duration of your session; so feel free to share it with others for happy fun time!
You can restart your local server all you want, lt is smart enough to detect this and reconnect once it is back.
Below are some common arguments. See lt --help for additional arguments
--subdomainrequest a named subdomain on the localtunnel server (default is random characters)--local-hostproxy to a hostname other than localhost--client-tokenauthenticate with a client token for persistent subdomain reservation (Protocol 0.0.9-epc)--hmac-secretauthenticate requests with HMAC-SHA256 (Protocol 0.0.10-epc, min 32 characters)
You may also specify arguments via env variables. e.g.
PORT=3000 lt
LocalTunnel client now supports two optional authentication methods (Protocol 0.0.10-epc):
Use a persistent token to identify your client and reserve your subdomain across different IP addresses.
lt --port 3000 --subdomain myapp --client-token my-secure-token-123Benefits:
- Reconnect with the same subdomain from different IP addresses
- Persistent client identification across network changes
- Priority over IP-based identification on supported servers
Requirements:
- Format: Alphanumeric characters, hyphens, and underscores only
[a-zA-Z0-9_-]+ - Maximum length: 256 characters
Cryptographically authenticate your tunnel creation requests using a shared secret.
lt --port 3000 --subdomain myapp --hmac-secret "my-very-secure-shared-secret-32-chars"Benefits:
- Cryptographic authentication of requests
- Protection against replay attacks using nonce
- Server-side validation of request authenticity
Requirements:
- Minimum length: 32 characters (enforced for security)
Use both methods together for maximum security:
lt --port 3000 --subdomain myapp \
--client-token my-token-123 \
--hmac-secret "my-very-secure-shared-secret-32-chars"Store your authentication credentials securely using environment variables:
export LT_CLIENT_TOKEN="my-secure-token-123"
export LT_HMAC_SECRET="my-very-secure-shared-secret-32-chars"
lt --port 3000 --subdomain myappUsing .env file:
# Copy the example file
cp .env.example .env
# Edit .env with your settings
# Then run localtunnel (it will automatically load .env variables)
lt
# Or run the dotenv example script
node examples/dotenv-usage.jsSee .env.example for a complete configuration template with all available options, and examples/dotenv-usage.js for a working example.
Note: Both authentication methods are optional and backward compatible. Clients without authentication will continue to work using IP-based identification.
All CLI options can be set via environment variables with LT_ prefix (e.g., LT_PORT, LT_CLIENT_TOKEN):
| Variable | Description | Default | Example |
|---|---|---|---|
LT_PORT |
Internal HTTP server port | - | LT_PORT=3000 |
LT_HOST |
Upstream server providing forwarding | https://localtunnel.me |
LT_HOST=https://custom.server.com |
LT_SUBDOMAIN |
Request a specific subdomain | random | LT_SUBDOMAIN=myapp |
LT_LOCAL_HOST |
Tunnel traffic to this host instead of localhost | localhost |
LT_LOCAL_HOST=192.168.1.100 |
LT_LOCAL_HTTPS |
Tunnel traffic to a local HTTPS server | false |
LT_LOCAL_HTTPS=true |
LT_LOCAL_CERT |
Path to certificate PEM file for local HTTPS | - | LT_LOCAL_CERT=/path/to/cert.pem |
LT_LOCAL_KEY |
Path to certificate key file for local HTTPS | - | LT_LOCAL_KEY=/path/to/key.pem |
LT_LOCAL_CA |
Path to certificate authority file | - | LT_LOCAL_CA=/path/to/ca.pem |
LT_ALLOW_INVALID_CERT |
Disable certificate checks for local HTTPS | false |
LT_ALLOW_INVALID_CERT=true |
LT_CLIENT_TOKEN |
Client token for authentication (Protocol 0.0.9-epc) | - | LT_CLIENT_TOKEN=my-token-123 |
LT_HMAC_SECRET |
HMAC secret for request authentication (Protocol 0.0.10-epc, min 32 chars) | - | LT_HMAC_SECRET=my-secret |
LT_OPEN |
Opens the tunnel URL in your browser | false |
LT_OPEN=true |
LT_PRINT_REQUESTS |
Print basic request info | false |
LT_PRINT_REQUESTS=true |
| Variable | Description | Default | Example |
|---|---|---|---|
DEBUG |
Enable debug output | - | DEBUG=localtunnel:* |
Note: To connect to servers using HTTPS with self-signed certificates or certificates from unrecognized CAs, you need to set the Node.js environment variable
NODE_TLS_REJECT_UNAUTHORIZED='0'.Warning: This disables TLS certificate validation and should only be used in development/testing environments. Never use this in production as it makes your connection vulnerable to man-in-the-middle attacks.
Example:
NODE_TLS_REJECT_UNAUTHORIZED='0' lt --host https://my-server. --port 3000Example with multiple variables:
LT_PORT=3000 LT_SUBDOMAIN=myapp LT_CLIENT_TOKEN=my-token DEBUG=localtunnel:* ltThe localtunnel client is also usable through an API (for test integration, automation, etc)
Creates a new localtunnel to the specified local port. Will return a Promise that resolves once you have been assigned a public localtunnel url. options can be used to request a specific subdomain. A callback function can be passed, in which case it won't return a Promise. This exists for backwards compatibility with the old Node-style callback API. You may also pass a single options object with port as a property.
const localtunnel = require("localtunnel");
(async () => {
const tunnel = await localtunnel({ port: 3000 });
// the assigned public url for your tunnel
// i.e. https://abcdefgjhij.localtunnel.me
tunnel.url;
tunnel.on("close", () => {
// tunnels are closed
});
})();port(number) [required] The local port number to expose through localtunnel.subdomain(string) Request a specific subdomain on the proxy server. Note You may not actually receive this name depending on availability.host(string) URL for the upstream proxy server. Defaults tohttps://localtunnel.me.local_host(string) Proxy to this hostname instead oflocalhost. This will also cause theHostheader to be re-written to this value in proxied requests.local_https(boolean) Enable tunneling to local HTTPS server.local_cert(string) Path to certificate PEM file for local HTTPS server.local_key(string) Path to certificate key file for local HTTPS server.local_ca(string) Path to certificate authority file for self-signed certificates.allow_invalid_cert(boolean) Disable certificate checks for your local HTTPS server (ignore cert/key/ca options).clientToken(string) [NEW] Client token for authentication and subdomain reservation (Protocol 0.0.9-epc). Format: alphanumeric, hyphens, and underscores only. Max 256 characters.hmacSecret(string) [NEW] HMAC shared secret for request authentication (Protocol 0.0.10-epc). Minimum 32 characters required.
Refer to tls.createSecureContext for details on the certificate options.
const localtunnel = require("localtunnel");
(async () => {
const tunnel = await localtunnel({
port: 3000,
subdomain: 'myapp',
clientToken: 'my-secure-token-123',
hmacSecret: 'my-very-secure-shared-secret-32-chars'
});
console.log('Tunnel URL:', tunnel.url);
tunnel.on("close", () => {
console.log('Tunnel closed');
});
})();The tunnel instance returned to your callback emits the following events
| event | args | description |
|---|---|---|
| request | info | fires when a request is processed by the tunnel, contains method and path fields |
| error | err | fires when an error happens on the tunnel |
| close | fires when the tunnel has closed |
The tunnel instance has the following methods
| method | args | description |
|---|---|---|
| close | close the tunnel |
This fork includes code/library updates, test refactoring, protocol compliance improvements, enhanced error handling, and authentication features (Protocol 0.0.10-epc):
Added two optional authentication methods for enhanced security and persistent client identification:
- Persistent client identification using tokens
- Reconnect with same subdomain from different IP addresses
- Token validation (alphanumeric, hyphens, underscores, max 256 chars)
- Header:
X-LT-Client-Token
- Cryptographic request authentication
- HMAC-SHA256 signature calculation
- Protection against replay attacks using timestamp and nonce
- Headers:
Authorization,X-Timestamp,X-Nonce - Minimum 32-character secret enforced
Both features are optional and backward compatible. See the Authentication section for usage examples, or the PROTOCOL_UPGRADE.md guide for complete details.
Original behavior:
- All errors triggered infinite retry attempts
Current behavior:
- 4xx errors (Client Errors): No retry, returns error immediately
- Examples: 403 Forbidden (invalid subdomain), 409 Conflict (reserved subdomain)
- 5xx errors (Server Errors): Retry up to 3 times with 1s interval
- After 3 failed retries, returns error with count
- Network errors: Infinite retry (maintains original behavior)
- Examples: ECONNREFUSED, ETIMEDOUT
This prevents unnecessary retry loops for client mistakes while maintaining resilience for temporary server issues.
Includes client.spec.reference.js - a comprehensive test specification (v1.0.0, protocol 0.0.8-epc) that defines expected client behavior for:
- Tunnel creation and management
- TCP connection handling
- HTTP request forwarding
- Error scenarios and retry logic
This specification can be used by alternative client implementations to ensure compatibility.
- PROTOCOL_UPGRADE.md - Protocol 0.0.10-epc upgrade guide and authentication features
- .env.example - Environment variables configuration template
- TESTING.md - Testing guide and protocol specifications
- CHANGELOG.md - Version history and changes
- examples/authentication-example.js - Authentication usage examples
- examples/dotenv-usage.js - Using .env file for configuration
Clients in other languages
go gotunnelme
C#/.NET localtunnel-client
Rust rlt
See localtunnel/server for details on the original server that powers localtunnel.
See ericchaves/localtunnel-server for details on our updated localtunnel server.
MIT