⚠️ Deno Deploy Sandbox API is currently in private alpha. Interested in trying it out? Email deploy@deno.com.
A TypeScript/JavaScript SDK for creating and interacting with secure, isolated sandbox environments. Create isolated sandboxes to securely run shell scripts, spawn processes, execute JavaScript applications and REPLs, and interact with files remotely.
- Create secure, isolated, and ephemeral Linux microVM sandboxes to execute arbitrary code and subprocesses.
- Run arbitrary shell commands and scripts within the sandbox.
- Run JavaScript applications and REPLs in the sandbox.
- Install NPM and JSR packages in the sandbox.
- Execute web framework dev servers like Vite or
next dev
. - Simply execute snippets of JS code, one after the other, maintaining state between snippets (great for progressively generated code from AI agents!)
- Expose any HTTP endpoints in the sandbox to the public internet via random and secure HTTPS URLs.
# Using Deno
deno add jsr:@deno/sandbox
# Using npm
npm install @deno/sandbox
# Using pnpm
pnpm install jsr:@deno/sandbox
# Using yarn
yarn add jsr:@deno/sandbox
-
Go to the "Sandbox" tab in the Deno Deploy EA dashboard. At the moment you will only be able to see this if you are invited to the private alpha - email deploy@deno.com to get access.
-
Create an access token and set it as the
DENO_DEPLOY_TOKEN
environment variable. -
Use the
@deno/sandbox
SDK to create a new sandbox and interact with it.
import { Sandbox } from "@deno/sandbox";
// Create a new sandbox
await using sandbox = await Sandbox.create();
// Write a TypeScript file
await sandbox.writeTextFile("hello.ts", "console.log('Hello, Sandbox!');");
// Run it
const child = await sandbox.spawn("deno", {
args: ["run", "hello.ts"],
stdout: "piped",
});
// Read the output
for await (const chunk of child.stdout) {
console.log(new TextDecoder().decode(chunk));
}
// Automatically shuts down the sandbox here
View the full API documentation here.
The snippets below assume package.json
contains { "type": "module" }
, the @deno/sandbox
package is installed, and that DENO_DEPLOY_TOKEN
env var is set.
import { Sandbox } from "@deno/sandbox";
await using sandbox = await Sandbox.create();
const result = await sandbox.eval(`
const a = 1;
const b = 2;
a + b;
`);
console.log("result:", result);
import { Sandbox } from "@deno/sandbox";
await using sandbox = await Sandbox.create();
const child = await sandbox.sh("echo $((21+21))", { stdout: "piped" });
const { status, stdoutText } = await child.output();
if (status.success) {
console.log("result:", stdoutText); // → "42"
}
Tip: prefer child.output()
for small outputs. For long‑running processes or large output, stream
the stdout/stderr by using child.spawn()
.
This creates a minimal Express app inside the sandbox, runs it on port 3000, and exposes it publicly
using sandbox.exposeHttp()
.
import { Sandbox } from "@deno/sandbox";
await using sandbox = await Sandbox.create();
// 1) Write package.json and server.js in the sandbox
await sandbox.writeTextFile(
"package.json",
JSON.stringify(
{
name: "sandbox-express-demo",
private: true,
type: "module",
dependencies: { express: "^4.19.2" },
},
null,
2,
),
);
await sandbox.writeTextFile(
"server.js",
`import express from 'express';
const app = express();
app.get('/', (req, res) => res.send('Hello from Express in @deno/sandbox!'));
app.get('/time', (req, res) => res.json({ now: new Date().toISOString() }));
app.listen(3000, () => console.log('listening on :3000'));
`,
);
console.log("Installing deps...");
const npm = await sandbox.sh("deno install", {
stdout: "piped",
stderr: "piped",
});
const npmOut = await npm.output();
if (!npmOut.status.success) {
throw new Error(npmOut.stderrText);
}
console.log("Starting server...");
const server = await sandbox.createJsRuntime({
entrypoint: "server.js",
});
// 4) Publish to the internet
const publicUrl = await sandbox.exposeHttp({ port: 3000 });
console.log("Public URL:", publicUrl); // e.g. https://<random>.sandbox.deno.net
// Fetch from your local machine to verify
const resp = await fetch(`${publicUrl}/time`);
console.log(await resp.json());
// Keep the process alive as long as you need; when done, closing the sandbox
// will tear it down.
import { Sandbox } from "@deno/sandbox";
await using sandbox = await Sandbox.create();
// Get SSH credentials
const { hostname, username } = await sandbox.exposeSsh();
console.log(`ssh ${username}@${hostname}`);
import { Sandbox } from "@deno/sandbox";
await using sandbox = await Sandbox.create();
// Start a JavaScript REPL
const repl = await sandbox.repl();
// Execute code interactively, maintaining state
await repl.eval("const x = 42;");
await repl.eval("const y = 8;");
const result = await repl.eval("x + y");
console.log("result:", result); // 50
import { Sandbox } from "@deno/sandbox";
await using sandbox = await Sandbox.create();
// Set environment variables
await sandbox.env.set("API_KEY", "secret-key-123");
await sandbox.env.set("NODE_ENV", "production");
// Use them in a script
const child = await sandbox.sh("echo $API_KEY", { stdout: "piped" });
const { stdoutText } = await child.output();
console.log("API_KEY:", stdoutText.trim());
child.stdout
is a Web ReadableStream
. In Node, convert a Node fs.WriteStream
to a Web
WritableStream
to pipe efficiently.
import { Sandbox } from "@deno/sandbox";
import fs from "node:fs";
import { Writable } from "node:stream";
await using sandbox = await Sandbox.create();
// Create a large file in the sandbox
await sandbox.writeTextFile("big.txt", "#".repeat(5_000_000));
// Stream it out to a local file
const child = await sandbox.spawn("cat", {
args: ["big.txt"],
stdout: "piped",
});
const file = fs.createWriteStream("./big-local-copy.txt");
await child.stdout.pipeTo(Writable.toWeb(file));
const status = await child.status;
console.log("done:", status);
The examples use Explicit Resource Management (await using
), added in Node.js 24.
For Node.js 22/23 or earlier, use try
/finally
:
const sandbox = await Sandbox.create();
try {
// ... use sandbox ...
} finally {
await sandbox.close();
}
Go to the console at https://app.deno.com and navigate to the Settings
page where you can find
Organization Tokens
section. Create a new token by clicking the Create a new token
button.
At the moment you will only be able to see this if you are invited to the private alpha - email deploy@deno.com to get access.
Sandboxes are ephemeral and live until the Sandbox
object returned from Sandbox.create()
is
destroyed.
Need longer lived sandboxes? Contact deploy@deno.com.
When creating a new sandbox, the SDK communicates with the Deno Deploy API to provision a secure, isolated Linux microVM. The SDK then establishes a secure connection to the sandbox, allowing you to interact with it programmatically.
When you're done with the sandbox, you can simply destroy the Sandbox
object. Doing this will
automatically shut down the sandbox and free up any resources it was using.
You can specify the region where the sandbox will be created when creating a new sandbox:
import { Sandbox } from "@deno/sandbox";
await using sandbox = await Sandbox.create({ region: "us-east-2" });
If not specified, the sandbox will be created in the default region.
Sandboxes have the following limits:
- CPU: 1 vCPU
- Memory: 512 MB
- Disk: 10 GB
Exceeding these limits may result in throttling or termination of your sandbox.