### Start Services Sequentially with Dependencies Source: https://developers.cloudflare.com/sandbox/guides/background-processes Start services in sequence, waiting for dependencies to be ready. This example starts a database and then an API server that depends on it. ```javascript // Start database first const db = await sandbox.startProcess("redis-server"); // Wait for database to be ready await db.waitForPort(6379, { mode: "tcp" }); // Now start API server (depends on database) const api = await sandbox.startProcess("node api-server.js", { env: { DATABASE_URL: "redis://localhost:6379" }, }); // Wait for API to be ready await api.waitForPort(8080, { path: "/health" }); console.log("All services running"); ``` ```javascript // Start database first const db = await sandbox.startProcess('redis-server'); // Wait for database to be ready await db.waitForPort(6379, { mode: 'tcp' }); // Now start API server (depends on database) const api = await sandbox.startProcess('node api-server.js', { env: { DATABASE_URL: 'redis://localhost:6379' } }); // Wait for API to be ready await api.waitForPort(8080, { path: '/health' }); console.log('All services running'); ``` -------------------------------- ### Example Custom Startup Script Source: https://developers.cloudflare.com/sandbox/configuration/dockerfile A bash script to start services in the background and wait for them, ensuring proper signal forwarding by the sandbox binary. ```bash #!/bin/bash # Start your services in the background node /workspace/my-app.js & # Start additional services redis-server --daemonize yes until redis-cli ping; do sleep 1; done # Keep the script running (the sandbox binary handles the API server) wait ``` -------------------------------- ### Start Services in Sequence (TypeScript) Source: https://developers.cloudflare.com/sandbox/llms-full.txt This TypeScript snippet achieves the same sequential service startup as the JavaScript example, ensuring dependencies are satisfied. It's useful for complex application setups requiring ordered initialization. ```typescript // Start database firstconst db = await sandbox.startProcess('redis-server'); // Wait for database to be readyawait db.waitForPort(6379, { mode: 'tcp' }); // Now start API server (depends on database)const api = await sandbox.startProcess('node api-server.js', { env: { DATABASE_URL: 'redis://localhost:6379' } }); // Wait for API to be readyawait api.waitForPort(8080, { path: '/health' }); console.log('All services running'); ``` -------------------------------- ### Example: Expose and Access a Tunnel Source: https://developers.cloudflare.com/sandbox/api/tunnels Demonstrates how to start a process, get a tunnel for a specific port, and access its URL. Repeated calls for the same port return the same record. ```typescript import { getSandbox } from "@cloudflare/sandbox"; export { Sandbox } from "@cloudflare/sandbox"; export default { async fetch(request, env) { 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 // Repeated calls for the same port return the same record. const same = await sandbox.tunnels.get(8080); console.log(same.url === tunnel.url); // true return Response.json({ url: tunnel.url }); }, }; ``` ```typescript import { getSandbox } from "@cloudflare/sandbox"; export { Sandbox } from "@cloudflare/sandbox"; export default { async fetch(request: Request, env: Env): Promise { 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 // Repeated calls for the same port return the same record. const same = await sandbox.tunnels.get(8080); console.log(same.url === tunnel.url); // true return Response.json({ url: tunnel.url }); }, }; ``` -------------------------------- ### Start Services in Sequence (JavaScript) Source: https://developers.cloudflare.com/sandbox/llms-full.txt Use this snippet to start multiple services sequentially, ensuring dependencies are met before proceeding. It demonstrates waiting for a database to be ready before starting an API server. ```javascript // Start database firstconst db = await sandbox.startProcess("redis-server"); // Wait for database to be readyawait db.waitForPort(6379, { mode: "tcp" }); // Now start API server (depends on database)const api = await sandbox.startProcess("node api-server.js", { env: { DATABASE_URL: "redis://localhost:6379" },}); // Wait for API to be readyawait api.waitForPort(8080, { path: "/health" }); console.log("All services running"); ``` -------------------------------- ### Create a Sandbox Instance Source: https://developers.cloudflare.com/sandbox/concepts/sandboxes/index.md A sandbox is created the first time you reference its ID. This example shows how to get a sandbox instance and execute a command. ```typescript const sandbox = getSandbox(env.Sandbox, "user-123"); await sandbox.exec('echo "Hello"'); // First request creates sandbox ``` -------------------------------- ### Start Local Development Server Source: https://developers.cloudflare.com/sandbox/tutorials/automated-testing-pipeline Run this command to start the local development server for your testing pipeline. ```bash npm run dev ``` -------------------------------- ### Install Python, Node.js, and System Packages Source: https://developers.cloudflare.com/sandbox/concepts/containers Install additional software at runtime using standard package managers for Python, Node.js, and system packages. ```bash # Python packages pip install scikit-learn tensorflow # Node.js packages npm install express # System packages (requires apt-get update first) apt-get update && apt-get install -y redis-server ``` -------------------------------- ### Start Process with Environment Configuration Source: https://developers.cloudflare.com/sandbox/llms-full.txt Starts a new process, such as a Node.js server, and configures its working directory and environment variables. Use this to set up the execution context for your application. ```javascript const process = await sandbox.startProcess("node server.js", { cwd: "/workspace/api", env: { NODE_ENV: "production", PORT: "8080", API_KEY: env.API_KEY, DATABASE_URL: env.DATABASE_URL, },}); console.log("API server started"); ``` ```typescript const process = await sandbox.startProcess('node server.js', { cwd: '/workspace/api', env: { NODE_ENV: 'production', PORT: '8080', API_KEY: env.API_KEY, DATABASE_URL: env.DATABASE_URL }}); console.log('API server started'); ``` -------------------------------- ### Start and list processes across sessions Source: https://developers.cloudflare.com/sandbox/concepts/sessions/index.md Shows how to start a process in one session and see it listed in another within the same sandbox. ```typescript await session1.startProcess('node server.js'); await session2.listProcesses(); // Sees the server ``` -------------------------------- ### Install Sandbox Dependencies (bun) Source: https://developers.cloudflare.com/sandbox/guides/browser-terminals/index.md Install the necessary dependencies for the sandbox functionality using bun. ```bash bun install @xterm/xterm @xterm/addon-fit @cloudflare/sandbox ``` -------------------------------- ### Install Runtime Software Source: https://developers.cloudflare.com/sandbox/llms-full.txt Install additional software at runtime using standard package managers for Python, Node.js, and system packages. Ensure to update package lists before installing system packages. ```bash # Python packages pip install scikit-learn tensorflow # Node.js packages npm install express # System packages (requires apt-get update first) apt-get update && apt-get install -y redis-server ``` -------------------------------- ### Install dependencies with bun Source: https://developers.cloudflare.com/sandbox/tutorials/code-review-bot/index.md Install the necessary bun packages for Anthropic AI SDK and Octokit REST client. ```bash bun add @anthropic-ai/sdk @octokit/rest ``` -------------------------------- ### Example Startup Script Source: https://developers.cloudflare.com/sandbox/configuration/dockerfile/index.md A basic bash script that can be used as a custom startup command for the sandbox. ```bash #!/bin/bash ``` -------------------------------- ### Back up and Restore with localBucket Source: https://developers.cloudflare.com/sandbox/guides/backup-restore This example demonstrates how to create and restore a local backup using the `localBucket: true` option. ```javascript const sandbox = getSandbox(env.Sandbox, "my-sandbox"); // Create a local backup const backup = await sandbox.createBackup({ dir: "/workspace", localBucket: true, }); // Restore the backup const result = await sandbox.restoreBackup(backup); console.log(`Restored: ${result.success}`); ``` -------------------------------- ### Manage Sandbox Processes and Tunnels in a Worker (TypeScript) Source: https://developers.cloudflare.com/sandbox/api/tunnels/index.md This TypeScript code provides the same functionality as the JavaScript example, demonstrating the use of the Cloudflare Sandbox SDK. It includes type annotations for better code clarity and safety. It shows how to get or start a process, provision a tunnel, and handle errors. ```typescript import { getSandbox } from "@cloudflare/sandbox"; export { Sandbox } from "@cloudflare/sandbox"; export default { async fetch(request: Request, env: Env): Promise { const sandbox = getSandbox(env.Sandbox, "my-sandbox"); // Reuse an existing app process across container restarts, or start it. let proc = await sandbox.getProcess('app'); if (!proc) { try { proc = await sandbox.startProcess('python -m http.server 8080', { processId: 'app' }); } catch (err) { if ((err as { code?: string })?.code !== 'PROCESS_ALREADY_EXISTS') throw err; proc = await sandbox.getProcess('app'); } } // Provision (or reuse) https://app.example.com pointing at port 8080. const tunnel = await sandbox.tunnels.get(8080, { name: "app" }); console.log(tunnel.url); // → https://app.example.com return Response.json({ url: tunnel.url }); }, }; ``` -------------------------------- ### Example: Create and Restore Backup (JavaScript) Source: https://developers.cloudflare.com/sandbox/api/backups/index.md Demonstrates creating a backup of `/workspace` and then restoring it using the Sandbox API in JavaScript. Requires `getSandbox` import and an R2 binding. ```javascript import { getSandbox } from "@cloudflare/sandbox"; const sandbox = getSandbox(env.Sandbox, "my-sandbox"); // Create a backup of /workspaceconst backup = await sandbox.createBackup({ dir: "/workspace" }); // Later, restore the backupawait sandbox.restoreBackup(backup); ``` -------------------------------- ### Legacy startup script example Source: https://developers.cloudflare.com/sandbox/configuration/dockerfile/index.md Existing startup scripts ending with `exec bun /container-server/dist/index.js` will continue to function for backward compatibility. It is recommended to migrate to the `CMD` instruction for new startup scripts. ```shell exec bun /container-server/dist/index.js ``` -------------------------------- ### Get Install Command Source: https://developers.cloudflare.com/sandbox/tutorials/automated-testing-pipeline/index.md Returns the appropriate dependency installation command based on the detected project type. This ensures that dependencies are installed correctly for Node.js, Python, or Go projects. ```typescript function getInstallCommand(projectType: string): string { switch (projectType) { case 'nodejs': return 'npm install'; case 'python': return 'pip install -r requirements.txt || pip install -e .'; case 'go': return 'go mod download'; default: return ''; } } ``` -------------------------------- ### Wait for service to start before exposing port (JavaScript) Source: https://developers.cloudflare.com/sandbox/llms-full.txt If a port is not ready when you try to expose it, wait for the service to start. This JavaScript example starts a process with 'npm run dev' and then waits for 3 seconds before exposing port 8080. ```javascript // Extract hostname from requestconst { hostname } = new URL(request.url); await sandbox.startProcess("npm run dev");await new Promise((resolve) => setTimeout(resolve, 3000));await sandbox.exposePort(8080, { hostname }); ``` -------------------------------- ### Kill Existing Processes Before Starting (TypeScript) Source: https://developers.cloudflare.com/sandbox/llms-full.txt This TypeScript example shows how to clear any running processes using `killAllProcesses()` to avoid port conflicts before starting a new server process. ```typescript await sandbox.killAllProcesses();const server = await sandbox.startProcess('node server.js'); ``` -------------------------------- ### Navigate to the project directory Source: https://developers.cloudflare.com/sandbox/get-started/index.md Change into the newly created project directory. ```bash cd my-sandbox ``` -------------------------------- ### Start Cloudflare Tunnel and Get Preview URL Source: https://developers.cloudflare.com/sandbox/concepts/preview-urls Use this to quickly deploy a web service and get a preview URL. The URL is randomly generated and has no authentication. Each URL uses an additional `cloudflared` process. ```javascript await sandbox.startProcess("python -m http.server 8000"); const tunnel = await sandbox.tunnels.get(8000); console.log(tunnel.url); // https://acute-llama-dancing-roundly.trycloudflare.app // Request will be routed directly to the webserver running on the sandbox. const req = await fetch(`${tunnel.url}/api/users`); // => GET http://localhost:8000/api/users ``` -------------------------------- ### Create startup script for WebSocket server Source: https://developers.cloudflare.com/sandbox/guides/websocket-connections/index.md This script prepares the environment for running a WebSocket server within the sandbox. It ensures the server script is executable and then starts the WebSocket server and the SDK's control plane. ```bash #!/bin/bash # Start your WebSocket server in the background bun /workspace/echo-server.ts # Start SDK's control plane (needed for the SDK to work) exec bun dist/index.js ``` -------------------------------- ### SandboxAddon Initialization and Usage Source: https://developers.cloudflare.com/sandbox/api/terminal Demonstrates how to initialize the SandboxAddon with custom options and connect it to a sandbox terminal. It includes setting up the WebSocket URL and handling connection state changes. ```APIDOC ## SandboxAddon Initialization and Usage ### Description Initializes the `SandboxAddon` for xterm.js, which manages the WebSocket connection to a Cloudflare Sandbox. It allows customization of the WebSocket URL, reconnection behavior, and provides callbacks for connection state changes. ### Constructor ```typescript new SandboxAddon(options: SandboxAddonOptions) ``` ### Options * `getWebSocketUrl(params)` - Function to construct the WebSocket URL. Receives `sandboxId`, `sessionId` (optional), and `origin`. Returns the WebSocket URL string. * `reconnect` - Boolean, enables automatic reconnection with exponential backoff. Defaults to `true`. * `onStateChange(state, error?)` - Callback function invoked when the connection state changes. `state` can be 'disconnected', 'connecting', or 'connected'. `error` is provided if the state change is due to an error. ### Example Usage ```typescript import { Terminal } from "@xterm/xterm"; import { SandboxAddon } from "@cloudflare/sandbox/xterm"; const terminal = new Terminal({ cursorBlink: true }); terminal.open(document.getElementById("terminal")); const addon = new SandboxAddon({ getWebSocketUrl: ({ sandboxId, sessionId, origin }) => { const params = new URLSearchParams({ id: sandboxId }); if (sessionId) params.set("session", sessionId); return `${origin}/ws/terminal?${params}`; }, onStateChange: (state, error) => { console.log(`Terminal ${state}`, error); }, }); terminal.loadAddon(addon); addon.connect({ sandboxId: "my-sandbox" }); ``` ``` -------------------------------- ### Start a background web server process Source: https://developers.cloudflare.com/sandbox/guides/background-processes/index.md Use `startProcess()` to launch a long-running service like a web server. The process runs in the background, allowing your main code to continue execution. This example starts a Python HTTP server. ```javascript import { getSandbox } from "@cloudflare/sandbox"; const sandbox = getSandbox(env.Sandbox, "my-sandbox"); // Start a web serverconst server = await sandbox.startProcess("python -m http.server 8000"); console.log("Server started");console.log("Process ID:", server.id);console.log("PID:", server.pid);console.log("Status:", server.status); // 'running' // Process runs in background - your code continues ``` ```typescript import { getSandbox } from '@cloudflare/sandbox'; const sandbox = getSandbox(env.Sandbox, 'my-sandbox'); // Start a web serverconst server = await sandbox.startProcess('python -m http.server 8000'); console.log('Server started');console.log('Process ID:', server.id);console.log('PID:', server.pid);console.log('Status:', server.status); // 'running' // Process runs in background - your code continues ``` -------------------------------- ### Create startup script for WebSocket server Source: https://developers.cloudflare.com/sandbox/guides/websocket-connections Starts the WebSocket server in the background and then executes the SDK's control plane. ```bash #!/bin/bash # Start your WebSocket server in the background bun /workspace/echo-server.ts & # Start SDK's control plane (needed for the SDK to work) exec bun dist/index.js ``` -------------------------------- ### Provision and Access a Tunnel Source: https://developers.cloudflare.com/sandbox/api/tunnels This snippet demonstrates how to get or start a process, then provision a tunnel to expose it. It reuses existing processes and tunnels if available, otherwise it starts a new process and creates a new tunnel. The tunnel's public URL is logged and returned. ```typescript import { getSandbox } from "@cloudflare/sandbox"; export { Sandbox } from "@cloudflare/sandbox"; export default { async fetch(request, env) { const sandbox = getSandbox(env.Sandbox, "my-sandbox"); // Reuse an existing app process across container restarts, or start it. let proc = await sandbox.getProcess("app"); if (!proc) { try { proc = await sandbox.startProcess("python -m http.server 8080", { processId: "app", }); } catch (err) { if (err?.code !== "PROCESS_ALREADY_EXISTS") throw err; proc = await sandbox.getProcess("app"); } } // Provision (or reuse) https://app.example.com pointing at port 8080. const tunnel = await sandbox.tunnels.get(8080, { name: "app" }); console.log(tunnel.url); // → https://app.example.com return Response.json({ url: tunnel.url }); }, }; ``` ```typescript import { getSandbox } from "@cloudflare/sandbox"; export { Sandbox } from "@cloudflare/sandbox"; export default { async fetch(request: Request, env: Env): Promise { const sandbox = getSandbox(env.Sandbox, "my-sandbox"); // Reuse an existing app process across container restarts, or start it. let proc = await sandbox.getProcess('app'); if (!proc) { try { proc = await sandbox.startProcess('python -m http.server 8080', { processId: 'app' }); } catch (err) { if ((err as { code?: string })?.code !== 'PROCESS_ALREADY_EXISTS') throw err; proc = await sandbox.getProcess('app'); } } // Provision (or reuse) https://app.example.com pointing at port 8080. const tunnel = await sandbox.tunnels.get(8080, { name: "app" }); console.log(tunnel.url); // → https://app.example.com return Response.json({ url: tunnel.url }); }, }; ``` -------------------------------- ### Write and Read File (Python) Source: https://developers.cloudflare.com/sandbox/llms-full.txt Use Python with httpx to write 'hello world' to 'hello.py' in the sandbox and then retrieve the file's content. ```python # /// script# dependencies = ["httpx"]# /// import os import httpx API_URL = os.environ["SANDBOX_API_URL"] API_KEY = os.environ["SANDBOX_API_KEY"] SANDBOX_ID = os.environ["SANDBOX_ID"] # from the "Create a sandbox" step headers = {"Authorization": f"Bearer {API_KEY}"} # Write a file httpx.put( f"{API_URL}/v1/sandbox/{SANDBOX_ID}/file/workspace/hello.py", headers=headers, content=b'print("hello world")', ) # Read a file content = httpx.get( f"{API_URL}/v1/sandbox/{SANDBOX_ID}/file/workspace/hello.py", headers=headers, ).text print(content) ``` -------------------------------- ### Create and Log Tunnel URL - TypeScript Source: https://developers.cloudflare.com/sandbox/llms-full.txt Starts an HTTP server in the sandbox and retrieves its tunnel URL. Demonstrates idempotency of the get() method for tunnels. ```typescript import { getSandbox } from "@cloudflare/sandbox"; export { Sandbox } from "@cloudflare/sandbox"; export default { async fetch(request: Request, env: Env): Promise { 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 // Repeated calls for the same port return the same record. const same = await sandbox.tunnels.get(8080); console.log(same.url === tunnel.url); // true return Response.json({ url: tunnel.url }); }, }; ``` -------------------------------- ### Create and Store Backup Handle Source: https://developers.cloudflare.com/sandbox/guides/backup-restore This example shows how to create a backup, store its handle in KV, and later retrieve and restore from it. ```javascript const sandbox = getSandbox(env.Sandbox, "my-sandbox"); // Create a backup and store the handle in KV const backup = await sandbox.createBackup({ dir: "/workspace", name: "deploy-v2", ttl: 604800, // 7 days }); await env.KV.put(`backup:${userId}`, JSON.stringify(backup)); // Later, retrieve and restore const stored = await env.KV.get(`backup:${userId}`); if (stored) { const backupHandle = JSON.parse(stored); await sandbox.restoreBackup(backupHandle); } ``` -------------------------------- ### Intercept All Outbound HTTP/HTTPS Traffic (JavaScript) Source: https://developers.cloudflare.com/sandbox/llms-full.txt Use the `outbound` property to intercept all outbound HTTP and HTTPS traffic from the sandbox. This example blocks any method other than GET. ```javascript import { Sandbox, ContainerProxy } from "@cloudflare/sandbox";export { ContainerProxy }; export class MySandbox extends Sandbox {} MySandbox.outbound = async (request, env, ctx) => { if (request.method !== "GET") { console.log(`Blocked ${request.method} to ${request.url}`); return new Response("Method Not Allowed", { status: 405 }); } return fetch(request); }; ``` -------------------------------- ### Main Execution Block Source: https://developers.cloudflare.com/sandbox/tutorials/openai-agents/index.md Sets up the asyncio event loop to run the 'run' function. It takes the prompt from command-line arguments or defaults to a 'hello world' server creation task. ```python if __name__ == "__main__": prompt = sys.argv[1] if len(sys.argv) > 1 else "Create a hello world HTTP server using Bun.serve" asyncio.run(run(prompt, Path("output"))) ``` -------------------------------- ### Intercept All Outbound HTTP/HTTPS Traffic (TypeScript) Source: https://developers.cloudflare.com/sandbox/llms-full.txt Use the `outbound` property to intercept all outbound HTTP and HTTPS traffic from the sandbox in TypeScript. This example blocks any method other than GET. ```typescript import { Sandbox, ContainerProxy } from "@cloudflare/sandbox";export { ContainerProxy }; export class MySandbox extends Sandbox {} MySandbox.outbound = async ( request: Request, env: Env, ctx: OutboundHandlerContext, ) => { if (request.method !== "GET") { console.log(`Blocked ${request.method} to ${request.url}`); return new Response("Method Not Allowed", { status: 405 }); } return fetch(request); }; ``` -------------------------------- ### Stream command execution with TypeScript Source: https://developers.cloudflare.com/sandbox/guides/streaming-output Use `execStream()` to get real-time output from a command. This example iterates over the stream, handling stdout, stderr, completion, and error events. ```typescript import { getSandbox, parseSSEStream } from "@cloudflare/sandbox"; const sandbox = getSandbox(env.Sandbox, "my-sandbox"); const stream = await sandbox.execStream("npm run build"); for await (const event of parseSSEStream(stream)) { switch (event.type) { case "stdout": console.log(event.data); break; case "stderr": console.error(event.data); break; case "complete": console.log("Exit code:", event.exitCode); break; case "error": console.error("Failed:", event.error); break; } } ``` ```typescript import { getSandbox, parseSSEStream, type ExecEvent } from '@cloudflare/sandbox'; const sandbox = getSandbox(env.Sandbox, 'my-sandbox'); const stream = await sandbox.execStream('npm run build'); for await (const event of parseSSEStream(stream)) { switch (event.type) { case 'stdout': console.log(event.data); break; case 'stderr': console.error(event.data); break; case 'complete': console.log('Exit code:', event.exitCode); break; case 'error': console.error('Failed:', event.error); break; } } ``` -------------------------------- ### Wrangler Configuration for Sandbox Example Source: https://developers.cloudflare.com/sandbox/llms-full.txt Configure your Wrangler project with AI bindings, container setup for sandboxes, and Durable Objects. Ensure the `compatibility_date` is set to a recent date. ```json { "name": "sandbox-code-interpreter-example", "main": "src/index.ts", // Set this to today's date "compatibility_date": "2026-06-30", "ai": { "binding": "AI" }, "containers": [ { "class_name": "Sandbox", "image": "./Dockerfile", "name": "sandbox", "max_instances": 1, "instance_type": "basic" } ], "durable_objects": { "bindings": [ { "class_name": "Sandbox", "name": "Sandbox" } ] } } ``` ```toml name = "sandbox-code-interpreter-example" main = "src/index.ts" # Set this to today's date compatibility_date = "2026-06-30" [ai] binding = "AI" [[containers]] class_name = "Sandbox" image = "./Dockerfile" name = "sandbox" max_instances = 1 instance_type = "basic" [[durable_objects.bindings]] class_name = "Sandbox" name = "Sandbox" ``` -------------------------------- ### Start the development server Source: https://developers.cloudflare.com/sandbox/get-started/index.md Run the development server to test your Worker locally. The first run may take a few minutes to build the Docker container. ```bash npm run dev ``` -------------------------------- ### Get Sandbox Instance Source: https://developers.cloudflare.com/sandbox/llms-full.txt Retrieve or create a sandbox instance by ID. The container starts lazily on the first operation. It's recommended to set `enableDefaultSession` to `false` for isolated operations. ```typescript const sandbox = getSandbox( binding: DurableObjectNamespace, sandboxId: string, options?: SandboxOptions): Sandbox ``` ```javascript import { getSandbox } from "@cloudflare/sandbox"; export default { async fetch(request, env) { const sandbox = getSandbox(env.Sandbox, "user-123"); const result = await sandbox.exec("python script.py"); return Response.json(result); }, }; ``` ```typescript import { getSandbox } from '@cloudflare/sandbox'; export default { async fetch(request: Request, env: Env): Promise { const sandbox = getSandbox(env.Sandbox, 'user-123'); const result = await sandbox.exec('python script.py'); return Response.json(result); } }; ``` -------------------------------- ### JavaScript: Create Proxy Handler and Issue Sandbox Token Source: https://developers.cloudflare.com/sandbox/guides/proxy-requests Use `createProxyHandler` to register services and `createProxyToken` to issue tokens for sandboxes. This example shows the basic setup for a Cloudflare Worker. ```javascript import { getSandbox } from "@cloudflare/sandbox"; import { createProxyHandler, createProxyToken } from "./proxy"; import { myApi } from "./services/myapi"; export { Sandbox } from "@cloudflare/sandbox"; const proxyHandler = createProxyHandler({ mountPath: "/proxy", jwtSecret: (env) => env.PROXY_JWT_SECRET, services: { myapi: myApi }, }); export default { async fetch(request, env) { const url = new URL(request.url); // Route all /proxy/* requests through the proxy handler if (url.pathname.startsWith("/proxy/")) { return proxyHandler(request, env); } // Create a sandbox and issue it a short-lived token const sandboxId = "my-sandbox"; const sandbox = getSandbox(env.Sandbox, sandboxId); const token = await createProxyToken({ secret: env.PROXY_JWT_SECRET, sandboxId, expiresIn: "15m", }); const proxyBase = `https://${url.hostname}`; // Pass the token and proxy base URL to the sandbox await sandbox.setEnvVars({ PROXY_TOKEN: token, PROXY_BASE: proxyBase, }); return Response.json({ message: "Sandbox ready" }); }, }; ``` -------------------------------- ### Running Application with Sandbox Binary and CMD Source: https://developers.cloudflare.com/sandbox/configuration/dockerfile Use a custom base image, copy the sandbox binary, and define the application's entrypoint and command using ENTRYPOINT and CMD. ```dockerfile FROM node:20-slim COPY --from=docker.io/cloudflare/sandbox:0.7.0 /container-server/sandbox /sandbox # Copy your application COPY . /app WORKDIR /app ENTRYPOINT ["/sandbox"] CMD ["node", "server.js"] ``` -------------------------------- ### Stream process logs with TypeScript Source: https://developers.cloudflare.com/sandbox/guides/streaming-output/index.md Monitor background process output using `streamProcessLogs()` in TypeScript. This example starts a Node.js server process and streams its logs, using `LogEvent` for type safety. ```typescript import { parseSSEStream, type LogEvent } from '@cloudflare/sandbox'; const process = await sandbox.startProcess('node server.js'); ``` -------------------------------- ### Stream process logs with JavaScript Source: https://developers.cloudflare.com/sandbox/guides/streaming-output/index.md Monitor background process output using `streamProcessLogs()`. This example starts a Node.js server process and streams its logs, stopping when a 'Server listening' message is detected. ```javascript import { parseSSEStream } from "@cloudflare/sandbox"; const process = await sandbox.startProcess("node server.js"); const logStream = await sandbox.streamProcessLogs(process.id); for await (const log of parseSSEStream(logStream)) { console.log(log.data); if (log.data.includes("Server listening")) { console.log("Server is ready"); break; } } ``` -------------------------------- ### Set up Local Environment Variables Source: https://developers.cloudflare.com/sandbox/tutorials/analyze-data-with-ai/index.md Create a .dev.vars file in your project root for local development. Replace 'your_api_key_here' with your actual API key. The SANDBOX_TRANSPORT=rpc is required for new file streaming APIs. This file is gitignored and only used locally. ```bash echo "ANTHROPIC_API_KEY=your_api_key_here\nSANDBOX_TRANSPORT=rpc" > .dev.vars ``` -------------------------------- ### Expose Ports with Tunnels API Source: https://developers.cloudflare.com/sandbox/guides/2026-deprecation Replace exposePort() with the tunnels API for public URLs. This example demonstrates starting a process, waiting for a port, and returning the tunnel URL. Requires RPC transport. ```typescript import { getSandbox } from "@cloudflare/sandbox"; const sandbox = getSandbox(env.Sandbox, "my-sandbox", { transport: "rpc", }); const server = await sandbox.startProcess("python -m http.server 8080"); await server.waitForPort(8080); const tunnel = await sandbox.tunnels.get(8080); return Response.json({ url: tunnel.url }); ``` -------------------------------- ### Set up local environment variables Source: https://developers.cloudflare.com/sandbox/tutorials/claude-code Create a .dev.vars file to store your Anthropic API key for local development. This file is gitignored. ```bash echo "ANTHROPIC_API_KEY=your_api_key_here" > .dev.vars ``` -------------------------------- ### Expose a different port when 3000 is reserved (TypeScript) Source: https://developers.cloudflare.com/sandbox/llms-full.txt Similar to the JavaScript example, this TypeScript snippet shows how to avoid the reserved port 3000 by starting a Node.js process with a custom port (8080) and then exposing it. ```typescript // Extract hostname from requestconst { hostname } = new URL(request.url); // ❌ This will failawait sandbox.exposePort(3000, { hostname }); // Error: Port 3000 is reserved // ✅ Use a different portawait sandbox.startProcess('node server.js', { env: { PORT: '8080' } });await sandbox.exposePort(8080, { hostname }); ``` -------------------------------- ### Clone and Build Project with Git Checkout and Exec Source: https://developers.cloudflare.com/sandbox/guides/git-workflows/index.md Clone a repository and then use `exec` to run installation and build commands within the cloned directory. Ensure the `repoName` variable correctly matches the cloned repository's name. ```javascript await sandbox.gitCheckout("https://github.com/user/my-app"); const repoName = "my-app"; // Install and buildawait sandbox.exec(`cd ${repoName} && npm install`); await sandbox.exec(`cd ${repoName} && npm run build`); console.log("Build complete"); ``` ```typescript await sandbox.gitCheckout('https://github.com/user/my-app'); const repoName = 'my-app'; // Install and buildawait sandbox.exec(`cd ${repoName} && npm install`); await sandbox.exec(`cd ${repoName} && npm run build`); console.log('Build complete'); ``` -------------------------------- ### Create Terminal Connection to Specific Session (TypeScript) Source: https://developers.cloudflare.com/sandbox/llms-full.txt To create a terminal connection to a specific sandbox session, first get the session using `sandbox.getSession()` and then call `terminal()` on the session object. This example uses TypeScript. ```typescript // Specific session const session = await sandbox.getSession('dev'); return await session.terminal(request); ``` -------------------------------- ### Create Terminal Connection to Specific Session (JavaScript) Source: https://developers.cloudflare.com/sandbox/llms-full.txt To create a terminal connection to a specific sandbox session, first get the session using `sandbox.getSession()` and then call `terminal()` on the session object. This example uses JavaScript. ```javascript // Specific session const session = await sandbox.getSession("dev"); return await session.terminal(request); ``` -------------------------------- ### Set up Local Environment Variables Source: https://developers.cloudflare.com/sandbox/llms-full.txt This command-line snippet demonstrates how to create a `.dev.vars` file for local development, essential for storing sensitive tokens and secrets like GitHub and Anthropic API keys. ```bash cat > .dev.vars << EOFGITHUB_TOKEN=your_github_token_hereANTHROPIC_API_KEY=your_anthropic_key_hereWEBHOOK_SECRET=your_webhook_secret_hereEOF ``` -------------------------------- ### getSandbox() Source: https://developers.cloudflare.com/sandbox/api/lifecycle Get or create a sandbox instance by ID. The container starts lazily on first operation. Calling getSandbox() returns immediately—the container only spins up when you execute a command, write a file, or perform other operations. ```APIDOC ## getSandbox() ### Description Get or create a sandbox instance by ID. ### Method Signature `getSandbox(binding: DurableObjectNamespace, sandboxId: string, options?: SandboxOptions): Sandbox` ### Parameters #### Path Parameters * `binding` (DurableObjectNamespace) - Required - The Durable Object namespace binding from your Worker environment. * `sandboxId` (string) - Required - Unique identifier for this sandbox. The same ID always returns the same sandbox instance. In user-facing apps, scope IDs to a single user. * `options` (SandboxOptions) - Optional - Configuration options for the sandbox. * `enableDefaultSession` (boolean) - Use the default session for operations without an explicit `sessionId`. Set to `false` to evaluate each call in isolation (default: `true`). * `sleepAfter` (string) - Duration of inactivity before automatic sleep (default: `"10m"`). * `keepAlive` (boolean) - Prevent automatic sleep entirely. Persists across hibernation (default: `false`). * `containerTimeouts` (object) - Configure container startup timeouts. * `normalizeId` (boolean) - Lowercase sandbox IDs for preview URL compatibility (default: `false`). ### Returns `Sandbox` - The Sandbox instance. ### Example Usage ```javascript import { getSandbox } from "@cloudflare/sandbox"; export default { async fetch(request, env) { const sandbox = getSandbox(env.Sandbox, "user-123"); const result = await sandbox.exec("python script.py"); return Response.json(result); }, }; ``` ``` -------------------------------- ### Initialize and Connect to WebSocket Server (JavaScript) Source: https://developers.cloudflare.com/sandbox/guides/websocket-connections/index.md Initializes a Bun WebSocket server on the first connection and then connects to it. Requires the sandbox environment. ```javascript if (upgrade === "websocket") { // Initialize server on first connection if (!initialized) { await sandbox.writeFile( "/workspace/server.js", `Bun.serve({ port: 8080, fetch(req, server) { server.upgrade(req); }, websocket: { message(ws, msg) { ws.send(\`Echo: ${msg}\\`); } } });` ); await sandbox.startProcess("bun /workspace/server.js"); initialized = true; } // Connect to WebSocket server return await sandbox.wsConnect(request, 8080); } ``` -------------------------------- ### Get or Create Sandbox Instance Source: https://developers.cloudflare.com/sandbox/api/lifecycle Retrieve an existing sandbox instance by ID or create a new one. The container starts lazily on the first operation. It's recommended to set `enableDefaultSession` to `false` for isolated operations. ```typescript import { getSandbox } from "@cloudflare/sandbox"; export default { async fetch(request, env) { const sandbox = getSandbox(env.Sandbox, "user-123"); const result = await sandbox.exec("python script.py"); return Response.json(result); }, }; ``` ```typescript import { getSandbox } from '@cloudflare/sandbox'; export default { async fetch(request: Request, env: Env): Promise { const sandbox = getSandbox(env.Sandbox, 'user-123'); const result = await sandbox.exec('python script.py'); return Response.json(result); } }; ``` -------------------------------- ### Create, Execute, and Destroy Sandbox (Python) Source: https://developers.cloudflare.com/sandbox/bridge/index.md Demonstrates the full lifecycle of a sandbox: creation, running a command, and destruction. Ensure SANDBOX_API_URL and SANDBOX_API_KEY environment variables are set. ```python import os import httpx API_URL = os.environ["SANDBOX_API_URL"] API_KEY = os.environ["SANDBOX_API_KEY"] headers = {"Authorization": f"Bearer {API_KEY}"} # Create a sandbox resp = httpx.post(f"{API_URL}/v1/sandbox", headers=headers) sandbox_id = resp.json()["id"] print(f"Sandbox ID: {sandbox_id}") # Run a command # Response is a text/event-stream with the following SSE events: # event: stdout — data is a base64-encoded output chunk # event: stderr — data is a base64-encoded error chunk # event: exit — data is JSON: {"exit_code": 0} # event: error — data is JSON: {"error": "...", "code": "..."} exec_resp = httpx.post( f"{API_URL}/v1/sandbox/{sandbox_id}/exec", headers=headers, json={ "argv": ["sh", "-lc", "echo hello from the sandbox"], "timeout_ms": 10000, }, ) print(exec_resp.text) # Destroy the sandbox when done httpx.delete(f"{API_URL}/v1/sandbox/{sandbox_id}", headers=headers) ``` -------------------------------- ### Expose a different port when 3000 is reserved (JavaScript) Source: https://developers.cloudflare.com/sandbox/llms-full.txt When port 3000 is reserved by the internal Bun server, use a different port like 8080. This example demonstrates starting a Node.js process with a custom port and then exposing it. ```javascript // Extract hostname from requestconst { hostname } = new URL(request.url); // ❌ This will failawait sandbox.exposePort(3000, { hostname }); // Error: Port 3000 is reserved // ✅ Use a different portawait sandbox.startProcess("node server.js", { env: { PORT: "8080" } });await sandbox.exposePort(8080, { hostname }); ``` -------------------------------- ### Run Application with Sandbox Binary and CMD Source: https://developers.cloudflare.com/sandbox/llms-full.txt Use this Dockerfile to copy your application code and run it using the sandbox binary as the entrypoint. The `CMD` instruction allows the sandbox to manage your application's startup command with signal forwarding. ```Dockerfile FROM node:20-slim COPY --from=docker.io/cloudflare/sandbox:0.7.0 /container-server/sandbox /sandbox # Copy your applicationCOPY . /appWORKDIR /app ENTRYPOINT ["/sandbox"] CMD ["node", "server.js"] ``` -------------------------------- ### Expose a local server port via tunnels Source: https://developers.cloudflare.com/sandbox/guides/2026-deprecation/index.md Replace exposePort() with the tunnels API. This example starts a Python HTTP server, waits for port 8080 to be available, and then creates a tunnel to expose it. Requires RPC transport. ```typescript import { getSandbox, } from "@cloudflare/sandbox"; const sandbox = getSandbox(env.Sandbox, "my-sandbox", { transport: "rpc", }); const server = await sandbox.startProcess("python -m http.server 8080"); await server.waitForPort(8080); const tunnel = await sandbox.tunnels.get(8080); return Response.json({ url: tunnel.url }); ``` -------------------------------- ### Create a new Sandbox SDK project with npm Source: https://developers.cloudflare.com/sandbox/tutorials/analyze-data-with-ai/index.md Use this command to initialize a new Cloudflare Sandbox SDK project with the minimal template using npm. ```bash npm create cloudflare@latest -- analyze-data --template=cloudflare/sandbox-sdk/examples/minimal ``` -------------------------------- ### Manage Sandbox Processes and Tunnels in a Worker (JavaScript) Source: https://developers.cloudflare.com/sandbox/api/tunnels/index.md This JavaScript code demonstrates how to use the Cloudflare Sandbox SDK within a Worker. It shows how to get or start a process, provision a tunnel to that process, and log the tunnel URL. It handles potential `PROCESS_ALREADY_EXISTS` errors. ```javascript import { getSandbox } from "@cloudflare/sandbox"; export { Sandbox } from "@cloudflare/sandbox"; export default { async fetch(request, env) { const sandbox = getSandbox(env.Sandbox, "my-sandbox"); // Reuse an existing app process across container restarts, or start it. let proc = await sandbox.getProcess("app"); if (!proc) { try { proc = await sandbox.startProcess("python -m http.server 8080", { processId: "app", }); } catch (err) { if (err?.code !== "PROCESS_ALREADY_EXISTS") throw err; proc = await sandbox.getProcess("app"); } } // Provision (or reuse) https://app.example.com pointing at port 8080. const tunnel = await sandbox.tunnels.get(8080, { name: "app" }); console.log(tunnel.url); // → https://app.example.com return Response.json({ url: tunnel.url }); }, }; ``` -------------------------------- ### Expose Port with TypeScript Source: https://developers.cloudflare.com/sandbox/llms-full.txt This TypeScript snippet mirrors the JavaScript example, demonstrating how to expose a port from a Cloudflare Sandbox. It starts a Python HTTP server, waits for it, exposes the port, and logs the URL. It also includes the `proxyToSandbox` functionality for handling existing exposed ports. ```typescript import { getSandbox, proxyToSandbox } from '@cloudflare/sandbox'; export { Sandbox } from '@cloudflare/sandbox'; export default { async fetch(request: Request, env: Env): Promise { // Proxy requests to exposed ports first const proxyResponse = await proxyToSandbox(request, env); if (proxyResponse) return proxyResponse; // Extract hostname from request const { hostname } = new URL(request.url); const sandbox = getSandbox(env.Sandbox, 'my-sandbox'); // 1. Start a web server await sandbox.startProcess('python -m http.server 8000'); // 2. Wait for service to start await new Promise(resolve => setTimeout(resolve, 2000)); // 3. Expose the port const exposed = await sandbox.exposePort(8000, { hostname }); // 4. Preview URL is now available (public by default) console.log('Server accessible at:', exposed.url); // Production: https://8000-abc123.yourdomain.com // Local dev: http://localhost:8787/... return Response.json({ url: exposed.url }); } }; ``` -------------------------------- ### Create, Execute, and Destroy Sandbox (Python) Source: https://developers.cloudflare.com/sandbox/bridge Provides a Python example using the httpx library to create a sandbox, run a command, and then destroy the sandbox. The command execution response is an event-stream. ```python # /// script # dependencies = ["httpx"] # /// import os import httpx API_URL = os.environ["SANDBOX_API_URL"] API_KEY = os.environ["SANDBOX_API_KEY"] headers = {"Authorization": f"Bearer {API_KEY}"} # Create a sandbox resp = httpx.post(f"{API_URL}/v1/sandbox", headers=headers) sandbox_id = resp.json()["id"] print(f"Sandbox ID: {sandbox_id}") # Run a command # Response is a text/event-stream with the following SSE events: # event: stdout — data is a base64-encoded output chunk # event: stderr — data is a base64-encoded output chunk # event: exit — data is JSON: {"exit_code": 0} # event: error — data is JSON: {"error": "...", "code": "..."} exec_resp = httpx.post( f"{API_URL}/v1/sandbox/{sandbox_id}/exec", headers=headers, json={ "argv": ["sh", "-lc", "echo hello from the sandbox"], "timeout_ms": 10000, }, ) print(exec_resp.text) # Destroy the sandbox when done httpx.delete(f"{API_URL}/v1/sandbox/{sandbox_id}", headers=headers) ``` -------------------------------- ### Expose Service Port with JavaScript Source: https://developers.cloudflare.com/sandbox/guides/expose-services This example demonstrates the typical workflow for exposing a service port. It starts a Python HTTP server, waits for it to become ready, exposes port 8000, and logs the accessible URL. Ensure your Dockerfile includes EXPOSE directives for local development. ```javascript import { getSandbox, proxyToSandbox } from "@cloudflare/sandbox"; export { Sandbox } from "@cloudflare/sandbox"; export default { async fetch(request, env) { // Proxy requests to exposed ports first const proxyResponse = await proxyToSandbox(request, env); if (proxyResponse) return proxyResponse; // Extract hostname from request const { hostname } = new URL(request.url); const sandbox = getSandbox(env.Sandbox, "my-sandbox"); // 1. Start a web server await sandbox.startProcess("python -m http.server 8000"); // 2. Wait for service to start await new Promise((resolve) => setTimeout(resolve, 2000)); // 3. Expose the port const exposed = await sandbox.exposePort(8000, { hostname }); // 4. Preview URL is now available (public by default) console.log("Server accessible at:", exposed.url); // Production: https://8000-abc123.yourdomain.com // Local dev: http://localhost:8787/... return Response.json({ url: exposed.url }); }, }; ``` -------------------------------- ### Get Sandbox Instance Source: https://developers.cloudflare.com/sandbox/configuration/sandbox-options Import and initialize the sandbox instance using `getSandbox()`. This sets up the basic sandbox environment. ```javascript import { getSandbox } from '@cloudflare/sandbox'; const sandbox = getSandbox(binding, sandboxId, options?: SandboxOptions); ```