Isorun Docs
Sandboxes

Public URLs

Expose any port your in-sandbox code is listening on as a public HTTPS URL. Anonymous and WebSocket-aware.

sandbox.url(port) returns a public HTTPS URL that proxies to whatever your sandbox is listening on at that port. Start a vite dev server, a jupyter notebook, a gradio app, or any HTTP server inside the sandbox, and reach it from a browser anywhere on the internet.

Preview a dev server

TypeScript
import { Isorun } from 'isorun'

const isorun = new Isorun()
const sandbox = await isorun.create({ image: 'node:22-slim' })

await sandbox.exec('git clone https://github.com/me/my-app && cd my-app && npm install')

// Start vite in the background. nohup + setsid + redirect so the exec
// call returns immediately and the server keeps running.
await sandbox.exec('cd my-app && nohup setsid npm run dev >/dev/null 2>&1 &')

// Get a public URL anyone can open in a browser.
const url = sandbox.url(5173)
console.log(url)
// → https://5173-run<id>.isorun.app/

// Hand it to the user. Vite HMR over WebSocket works automatically.
notifyUser(url)

URL format

The URL encodes the port and the sandbox ID in the host:

https://<port>-<runID>.isorun.app/<path>?<query>
ComponentMeaning
<port>TCP port your in-sandbox server is listening on
<runID>Sandbox ID returned by sandbox.id
<path>Forwarded verbatim to the in-sandbox server
<query>Forwarded verbatim

So https://8000-run0123456789abcdef.isorun.app/foo/bar?q=1 becomes a request to localhost:8000/foo/bar?q=1 inside the sandbox.

What passes through the proxy

  • All HTTP methods. GET, POST, PUT, DELETE, PATCH, anything.
  • Streaming responses. SSE, chunked encoding, etc. pass through without buffering.
  • WebSocket upgrades. Vite HMR, Jupyter kernel WS, hot-reload, notebook websockets, gradio's queue WS, langchain streaming, all work end-to-end.
  • Cookies. Forwarded both directions.
  • Large request and response bodies. No size cap from the proxy.

Authentication model

The URL is anonymous: anyone with the URL can hit it. The sandbox ID in the host is high-entropy, so it's effectively unguessable unless you share it.

The sandbox ID is the only credential on a public URL. Treat any URL you generate as a bearer secret: sharing it grants access to that port.

If you need stronger auth in front of your in-sandbox service, run it behind a reverse proxy with auth inside the sandbox itself, or ship a per-port allowlist via your own gateway.

What gets added to the forwarded request:

  • X-Forwarded-Host
  • X-Forwarded-Proto: https
  • X-Real-IP: <client IP>

Performance

Most of the round-trip is network distance between the client and the runner. For traffic that needs the lowest latency, hold a persistent connection to the URL: HTTP keep-alive, WebSocket, or streaming SSE.

Limits

ConstraintValue
Ports per sandboxany TCP port your code listens on
Method supportall HTTP methods including PATCH and CUSTOM
WebSocket supportyes, end-to-end
Authnone; the sandbox ID is the credential

Next steps

On this page