Create a tunnel
The CLI (fastest path)
Section titled “The CLI (fastest path)”The CLI is the main way to run a tunnel. It creates the local↔public forwarding session and prints your URL.
npx @maxoperf/tunnel http 3000✔ guest tunnel online https://swift-otter-7f3.maxoperf-tunnel.com → http://127.0.0.1:3000↑ sign up for a named subdomain, more tunnels, access controls & capture: https://maxoperf.com/signup12:00:01 GET /api/users 200 12ms 1.2kBNo token, no account. The CLI saves a durable guest identity to ~/.maxoperf/tunnel.json (file mode 0600), so re-running the command reuses the same URL.
Create the tunnel first (console, API, or MCP, as described below), then run the CLI with its one-time client token:
npx @maxoperf/tunnel http 3000 --token mptt_example_token --name myapp✔ tunnel online https://myapp.maxoperf-tunnel.com → http://127.0.0.1:3000Account tunnels connect directly with zero interstitial warnings. Traffic reaches your destination port right away.
CLI options
Section titled “CLI options”| Flag / env | Purpose |
|---|---|
--token <mptt_…> / MAXOPERF_TUNNEL_TOKEN | Tunnel client token. Omit for a guest tunnel. |
--name <name> | Preferred subdomain label (informational only; the server sets the URL at create time). |
--server <host:port> / MAXOPERF_TUNNEL_SERVER | Gateway address (default app.maxoperf.com:443, TLS auto-detected). |
--api-url <url> / MAXOPERF_API_URL | Platform API origin, used for guest tunnels (default https://app.maxoperf.com). |
--local-host <host> | Local host to forward to (default 127.0.0.1). |
Credential resolution order: --token → MAXOPERF_TUNNEL_TOKEN → the saved config-file account token → the saved config-file guest token → mint a brand-new guest. Ctrl-C closes the session cleanly, so the tunnel goes offline at once instead of lingering as a zombie session. The CLI never prints or logs your token.
Create an account tunnel from the console
Section titled “Create an account tunnel from the console”- Open Tunnels in the left navigation and click Create tunnel.
- Enter a name: the DNS label that becomes
<name>.maxoperf-tunnel.com(lowercase letters, digits, hyphens; must be globally unique). - Optionally configure access controls (below), then save. MaxoPerf creates the tunnel offline. It goes live as soon as a client (the CLI, or your own gRPC client) connects with its token.
- Reveal the tunnel’s connection token from the tunnel detail page and run the CLI (or your client) with it.
Create it from the REST API
Section titled “Create it from the REST API”curl -X POST https://app.maxoperf.com/v1/tunnels \ -H "Authorization: Bearer mpak_example_key" \ -H "X-Account-Id: acn-1234567890" \ -H "Content-Type: application/json" \ -d '{ "name": "myapp", "authMode": "basic", "basicAuth": { "username": "demo", "password": "s3cret" }, "allowIps": ["203.0.113.0/24"], "rateLimitRpm": 600, "maxBodyBytes": 10485760, "idleTimeoutSeconds": 3600, "captureMode": "headers" }'The 201 response returns the tunnel’s URL and a one-time clientToken (mptt_…). MaxoPerf never shows it again, so copy it now. Other routes: GET /v1/tunnels, GET /v1/tunnels/:id, PATCH /v1/tunnels/:id (any config field except name), POST /v1/tunnels/:id/stop, POST /v1/tunnels/:id/start, DELETE /v1/tunnels/:id (stopped only), POST /v1/tunnels/:id/rotate-token.
Access controls
Section titled “Access controls”Configure these at create time or later via PATCH, from the tunnel’s Settings tab in the console:
| Control | What it does |
|---|---|
Auth mode: none / basic / bearer | Require HTTP basic auth or a bearer token before a request reaches your local server. |
| Allow / deny IPs | CIDR lists. An IP not in allowIps (when set) is blocked; an IP in denyIps is always blocked. |
Rate limit (rateLimitRpm) | Requests per minute before the tunnel starts responding 429. |
Max body size (maxBodyBytes) | Caps request/response body size the tunnel will proxy. |
Idle timeout (idleTimeoutSeconds) | How long the tunnel can sit with no traffic before it auto-stops. Default 3600s (1 hour). |
Expiry (expiresAt) | Optional absolute ISO-8601 timestamp after which the tunnel stops permanently. |
Reconnect and idle-shutdown behavior
Section titled “Reconnect and idle-shutdown behavior”- Idle or TTL auto-stop reactivates on reconnect. If a tunnel stopped itself because it went idle or hit its expiry, a client that reconnects with a valid token brings it straight back online on the same URL. You need no separate “start” step. This is why the guest URL stays the same across restarts.
- A manual or plan-driven stop does not. If you (or MaxoPerf, for a plan-limit reason) stopped a tunnel on purpose, it stays stopped even if a client keeps retrying. Call
POST /v1/tunnels/:id/start(or use the console) to bring it back. The rule exists so that a client’s automatic reconnect can’t quietly get around a deliberate stop or a plan cap. - Dropped network ≠ stopped tunnel. If your local network drops briefly, the CLI reconnects with backoff, and the tunnel’s public URL works again once it’s back. This doesn’t count as a “stop”.
Statistics and request capture
Section titled “Statistics and request capture”Every account tunnel’s Overview tab shows a live traffic timeline: request counts, 4xx/5xx error rates, blocked-request counts, bytes in/out, and p50/p95/p99 latency. The Requests tab lists individual request events (when captureMode is headers or body), and you can replay a captured request from the console.
captureMode | What’s recorded |
|---|---|
none (guest default) | Only aggregate stats, no per-request detail. |
headers | Per-request metadata + headers, but not the body. |
body | Full per-request capture including body (subject to the maxBodyBytes cap). |
Anti-phishing interstitial & bypass rules
Section titled “Anti-phishing interstitial & bypass rules”MaxoPerf shows an anti-phishing interstitial screen on unverified guest tunnels. It prevents abuse and keeps automated malicious activity off public tunnel hostnames:
| Tunnel tier | Browser requests (Accept: text/html) | API / CLI / Webhook requests |
|---|---|---|
Guest tunnel (tgs_...) | Displays warning interstitial with a Proceed to Developer Tunnel button | Transparent pass-through with non-browser User-Agent or skip header |
Account tunnel (acn_...) | Zero interstitial (direct pass-through) | Direct pass-through |
Automated bypass options
Section titled “Automated bypass options”If you are calling a guest tunnel from test automation, curl, or webhook callbacks:
- Skip header: Send
X-MaxoPerf-Skip-Browser-Warning: 1(orngrok-skip-browser-warning: 1for drop-in compatibility) in your HTTP request headers. - User-Agent: Standard non-browser
User-Agentstrings (such ascurl/*, Postman, test runners, and webhook services) bypass the warning automatically. - Interactive browser cookie: Clicking the Proceed button sets a session cookie
__mptt_skip_warning=1, so later requests in that browser session load directly. - Zero-interstitial account tunnels: Create or claim the tunnel into an authenticated MaxoPerf account to remove the interstitial for all visitors.
Claim a guest tunnel
Section titled “Claim a guest tunnel”If you signed up after starting in guest mode, attach your running guest tunnel to your account without losing its URL:
curl -X POST https://app.maxoperf.com/v1/tunnels/<id>/claim \ -H "Authorization: Bearer mpak_example_key" \ -H "X-Account-Id: acn-1234567890" \ -H "Content-Type: application/json" \ -d '{ "guestToken": "mptt_g_example_guest_token" }'The tunnel keeps its URL and moves from the guest cap to your plan’s tunnel limit. Account-tunnel configuration (access controls, capture, idle-timeout tuning) is available right away.
Next steps
Section titled “Next steps”- Tunnels overview: guest vs. account tunnels, what every tunnel gets.
- Virtual services: expose a mocked dependency the same way a tunnel exposes a local port.