Simon Willison highlights a clean pattern for giving Pyodide real, durable storage using the browser’s Origin Private File System (OPFS). Here’s why it matters and how to put it to work. Source: simonwillison.net.
Why OPFS matters for Pyodide
- Durable, fast, private: OPFS stores data per-origin, off the network, and is designed for speed with low-latency sync handles.
- Zero backend: Ship Python-powered apps (Pyodide) that save files and databases locally—great for demos, courses, and PWAs.
- Offline-first: Works without connectivity and survives reloads, making in-browser notebooks and tools feel native.
Quick setup pattern
- Load Pyodide (ideally in a Web Worker for responsiveness).
- Request OPFS root:
const root = await navigator.storage.getDirectory(). Mount it to the Emscripten file system used by Pyodide at a path like/opfs(see Pyodide FS docs linked below for mounting patterns). - Read/write from Python as usual. Example:
from pathlib import Path; Path('/opfs/hello.txt').write_text('hi'); print(Path('/opfs/hello.txt').read_text()). - Reduce eviction risk:
await navigator.storage.persist()to request persistent storage.
Once mounted, anything under /opfs persists across reloads—perfect for user projects, cacheable datasets, or even a local SQLite database.
Browser support and fallbacks
OPFS has strongest support in Chromium-based browsers, with other engines evolving. Check current status and APIs on MDN’s File System Access API docs.
No OPFS? Consider fallbacks: IndexedDB-backed storage or asking users to choose a folder via the File System Access API and mounting it in Pyodide (see Pyodide’s filesystem guide for mountNativeFS).
Great use cases
- In-browser notebooks and coding lessons with autosave.
- AI agent playgrounds that keep memory client-side.
- PWAs that cache models, embeddings, or datasets locally.
- Data apps using SQLite WASM stored in OPFS (see SQLite’s persistence notes).
Tips and gotchas
- Run Pyodide in a Worker for smoother UI—file I/O and Python execution won’t block the main thread.
- Design for quotas: request
storage.persist(), stream or chunk large files, and surface clear error states. - Privacy by design: OPFS is origin-scoped and not user-visible in the OS—great for safety, but add export/import features if users need portability.
Takeaway
Pyodide + OPFS turns the browser into a real Python runtime with durable storage—no server, no signup, just instant, private, offline-ready apps.
Get more practical AI and dev nuggets—subscribe to our free newsletter: theainuggets.com/newsletter.

