# Pyodide vs a server sandbox: can Pyodide run pip packages? Pyodide installs pure-Python wheels and packages built for it, without threads or subprocesses; a server sandbox runs any pip package. **A Runtime sandbox runs ordinary CPython on a real Linux machine, so `pip install` works for any wheel on PyPI, native extensions included.** A new sandbox ran its first Python command 351 ms after the create request at the median, over the public internet, on 24 September 2026 ([speed](/docs/speed)). ## What Pyodide is Pyodide is "a Python distribution for the browser and Node.js based on WebAssembly": CPython compiled to WebAssembly with Emscripten. Version 314.0.0, released 9 June 2026, moved it to Python 3.14.2; the current release on 25 September 2026 is 314.0.7, from 14 September 2026. When it runs in a browser, the project says, "Python has full access to the Web APIs." It is a good fit for Python that should run on the user's own device: notebooks in the browser, teaching tools, and data work where the data never leaves the page. ## Can Pyodide run pip packages? Some of them. Pyodide installs packages with `micropip`, and after Pyodide loads "only the Python standard library is available." `micropip` installs: - **Pure-Python wheels from PyPI.** The home page says "any pure Python package with a wheel available on PyPi is supported." A wheel ending in `py3-none-any.whl` is the sign. - **Packages built for Pyodide**, the wasm32 Emscripten wheels. The project has ported many packages with C, C++ and Rust extensions. Its list for the current release includes NumPy 2.4.6, pandas 3.0.2, SciPy 1.18.0, Matplotlib 3.10.8, scikit-learn 1.8.0, DuckDB 1.5.1 and lxml 6.1.3. Anything else fails. The FAQ says a package with "binary extensions (e.g. C, Fortran or Rust)" that nobody has built for Pyodide "needs to be cross-compiled for Pyodide." A wheel fetched from your own server needs CORS headers, or the browser blocks it. ## What else does not work in Pyodide? From Pyodide's own pages on WebAssembly constraints and its FAQ: - **No threads, processes or subprocesses.** "Fork and pthreads do not work in Pyodide." Starting a thread, a `multiprocessing` worker or a `subprocess` raises `RuntimeError`. Code that calls `git`, `ffmpeg` or a compiler cannot run. - **Sockets, only experimentally, and only in Node.js.** "By default, Pyodide does not support sockets in the browser." Node.js can enable an experimental socket API with `useNodeSockFS()`. - **HTTP through the browser.** Requests are "subject to the same limitations as any JavaScript network call": "very little or no control over certificates, timeouts, proxies", and CORS can block them. - **Missing standard modules.** `venv`, `ensurepip`, `termios`, `tkinter`, `curses`, `fcntl`, `resource` and others are removed; `ssl` is "a stub implementation that does not use OpenSSL." ## Side by side | | Pyodide | Runtime sandbox | | ------------------- | ---------------------------------------------------- | --------------------------------------------------------------- | | Where it runs | The user's browser, or Node.js | A Firecracker microVM on Runtime's servers | | Python | CPython 3.14.2 compiled to WebAssembly | CPython 3.12 on Ubuntu 24.04 | | Packages | Pure-Python wheels and Pyodide-built packages | Any `pip`, `uv` or `apt` package | | Native extensions | Only if cross-compiled for Pyodide | Install as on any Linux machine | | Threads, subprocess | `RuntimeError` | Normal Linux processes and threads | | Sockets | Browser: none. Node.js: experimental | Any public host, narrowed by allow and deny lists | | Other languages | Python, with a JavaScript bridge | Node.js, Bun, gcc; interpreter runs Python, JS, TS, R, Java, Go | | Isolation | The browser tab or Node process; full Web API access | A kernel per sandbox; network, CPU and cost set on the host | | Cost | Runs on the user's device | $0.025 per active vCPU-hour, $0.0075 per GiB-hour | ## Is Pyodide safe for untrusted code? It depends where it runs. In a browser, Pyodide code runs in the page with "full access to the Web APIs", so model-written code shares the page's origin and whatever the page can reach. In Node.js, it runs inside your server's process. A server sandbox keeps the code off your machines and your users' pages entirely. ## When each fits - **Pick Pyodide** when the code should run on the user's device: a browser notebook, a teaching exercise, a chart from data the user dropped in, with pure-Python or already-ported packages. - **Pick a server sandbox** when the code comes from a model or an agent and may need any package, a subprocess, a compiler, a database driver, the network or more memory than a browser tab, or must not run where your users' sessions live. ## Run the same Python in a Runtime sandbox Allow the package index, install what the code needs, then switch the network off before the model's code runs: ```ts check import { Sandbox } from "withruntime"; await using sbx = await Sandbox.create({ network: { internet: true, allow: ["pypi.org", "*.pythonhosted.org"] }, timeoutSeconds: 600, onLeaseEnd: "stop", }); await sbx.exec("pip install polars", { check: true, timeoutMs: 180_000 }); await sbx.network.set({ internet: false }); const run = await sbx.exec([ "python3", "-c", "import polars, subprocess; print(polars.__version__, subprocess.run(['nproc'], capture_output=True, text=True).stdout)", ]); console.log(run.stdout); ``` ```python check from withruntime import Sandbox with Sandbox.create( network={"internet": True, "allow": ["pypi.org", "*.pythonhosted.org"]}, timeout_seconds=600, on_lease_end="stop", ) as sbx: sbx.exec("pip install polars", check=True, timeout_ms=180_000) sbx.network.set(internet=False) run = sbx.exec([ "python3", "-c", "import polars, subprocess; print(polars.__version__, subprocess.run(['nproc'], capture_output=True, text=True).stdout)", ]) print(run.stdout) ``` For a chat that runs Python turn after turn, the code interpreter keeps variables between cells and returns charts as PNG and data frames as tables ([code interpreter for chatbots](/use-cases/code-interpreter-for-chatbots)). NumPy, pandas and matplotlib are in the default image. New accounts get 50 free sandbox hours, no card: ```bash no-run npx withruntime sandbox run --trial -- python3 -c 'import pandas; print(pandas.__version__)' ``` More: [WebAssembly vs microVM](/compare/webassembly-vs-microvm), [what is a code interpreter?](/glossary/code-interpreter), [data analysis agent](/use-cases/data-analysis-agent), [Python SDK](/docs/python). ## Sources Checked 25 September 2026. - [Pyodide](https://pyodide.org/en/stable/), [changelog](https://pyodide.org/en/stable/project/changelog.html), [loading packages](https://pyodide.org/en/stable/usage/loading-packages.html), [packages built in Pyodide](https://pyodide.org/en/stable/usage/packages-in-pyodide.html) - [WebAssembly constraints](https://pyodide.org/en/stable/usage/wasm-constraints.html), [FAQ](https://pyodide.org/en/stable/usage/faq.html), [using sockets](https://pyodide.org/en/stable/usage/socket.html) Facts on this page were checked on 25 September 2026.