# 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, and 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 23 September 2026 ([Runtime vs E2B](/docs/e2b-alternative)). Both run each sandbox in a Firecracker microVM with its own kernel, so isolation is the same kind. ## The change ```bash no-run npm install withruntime # or: pip install withruntime (0.4.0 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 swaps 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: make one at [API keys](https://withruntime.com/account/keys) or with `npx withruntime keys create --name app`. ## Test it on the free trial first While you test, keep the work on the 50 free trial hours so nothing touches paid credit: ```ts check import { Sandbox } from "withruntime/e2b"; const sbx = await Sandbox.create({ runtime: { create: { funding: "trial" } } }); const result = await sbx.commands.run("python3 -c 'print(6 * 7)'"); console.log(result.stdout); await sbx.kill(); ``` ```python check from withruntime.e2b import Sandbox sbx = Sandbox.create(runtime_create={"funding": "trial"}) print(sbx.commands.run("python3 -c 'print(6 * 7)'").stdout) sbx.kill() ``` Remove the `funding` option when you go live, once credit is on the account. ## What stays the same | E2B behaviour | Under `withruntime/e2b` | | --------------------- | ---------------------------------------------------------- | | Default size | 2 vCPU, 512 MiB | | Default timeout | 300 seconds, after which the sandbox stops | | `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 | Trial time while the account has it, then prepaid credit | ## What throws, and why that is safe A call Runtime handles differently, such as E2B templates, workload identity or a single lease over an hour, throws `NotSupportedError` before anything happens, and the message names what to use instead, so nothing half-runs. `E2B.md` in the package lists every mapping. Two common replacements: - **Templates** become [custom images](/docs/images): a package list, any public or private image, or a Dockerfile, built once. - **Sessions over an hour** become a lease you extend, or `persistent: true` on a paid account, which renews itself while credit lasts. ## When to port to Runtime's own calls The import keeps your code running today. Moving to `withruntime` itself opens what E2B's API has no call for: `exec` that returns `exitCode` instead of throwing, forks of a running sandbox with its memory, network allow lists set on the host, secrets the sandbox never sees, and `idlePauseSeconds`. The calls map one to one ([migration](/docs/migrate#map-the-calls)): ```ts check import { Sandbox } from "withruntime"; const box = await Sandbox.create({ funding: "trial" }); try { console.log((await box.exec("python3 -c 'print(6 * 7)'", { check: true })).stdout); } finally { await box.stop(); } ``` ## Mistakes and how Runtime handles them - **An SDK older than 0.4.0.** The `withruntime/e2b` entry point arrived in 0.4.0. Upgrade the package. - **Keeping only the E2B key.** Runtime needs its own: set `RUNTIME_API_KEY`, or rely on the machine's saved connection. - **Relying on sandboxes that pause forever.** A paused Runtime sandbox is kept for the retention you set, up to 365 days on a paid account, 30 by default. - **Forgetting the switching credit.** Before your first top-up, run `npx withruntime switch --from e2b`; that top-up is matched with credit, up to $100. Then check the saving on your own runs with `runtime compare --from e2b` ([how to compare your costs](/how-to/compare-your-costs)). ## Related - [E2B alternatives](/compare/e2b-alternatives) and [E2B vs Daytona](/compare/e2b-vs-daytona) - [E2B pricing calculator](/calculators/e2b-pricing-calculator) - [JavaScript SDK](/docs/javascript#coming-from-e2b-daytona-or-vercel-sandbox) and [Python SDK](/docs/python#coming-from-e2b-daytona-or-vercel-sandbox) ## Sources - [E2B pricing](https://e2b.dev/pricing), checked 23 September 2026 Facts on this page were checked on 25 September 2026.