On Runtime, a preview is private from the moment you create it. One call
revokes every link you have handed out. The address stays the same, so a
bookmark keeps working for anyone you give the new token. Previews live under
runtimehost.com, never under withruntime.com, so what a sandbox serves never
shares an origin with your account.
Rotate the token
TypeScriptimport { Sandbox } from "withruntime";await using sbx = await Sandbox.create();await sbx.spawn("python3 -m http.server 3000");const first = await sbx.previews.create(3000);const fresh = await sbx.previews.rotate(3000); // first.token is refused from now onconst page = await fetch(fresh.url, { headers: { "x-runtime-preview-token": fresh.token! },});console.log(fresh.url === first.url, page.status);Pythonfrom withruntime import Sandboxwith Sandbox.create() as sbx: sbx.spawn("python3 -m http.server 3000") first = sbx.previews.create(3000) fresh = sbx.previews.rotate(3000) # first["token"] is refused from now on print(fresh["url"] == first["url"], fresh["token"] is not None)Over plain HTTPS, the same call is a POST to the preview's :rotate route
(API reference):
Terminalcurl -sS -X POST "https://api.withruntime.com/v1/sandboxes/${ID}/previews/3000:rotate" \ -H "Authorization: Bearer ${RUNTIME_API_KEY}"The response includes the new token and a new urlWithToken. The new URL
works as it is in a browser, with fetch, curl or a WebSocket client. In code, you can also send the token in the x-runtime-preview-token
header.
From a terminal, withruntime 0.7.0 and later rotate the token in one command
and print the new token:
Terminalruntime sandboxes preview rotate "${ID}" 3000When to rotate
- A link went somewhere it should not: a public chat, a ticket, a screenshot, a log.
- Someone who had access leaves the project. Rotation cuts off every holder immediately, whoever they forwarded the link to.
- A demo or review is over but the sandbox keeps running for you.
- On a schedule, for a preview that stays up for days, so no token stays useful for long.
Rotate, delete or leave public
| Call | What happens |
|---|---|
sbx.previews.create(3000) |
Shares the port, private: a request needs the token |
sbx.previews.rotate(3000) |
Refuses every token issued for the port so far and returns a new one; runtime sandboxes preview rotate <id> 3000 from CLI 0.7.0 |
sbx.previews.delete(3000) |
Stops sharing the port; runtime sandboxes unshare <id> 3000 from the CLI |
sbx.previews.create(3000, { visibility: "public" }) |
Paid sandboxes: anyone with the address can open it; no token to rotate |
runtime sandboxes previews <id> |
Lists the sandbox's shared ports |
Rotating keeps the port shared and the server running. Deleting stops the
sharing completely. Both take effect when the call returns. The next request
with an old token is refused, and Runtime closes any WebSocket opened with one.
Choose rotate when the right people still need the page. Choose delete when
nobody does. MCP agents create, list, rotate and delete previews with the
actions of the same names in the runtime_sandboxes_previews tool
(MCP).
Mistakes and how Runtime handles them
- Forwarding
urlWithToken. Anyone with the link gets in until the token expires or you rotate it. Rotating is how you take that access back. - Expecting a public preview to be protected. A public address needs no token, so rotating protects nothing. Keep previews that show private data private.
- The page stops answering after a rotation. Old tokens are refused by design. Share the new one. The server inside the sandbox is not changed.
- The server dies with its command. Start it with
spawn, notexec, and make it listen on0.0.0.0orlocalhostinside the sandbox (the sandbox environment). - A paused sandbox. A visit to a shared port wakes the sandbox. The browser shows a short "Waking up" page that reloads itself (wake on request).
Every response from a preview includes an X-Runtime-Report header. Anyone can
use it to report the preview, and Runtime can turn off a reported preview
(custom domains work the same way).
For your own hostname
A preview address belongs to Runtime. To serve the same port at a name you own, with HTTPS, add a custom domain. To reach the port only from your own machine, with no link at all, use port forwarding.
Related
- Share a port in the JavaScript guide.
- Network access: what can reach a sandbox.
- Preview agent-built apps.
Facts on this page were checked on 26 October 2026.