# How to switch from E2B to Runtime by changing one import Replace `from "e2b"` with `from "withruntime/e2b"` (Python: `from withruntime.e2b import Sandbox`) and set `RUNTIME_API_KEY`. **Code written for E2B's SDK runs on Runtime unchanged, apart from the import. The same job costs 77% less.** 1,000 one-minute runs of a 2 vCPU, 4 GiB sandbox cost $0.64 on Runtime, against $2.76 at E2B's published rates, checked 25 October 2026 ([Runtime vs E2B](/docs/e2b-alternative)). Both run each sandbox in a Firecracker microVM with its own kernel. The isolation model is the same kind. ## The change ```bash no-run npm install withruntime # 0.11.2 or later; or: pip install withruntime (0.11.1 or later) ``` ```ts no-run import { Sandbox } from "withruntime/e2b"; // was: from "e2b" ``` ```python no-run from withruntime.e2b import Sandbox # was: from e2b import Sandbox ``` E2B's code interpreter package changes the same way: `withruntime/e2b/code-interpreter` in JavaScript and `withruntime.e2b.code_interpreter` in Python. Then give the process a key. Locally, any `npx withruntime` command connects the machine with one browser approval, and the SDK finds that connection by itself. On a server or in CI, set `RUNTIME_API_KEY` from your secret manager. Create a key at [API keys](https://withruntime.com/account/keys), or run `npx withruntime keys create --name app`. ## Test it without credit first While you test, run the work on free usage so that no paid credit is used: ```ts check import { Sandbox } from "withruntime/e2b"; const sbx = await Sandbox.create(); const result = await sbx.commands.run("python3 -c 'print(sum([125, 250, 375]))'"); console.log(result.stdout); await sbx.kill(); ``` ```python check from withruntime.e2b import Sandbox sbx = Sandbox.create() print(sbx.commands.run("python3 -c 'print(sum([125, 250, 375]))'").stdout) sbx.kill() ``` ## What stays the same | E2B behavior | Under `withruntime/e2b` | | ---------------------- | --------------------------------------------------------------- | | Default size | 2 vCPU, 512 MiB | | A `timeoutMs` you give | Up to 24 hours, kept by the server; then the sandbox is deleted | | `kill()` | Deletes the sandbox for good | | `commands.run` output | The whole output, returned | | Non-zero exit | Throws `CommandExitError`, as E2B does | | `getMetrics()` | CPU and memory from Runtime's readings; `diskUsed` is null | | Code interpreter | The drop-in packages above | | Billing | Free usage first, then prepaid credit | One thing differs on purpose. With no timeout, E2B deletes a sandbox after 300 seconds. Runtime pauses it instead, and keeps its memory and files as [paused storage](/docs/pricing#paused-storage) until you call `kill()`. ## What throws, and why that is safe A call that Runtime handles differently, such as workload identity, throws `NotSupportedError` before anything happens. The message names what to use instead, so nothing runs partway. `E2B.md` in the package lists every mapping. Two common replacements: - **Templates** become [custom images](/docs/images) of the same name. Build your `e2b.Dockerfile` once with `npx withruntime images build --dockerfile e2b.Dockerfile --name