On this page
Expose HTTP
You can run dev servers, preview apps, webhook receivers, or framework CLIs on any port and publish them instantly to a secure, random HTTPS URL.
await sandbox.writeTextFile(
"server.js",
"Deno.serve(() => new Response('Hello from Sandboxes'));",
);
const runtime = await sandbox.createJsRuntime({ entrypoint: "server.js" });
const publicUrl = await sandbox.exposeHttp({ port: 8080 });
console.log(publicUrl); // https://<random>.sandbox.deno.net
The URL stays live for the sandbox lifetime, making it perfect for short-lived QA links or agent generated previews.
When to expose HTTP Jump to heading
Expose HTTP whenever you need to share the sandbox with teammates, bots, or external services:
- Preview links for AI-generated web apps or instant demos
- Webhook receivers that must be reachable from Stripe, GitHub, etc.
- Framework dev servers (
next dev,astro dev,deno task dev) that should be inspected from a browser - Temporary APIs, health checks, or observability probes
Because sandboxes are ephemeral, you do not need to manage DNS or certificates.
Each call to exposeHttp() returns a unique hostname under *.sandbox.deno.net
with TLS automatically configured.
All requests to a sandbox's URL will send HTTP traffic to the sandbox.
Step-by-step Jump to heading
- Start a server inside the sandbox. Listen on any unprivileged port (e.g.,
3000,8080). - Expose the port:
const url = await sandbox.exposeHttp({ port: 3000 }); - Share or fetch from the URL. Requests enter through Deploy’s global edge and are tunneled directly to your sandbox.
Multiple ports can be exposed simultaneously by calling exposeHttp() for each
port. You can also re-use the same exposed URL after restarting your server, as
long as the sandbox itself remains alive.
Observing traffic Jump to heading
Requests routed through the exposed URL show up alongside your Deploy logs and traces. Use the dashboard to:
- Filter logs by sandbox ID or time range
- Inspect request traces to track latency between the edge and your VM
- Cancel or restart the sandbox if a preview misbehaves
Security and networking Jump to heading
- Exposed URLs are long, random subdomains that are hard to guess.
- TLS termination happens at the Deploy edge; traffic is encrypted end-to-end.
Cleanup and limits Jump to heading
- An exposed URL stops accepting traffic when the sandbox lifetime ends. You can
call
sandbox.kill()to terminate the sandbox (and URL) ahead of schedule if needed. - For persistent services, graduate the code into a Deploy app rather than relying on a long-running sandbox.
Full example with a framework Jump to heading
import { Sandbox } from "@deno/sandbox";
await using sandbox = await Sandbox.create();
// Install dependencies
await sandbox.writeTextFile(
"package.json",
JSON.stringify(
{
private: true,
scripts: { dev: "next dev" },
dependencies: {
next: "^15.0.0",
react: "^19.0.0",
"react-dom": "^19.0.0",
},
},
null,
2,
),
);
await sandbox.sh`npm install`;
// Start the dev server
const server = await sandbox.spawn("npm", {
args: ["run", "dev"],
stdout: "inherit",
stderr: "inherit",
});
// Publish it
const previewUrl = await sandbox.exposeHttp({ port: 3000 });
console.log(`Preview ready at ${previewUrl}`);
await server.status; // keep running until the process exits
This pattern lets agents or developers spin up high-fidelity previews, share
them for feedback, and tear everything down with a single Ctrl+C.