Build secure, isolated code execution environments on Cloudflare Workers.
bash
npm install @cloudflare/sandbox
docker info # Must succeed - Docker required for local dev
Your knowledge of the Sandbox SDK may be outdated. Prefer retrieval over pre-training for any Sandbox SDK task.
ResourceURLDocshttps://developers.cloudflare.com/sandbox/API Referencehttps://developers.cloudflare.com/sandbox/api/Exampleshttps://github.com/cloudflare/sandbox-sdk/tree/main/examplesGet Startedhttps://developers.cloudflare.com/sandbox/get-started/
When implementing features, fetch the relevant doc page or example first.
wrangler.jsonc (exact - do not modify structure):
jsonc
{
"containers": [{
"class_name": "Sandbox",
"image": "./Dockerfile",
"instance_type": "lite",
"max_instances": 1
}],
"durable_objects": {
"bindings": [{ "class_name": "Sandbox", "name": "Sandbox" }]
},
"migrations": [{ "new_sqlite_classes": ["Sandbox"], "tag": "v1" }]
}
Worker entry - must re-export Sandbox class:
typescript
import { getSandbox } from '@cloudflare/sandbox';
export { Sandbox } from '@cloudflare/sandbox'; // Required export
TaskMethodGet sandboxgetSandbox(env.Sandbox, 'user-123')Run commandawait sandbox.exec('python script.py')Run code (interpreter)await sandbox.runCode(code, { language: 'python' })Write fileawait sandbox.writeFile('/workspace/app.py', content)Read fileawait sandbox.readFile('/workspace/app.py')Create directoryawait sandbox.mkdir('/workspace/src', { recursive: true })List filesawait sandbox.listFiles('/workspace')Expose portawait sandbox.exposePort(8080)Destroyawait sandbox.destroy()
typescript
const sandbox = getSandbox(env.Sandbox, 'user-123');
const result = await sandbox.exec('python --version');
// result: { stdout, stderr, exitCode, success }
Use runCode() for executing LLM-generated code with rich outputs:
typescript
const ctx = await sandbox.createCodeContext({ language: 'python' });
await sandbox.runCode('import pandas as pd; data = [1,2,3]', { context: ctx });
const result = await sandbox.runCode('sum(data)', { context: ctx });
// result.results[0].text = "6"
Languages: python, javascript, typescript
State persists within context. Create explicit contexts for production.
typescript
await sandbox.mkdir('/workspace/project', { recursive: true });
await sandbox.writeFile('/workspace/project/main.py', code);
const file = await sandbox.readFile('/workspace/project/main.py');
const files = await sandbox.listFiles('/workspace/project');
NeedUseWhyShell commands, scriptsexec()Direct control, streamingLLM-generated coderunCode()Rich outputs, state persistenceBuild/test pipelinesexec()Exit codes, stderr captureData analysisrunCode()Charts, tables, pandas
Base image ( docker.io/cloudflare/sandbox:0.7.0) includes Python 3.11, Node.js 20, and common tools.
Add dependencies by extending the Dockerfile:
dockerfile
FROM docker.io/cloudflare/sandbox:0.7.0
# Python packages
RUN pip install requests beautifulsoup4
# Node packages (global)
RUN npm install -g typescript
# System packages
RUN apt-get update && apt-get install -y ffmpeg && rm -rf /var/lib/apt/lists/*
EXPOSE 8080 # Required for local dev port exposure
Keep images lean - affects cold start time.
Expose HTTP services running in sandboxes:
typescript
const { url } = await sandbox.exposePort(8080);
// Returns preview URL for the service
Production requirement: Preview URLs need a custom domain with wildcard DNS ( *.yourdomain.com). The .workers.dev domain does not support preview URL subdomains.
See: https://developers.cloudflare.com/sandbox/guides/expose-services/
The SDK provides helpers for OpenAI Agents at @cloudflare/sandbox/openai:
typescript
import { Shell, Editor } from '@cloudflare/sandbox/openai';
See examples/openai-agents for complete integration pattern.
getSandbox() returns immediately - container starts lazily on first operationsleepAfter)destroy() to immediately free resourcessandboxId always returns same sandbox instanceCommandClient, FileClient) - use sandbox.* methodsexport { Sandbox }destroy() for temporary sandboxes