The coding playground on this blog just got a new language: Python!
I've always liked the idea of being able to experiment with code while reading about it. Code examples are much more useful when you can tweak and run them right alongside the explanation. That's why I built the coding playground into this blog in the first place.
It started with JavaScript and TypeScript, and now supports Python too. The best part? Everything still runs entirely in your browser, thanks to Pyodide. No server, no setup, just code you can play around with.
# Updated controls
The playground previously ran snippets automatically, but Python adds a startup cost. Before the first snippet can run, Pyodide needs to load and initialize CPython and its standard library. The core runtime assets total about 13.5 MB before HTTP compression, excluding external packages. I added an option to disable auto-run and a dedicated run button to control when the runtime loads and the code executes.
The run button shows three states: idle, initializing while the runtime is prepared, and running with an animated progress ring while the code executes.
Auto-run is still available for small examples and can be toggled in each playground, keeping the same edit-and-run workflow as the existing JavaScript and TypeScript examples.
Reset restores the original example and starts a fresh worker. It also provides a way to recover when code gets stuck in an infinite loop.
# Multi-file Python example
main.py is the entry point, regardless of which
file is open in the editor. Project files can import from one another,
just as in a local Python project.
# Python runtime
This playground uses Pyodide 314.0.7, which bundles CPython 3.14.2.
Each Pyodide release ships a specific Python version, so choosing
the runtime also determines which Python features are available. The
interpreter version is available through
sys.version:
These releases illustrate how the bundled Python version has
changed. The exact versions come from each release's
pyodide-lock.json runtime metadata:
| Pyodide release | Bundled Python |
|---|---|
| 0.24.1 | 3.11.3 |
| 0.25.1 | 3.11.3 |
| 0.26.4 | 3.12.1 |
| 0.27.8 | 3.12.7 |
| 0.28.3 | 3.13.2 |
| 0.29.5 | 3.13.2 |
| 314.0.7 | 3.14.2 |
Why the jump from 0.29 to 314.0? On June 9, 2026, Pyodide introduced a new versioning scheme with the release of 314.0.0. The major version now reflects the bundled Python version: Pyodide 314.x corresponds to Python 3.14.
Alongside this change, Pyodide aligned binary compatibility with Python releases as part of the packaging standardization in PEP 783. Compiled packages targeting the same Python version can work across multiple Pyodide releases without needing a rebuild for each one.
# Package support
The playground also supports external libraries. Pure-Python packages generally work as long as they do not rely on unsupported system features. Libraries with native extensions, such as NumPy, need WebAssembly-compatible builds, which Pyodide provides for supported packages. Wheels built for desktop platforms will not work in the browser.
Before each run, the worker calls
loadPackagesFromImports to scan imports across
all Python project files and load matching packages on demand. Once loaded,
a package remains available in that worker. The example below demonstrates
this with NumPy.
# Capabilities and limitations
Pyodide runs real CPython, but it does not provide a full desktop
environment. Functions, classes, decorators, data classes, and
pattern matching work normally. The playground also supports
top-level await through Pyodide's asynchronous
execution API. The main limitations are access to operating-system services
and browser resources.
- Processes and threads: browser-based Pyodide cannot
launch local programs or start processes with
multiprocessing. Python threading viathreading.Threadis not supported in Pyodide. - Networking: HTTP requests use browser networking and follow CORS rules. Opening arbitrary TCP or UDP sockets or listening on a port is not supported. HTTPS is handled by the browser.
- Files:
open()works against a virtual filesystem by default. Access to local files requires explicit browser integration and permission. Persistent storage also needs to be configured. - Desktop and terminal libraries: libraries such as
tkinterandcursesare unavailable.
Asynchronous Python code works through Pyodide's integration with the JavaScript event loop. Runtime downloads, startup time, and browser memory limits are also worth keeping in mind.
Pyodide's Python compatibility documentation provides the full list of limitations.
# What's next
There are still a few things I'd like to improve, such as better error messages and support for interactive input. But for now, I'm pretty happy with how the Python integration turned out.
I'll also be publishing a follow-up post soon with a more technical deep dive into the Pyodide integration and some of the challenges along the way.
In the meantime, feel free to play around with the examples above!