Sandbox services now get public preview URLs with tunnels!
Hey everyone, it's me, Shii-chan! Today we're talking about sharing a service running inside a container on a public URL in just a couple of lines. Super handy when you want to show a work-in-progress preview to someone!
Cloudflare ChangelogWhat was announced?
Cloudflare's Changelog announced that Sandboxes now include a new sandbox.tunnels namespace. You can take a service running inside a Sandbox container and expose it on a public preview URL.
Under the hood it runs cloudflared inside the sandbox, so you don't need to configure exposePort() or bring a custom domain. It lands as part of the Agents updates.
The story so far
Until now, exposing a service inside a container to the outside world meant setting up exposePort() or bringing your own custom domain — a bit of a chore.
What changes
By default, calling sandbox.tunnels.get(port) creates a quick tunnel on a zero-config *.trycloudflare.com URL. No Cloudflare account, DNS record, or custom domain required. It's perfect for quick development and .workers.dev deployments.
import { getSandbox } from "@cloudflare/sandbox";
const sandbox = getSandbox(env.Sandbox, "my-sandbox");
await sandbox.startProcess("python -m http.server 8080");
const tunnel = await sandbox.tunnels.get(8080);
console.log(tunnel.url); // → https://random-words-here.trycloudflare.com
Dive Deep
When you want more control, you can create a named tunnel with sandbox.tunnels.get(port, { name }). Passing a name binds a hostname ({name}.{your-zone}) to a Cloudflare Tunnel plus a CNAME record on your zone, giving you a URL like https://my-app-preview.example.com.
const tunnel = await sandbox.tunnels.get(8080, { name: "my-app-preview" });
console.log(tunnel.url); // → https://my-app-preview.example.com
Quick tunnels generate a new random URL each time, but a named tunnel produces a persistent URL that survives container restarts. That makes named tunnels a good fit for production, where you want control over the tunnel and its origin.
And when you call sandbox.destroy(), it tears down the Cloudflare Tunnel and the DNS record alongside the container, so you don't leave dangling tunnels or records behind. It even handles the cleanup for you!
You can update with npm i @cloudflare/sandbox@latest. For full API details, check the Sandbox tunnels reference.
Wrap-up
sandbox.tunnels.get(port)gives you a zero-config quick tunnel on*.trycloudflare.com- Pass
{ name }for a persistent named tunnel whose URL survives restarts sandbox.destroy()cleans up the tunnel and DNS record for you- Update with
npm i @cloudflare/sandbox@latest
This one's for developers who want to quickly share whatever they're running inside a Sandbox!