Pyodide 314.0: Publish WebAssembly Wheels to PyPI via PEP 783
Pyodide 314.0 is out, and it's a big deal for Python-in-the-browser. The headline feature: PEP 783 is now accepted, meaning Python package maintainers can publish WebAssembly (Wasm) wheels directly to PyPI. No more relying on the Pyodide team to build and host over 300 packages. This shifts the burden from a central team to the community, where it belongs.
PEP 783: What Changed
PEP 783 defines the "PyEmscripten" platform for Python wheels. With its acceptance, platform tags now use pyemscripten_* prefixes: pyemscripten_2025_0 for Python 3.13 (Pyodide 0.29.x) and pyemscripten_2026_0 for Python 3.14 (Pyodide 314.x).
cibuildwheel v4.0 already supports building for these ABIs. You can start building today. If you target the 2026 ABI (prerelease), enable it via pyodide-prerelease option; stable support will land in cibuildwheel v4.1.0 soon.
New Versioning Scheme
Pyodide's version now matches the Python version it ships. So 314.0 corresponds to Python 3.14. This stabilizes platform compatibility: binary-incompatible changes only happen when Python updates (annually). You can reuse packages across Pyodide releases targeting the same Python version. This release ships Python 3.14.2 and Emscripten 5.0.3.
Standard Library Changes
Pyodide previously "unvendored" ssl, sqlite3, and lzma to reduce download size. Now they're restored to the standard library for a better user experience. This increases initial download size but removes the need for separate await pyodide.loadPackage("sqlite3") calls. The pydecimal and test packages are removed; fullstdlib option in loadPyodide() is deprecated and has no effect.
OpenSSL is dropped entirely. The ssl module now uses a custom implementation without actual SSL/TLS support (not that it worked before in the browser). hashlib loses some cryptographic hash functions that depended on OpenSSL.
On the plus side, Python 3.14's compression.zstd module is available out of the box.
ES Module Native Support
pyodide.asm.js is now pyodide.asm.mjs, a proper ES module. Classic workers are no longer supported; you must use module workers (type: "module"). Service workers must import createPyodideModule from the .mjs file and pass it to loadPyodide. Update bundler configs accordingly.
Experimental Node.js Socket Support
You can now use TCP sockets in Pyodide running on Node.js. Call await pyodide.useNodeSockFS() to enable. Tested with pymysql, pg8000, and redis-py. On Node.js <= v24, pass --experimental-wasm-stack-switching for JSPI.
JavaScript Interop Improvements
- JsBigInt: JavaScript
bigintvalues now roundtrip correctly through Python without losing precision. Python integers > 2^53 also convert toJsBigInt. - Resource Management: PyProxy and PyBufferView implement
[Symbol.dispose], so you can useusingin JavaScript. Conversely, JS objects with[Symbol.dispose]work as Python context managers withwith. - Array-like Support: Any JS object that is iterable and has a
lengthproperty now supports subscript access (proxy[i]) and slice notation (proxy[1:4]).
What You Should Do Now
If you maintain a Python package, check the Pyodide build guide and Victorien Plot's article on building PyEmscripten wheels. Start publishing Wasm wheels to PyPI. If you use Pyodide, update to 314.0 and adjust your code for the ES module changes. Test your standard library usage—you might be able to drop explicit loadPackage calls.
The future of Python in the browser just got a lot more open.

