A modern, open-source alternative to localtunnel. Bundles client & server to host your own tunnel infrastructure.

npm install pipenet

Use Cases

Expose local services to the internet, or embed tunneling in your own tools.

Local Development

Share your local server with teammates, test webhooks, or demo work without deploying.

SDK Integration

Embed pipenet in your own tools to provide tunneling capabilities. mcp-proxy uses pipenet to connect local MCP servers with remote AI clients.

Self-Hosted Infrastructure

Run your own tunnel server for full control over security, domains, and availability.

Quick Start

One package. Two modes. Use the public server or deploy your own.

Client
# Expose local port
npx pipenet client --port 3000

# Custom subdomain
npx pipenet client --port 3000 \
  --subdomain myapp

# Your own server
npx pipenet client --port 3000 \
  --host https://tunnel.example.com
Server
# Start server
npx pipenet server --port 3000

# Custom domain
npx pipenet server --port 3000 \
  --domain tunnel.example.com

# Cloud-ready
npx pipenet server --port 3000 \
  --tunnel-port 3001

Comparison

Built for modern deployment environments.

Feature pipenet localtunnel
Cloud deployment single-port random ports
Multiple domains
TypeScript
ES Modules
Maintenance Active Limited
WebSocket

Supported Protocols

Tunnels any HTTP-based traffic to your local server.

Protocol Notes
HTTP / HTTPS Standard request/response
WebSocket Full duplex via HTTP upgrade
SSE Long-lived HTTP connections
HTTP Streaming Chunked transfer encoding

API

Programmatic usage for testing, automation, and integration.

import { pipenet } from 'pipenet';

const tunnel = await pipenet({ port: 3000 });

console.log(tunnel.url);  // https://abc123.pipenet.dev

tunnel.on('request', (info) => console.log(info.method, info.path));
tunnel.on('close', () => console.log('closed'));

Client Options

portnumber Local port to expose
hoststring Tunnel server URL
subdomainstring Request specific subdomain
localHoststring Proxy to this hostname instead of localhost
localHttpsboolean Tunnel to local HTTPS server
allowInvalidCertboolean Skip cert validation

Events

requestFired on each proxied request with method and path
errorFired when an error occurs
closeFired when tunnel closes

Server

Deploy your own tunnel infrastructure with lifecycle hooks.

import { createServer } from 'pipenet/server';

const server = createServer({
  domains: ['tunnel.example.com'],
  secure: true,
  tunnelPort: 3001,

  // Lifecycle hooks
  onTunnelCreated: (tunnel) => {
    console.log(`Tunnel created: ${tunnel.id} at ${tunnel.url}`);
  },
  onTunnelClosed: (tunnel) => {
    console.log(`Tunnel closed: ${tunnel.id}`);
  },
  onRequest: (req) => {
    console.log(`${req.method} ${req.path} via ${req.tunnelId}`);
  },
});

await server.tunnelServer.listen(3001);
server.listen(3000);

Server Options

domainsstring[] Custom domain(s) for tunnel server
secureboolean Require HTTPS
landingstring Redirect URL for root requests
maxTcpSocketsnumber Max sockets per client (default: 10)
tunnelPortnumber Shared port for cloud deployments

Lifecycle Hooks

onTunnelCreatedCalled when a new tunnel is created
onTunnelClosedCalled when a tunnel is closed
onRequestCalled on each proxied request

Endpoints

GET /api/statusServer status and tunnel count
GET /api/tunnels/:id/statusStatus of specific tunnel
GET /:idRequest new tunnel with ID