Skip to content
Runtime

How to expose a port from a sandbox at an HTTPS URL

Start the server with spawn. Then call sbx.previews.create(port). The address needs a token, unless you pass visibility: "public".

On Runtime, a shared port is private by default. It lives on its own domain, runtimehost.com. A visit wakes a paused sandbox. So a preview can sit idle for days at paused-storage prices: $0.08 per decimal GB of saved state a month. Keeping a running machine instead costs $0.03125 an hour for 2 vCPU and 4 GiB (rates checked 25 October 2026, pricing). Runtime adds no badge or banner to the pages a preview serves.

Share a port and call it

TypeScriptimport { Sandbox } from "withruntime";await using sbx = await Sandbox.create();await sbx.spawn("python3 -m http.server 3000");const preview = await sbx.previews.create(3000);const page = await fetch(preview.url, {  headers: { "x-runtime-preview-token": preview.token! },});console.log(page.status); // 200
Pythonimport urllib.requestfrom withruntime import Sandboxwith Sandbox.create() as sbx:    sbx.spawn("python3 -m http.server 3000")    preview = sbx.previews.create(3000)    request = urllib.request.Request(preview["url"],                                     headers={"x-runtime-preview-token": preview["token"]})    print(urllib.request.urlopen(request).status)  # 200
Terminalruntime sandboxes preview "${id}" 3000            # private, with a tokenruntime sandboxes preview "${id}" 3000 --public   # anyone with the address (paid)runtime sandboxes previews "${id}"runtime sandboxes unshare "${id}" 3000

An agent on MCP uses runtime_sandboxes_previews with create, list, rotate and delete.

Who can open it

How you share it Who gets in Send
Private, from code A client that sends the token x-runtime-preview-token: <token>
Private, by link Whoever holds the link preview.urlWithToken
Public Anyone with the address preview.url

Public addresses are for paid sandboxes in an account that has bought credit. A sandbox without credit shares a port by link, with its token. While an account is blocked, or while every purchase it made is refunded in full, a public address needs the token too. It opens to anyone again once the account pays.

To show a private preview inside your own app, set an iframe's src to urlWithToken. The browser keeps the token for that frame on your site only. So the page's scripts, styles and live reload load without it.

To stop other sites from framing the preview, name your site when you share the port: previews.create(3000, { embedOrigins: ["https://app.example.com"] }). In Python, use embed_origins. You can list up to 16, and https://*.example.com covers subdomains. Each response then tells the browser to draw the preview only inside those sites. The link's token works in an iframe only there. With none named, any site may embed the preview.

Making a port public or private is written to the account's audit log. The entry records who did it and from where.

Manage the tokens

  • Revoke every token at the same time with previews.rotate(port). Every token issued before the call is refused. Use it when a link went somewhere it should not.
  • Stop sharing with previews.delete(port).
  • List what is shared with runtime sandboxes previews <id>.

A private preview's token expires. So a link sent today does not work forever (network access).

What the server must do

  • Run under spawn, not exec. Everything that exec starts ends when its command does. That includes nohup … &. spawn keeps the server running after your call returns.
  • Listen on 0.0.0.0 or localhost inside the sandbox.
  • WebSockets work, so dev servers keep their live reload.

A paused sandbox wakes on a visit

A visit to a shared port wakes a paused sandbox that has automatic wake turned on. An API client's request waits up to 30 seconds for the wake. A browser shows a short "Waking up" page that reloads itself. The wake is an ordinary wake, billed from the moment it runs. Pair a preview with idlePauseSeconds. That setting counts preview requests as use, so the sandbox runs only while people use it (pause and resume).

Preview, port-forward, SSH or a domain?

You need Use
A URL for a person or a webhook A preview
The port on your own machine, just for you runtime sandboxes port-forward <id> 3000
A shell or an editor in the sandbox runtime sandboxes ssh <id> (editors)
Your own hostname, paid accounts runtime domains add app.example.com <id> 3000
A raw TCP port, such as Postgres, paid accounts runtime ports open <id> 5432

Port forwarding and SSH go through Runtime's API with your key. So the sandbox opens nothing to the internet (networking).

Mistakes to avoid

  • Putting the token in a shared URL by hand. Send it as a header from code. Or hand out urlWithToken, which works in a browser, with fetch, curl and WebSocket clients.
  • Making a preview public to skip the token. A public address is open to anyone who finds it. Keep it private unless it is meant as a demo.
  • Serving from exec. The server ends when the command returns. Then nothing listens behind the preview.
  • Expecting previews_unavailable to clear. That 501 means previews are turned off there on purpose. Retrying will not help.
  • Treating the address as your site. Preview addresses sit under runtimehost.com, never under withruntime.com, so a sandbox's pages never share an origin with your account.

For a full product built on previews, see preview apps an AI agent builds; for browser automation against a preview, see Playwright.

Facts on this page were checked on 26 October 2026.

Related.

100 free hoursin your first 30 days.

of a 1 GB machine

  • No credit card
  • Four sandboxes at once, 2 vCPU and 4 GiB each
  • Then prepaid credit from $10, no plan fee
Start free, no card
Start free, no card