Skip to main content
Sandboxes are secure, isolated containers in Modal that boot in seconds. They provide a flexible execution environment for running arbitrary commands.

Access the Sandboxes API

import { ModalClient } from "modal";

const modal = new ModalClient();
const app = await modal.apps.fromName("my-app", { createIfMissing: true });
const image = modal.images.fromRegistry("python:3.13");

const sandbox = await modal.sandboxes.create(app, image);

Methods

Create a new Sandbox in the specified App with the given Image.
app
App
required
The App context for the Sandbox.
image
Image
required
The container image to use.
params
SandboxCreateParams
Configuration options
return
Promise<Sandbox>
The created Sandbox object.
const sandbox = await modal.sandboxes.create(app, image, {
  cpu: 2,
  memoryMiB: 4096,
  timeoutMs: 600000, // 10 minutes
  env: { ENVIRONMENT: "production" },
  command: ["python", "server.py"],
});
Get a running Sandbox by its ID.
sandboxId
string
required
The Sandbox ID.
return
Promise<Sandbox>
The Sandbox object.
const sandbox = await modal.sandboxes.fromId("sb-123456");
Get a running Sandbox by name from a deployed App.
appName
string
required
Name of the deployed App.
name
string
required
Name of the Sandbox.
params
SandboxFromNameParams
Optional parameters
return
Promise<Sandbox>
The Sandbox object.
const sandbox = await modal.sandboxes.fromName("my-app", "worker-1");
List all Sandboxes for the current environment or App.
params
SandboxListParams
Filter parameters
return
AsyncGenerator<Sandbox>
An async iterator of Sandbox objects.
for await (const sandbox of modal.sandboxes.list()) {
  console.log(sandbox.sandboxId);
}

// Filter by tags
for await (const sandbox of modal.sandboxes.list({ 
  tags: { env: "production" } 
})) {
  console.log(sandbox.sandboxId);
}

Sandbox object

Properties

sandboxId
string
Unique identifier for the Sandbox.
stdin
ModalWriteStream<string>
Stream for writing to the Sandbox’s standard input.
stdout
ModalReadStream<string>
Stream for reading the Sandbox’s standard output.
stderr
ModalReadStream<string>
Stream for reading the Sandbox’s standard error.

Methods

exec(command, params?)

Execute a command in the Sandbox and return a process handle.
command
string[]
required
Command and arguments to execute.
params
SandboxExecParams
Execution options
return
Promise<ContainerProcess>
A process object with stdin, stdout, stderr streams and a wait() method.
// Execute a simple command
const proc = await sandbox.exec(["python", "--version"]);
const output = await proc.stdout.readText();
console.log(output);
const exitCode = await proc.wait();

// Binary mode
const proc = await sandbox.exec(["cat", "image.png"], { mode: "binary" });
const imageData = await proc.stdout.readBytes();

terminate(params?)

Terminate the Sandbox.
params
SandboxTerminateParams
Termination options
return
Promise<void | number>
Returns void by default, or the exit code if wait is true.
// Terminate without waiting
await sandbox.terminate();

// Terminate and get exit code
const exitCode = await sandbox.terminate({ wait: true });
console.log(`Exited with code: ${exitCode}`);

wait()

Wait for the Sandbox to finish and return the exit code.
return
Promise<number>
The exit code.
const exitCode = await sandbox.wait();

poll()

Check if the Sandbox has finished without blocking.
return
Promise<number | null>
The exit code if finished, or null if still running.
const exitCode = await sandbox.poll();
if (exitCode !== null) {
  console.log(`Finished with code: ${exitCode}`);
} else {
  console.log("Still running");
}

tunnels(timeoutMs?)

Get tunnel metadata for ports exposed by the Sandbox.
timeoutMs
number
default:"50000"
Timeout in milliseconds.
return
Promise<Record<number, Tunnel>>
A mapping of container ports to Tunnel objects.
const sandbox = await modal.sandboxes.create(app, image, {
  encryptedPorts: [8000],
});

const tunnels = await sandbox.tunnels();
const tunnel = tunnels[8000];
console.log(`Service available at: ${tunnel.url}`);

open(path, mode?)

Open a file in the Sandbox filesystem.
path
string
required
Path to the file.
mode
SandboxFileMode
default:"'r'"
File mode: "r", "w", "a", "r+", "w+", or "a+".
return
Promise<SandboxFile>
A file handle with read(), write(), and close() methods.
const file = await sandbox.open("/data/output.txt", "w");
await file.write("Hello, world!");
await file.close();

const file = await sandbox.open("/data/output.txt", "r");
const content = await file.read();
await file.close();

snapshotFilesystem(timeoutMs?)

Snapshot the entire filesystem and return an Image.
timeoutMs
number
default:"55000"
Timeout in milliseconds.
return
Promise<Image>
An Image containing the filesystem snapshot.
const snapshot = await sandbox.snapshotFilesystem();
console.log(`Snapshot image ID: ${snapshot.imageId}`);

// Use the snapshot to create a new sandbox
const newSandbox = await modal.sandboxes.create(app, snapshot);

mountImage(path, image?)

Mount an Image at a path in the Sandbox filesystem.
path
string
required
Mount path.
image
Image
Image to mount. If undefined, mounts an empty directory.
const dataImage = await modal.images.fromId("im-123456");
await sandbox.mountImage("/mnt/data", dataImage);

snapshotDirectory(path)

Snapshot a directory and return an Image.
path
string
required
Directory path to snapshot.
return
Promise<Image>
An Image containing the directory contents.
const dirSnapshot = await sandbox.snapshotDirectory("/workspace/output");

setTags(tags)

Set tags (key-value pairs) on the Sandbox.
tags
Record<string, string>
required
Tags to set.
await sandbox.setTags({ 
  env: "production",
  version: "1.0",
});

getTags()

Get tags currently attached to the Sandbox.
return
Promise<Record<string, string>>
The Sandbox’s tags.
const tags = await sandbox.getTags();
console.log(tags); // { env: "production", version: "1.0" }

detach()

Disconnect from the Sandbox, cleaning up local resources. The Sandbox continues running.
sandbox.detach();

Example: Run a Python script

import { ModalClient } from "modal";

const modal = new ModalClient();

const app = await modal.apps.fromName("python-runner", {
  createIfMissing: true,
});

const image = modal.images
  .fromRegistry("python:3.13")
  .dockerfileCommands(["RUN pip install requests numpy"]);

const sandbox = await modal.sandboxes.create(app, image, {
  memoryMiB: 2048,
});

// Write a script
const script = await sandbox.open("/tmp/script.py", "w");
await script.write(`
import numpy as np
print(f"NumPy version: {np.__version__}")
print(f"Random array: {np.random.rand(5)}")
`);
await script.close();

// Execute it
const proc = await sandbox.exec(["python", "/tmp/script.py"]);
const output = await proc.stdout.readText();
console.log(output);

await sandbox.terminate();

Example: Web server with port tunneling

import { ModalClient } from "modal";

const modal = new ModalClient();

const app = await modal.apps.fromName("web-server", {
  createIfMissing: true,
});

const image = modal.images
  .fromRegistry("python:3.13")
  .dockerfileCommands(["RUN pip install fastapi uvicorn"]);

const sandbox = await modal.sandboxes.create(app, image, {
  encryptedPorts: [8000],
  command: [
    "uvicorn",
    "main:app",
    "--host",
    "0.0.0.0",
    "--port",
    "8000",
  ],
});

const tunnels = await sandbox.tunnels();
const tunnel = tunnels[8000];
console.log(`Server available at: ${tunnel.url}`);

// Access the server...

await sandbox.terminate();

Build docs developers (and LLMs) love