Experimental:
pyobservablejsis experimental software. Its API may change between releases.
pyobservablejs embeds reactive Observable notebooks in Python. A notebook can
combine JavaScript, Observable JavaScript, Markdown, HTML, inputs, files, and
browser libraries, then render as an anywidget in JupyterLab, marimo, VS Code
notebooks, Google Colab, and other anywidget hosts.
Python constructs the notebook and owns shared values. Notebook Kit runs each view in the browser, where inputs rerun dependent cells and structured results can return to Python.
An authored notebook with an interactive filter and plot
Install and render a notebook
Add pyobservablejs to a Python 3.11 through 3.14 environment:
uv pip install pyobservablejs
Or open a temporary marimo environment with the package available:
uvx --with pyobservablejs marimo edit notebook.py
Create a notebook with a heading, browser input, and reactive Markdown:
import observablejs as obs
notebook = obs.Notebook(
obs.md("## Threshold report"),
obs.js(
"""
const threshold = view(Inputs.range(
[0, 1],
{value: 0.5, step: 0.1, label: "Threshold"}
));
""",
key="threshold_control",
),
obs.js(
"md`Current threshold: **${threshold}**`",
key="summary",
),
)
view = notebook.view()
view
The view renders the heading, slider, and current value. Moving the slider
reruns the summary in the browser. Each cell key is its public identity, so
notebook.view("summary") creates a focused view and evaluates its dependencies
with their output hidden.
Update the same input from Python while the view stays mounted:
notebook.update_variables({"threshold": 0.8})
Work with notebooks
| Task | Documentation |
|---|---|
| Author JavaScript, Observable JavaScript, Markdown, and HTML cells | Author notebook cells |
| Load Notebook Kit HTML or a public ObservableHQ notebook | Create notebooks |
| Display a whole notebook or selected keyed cells | Display views |
| Send Python values and read browser results | Connect Python and Observable |
| Register files or embed local JavaScript modules | Add files and local modules |
| Inspect cell results, errors, and dependencies | Read browser results and inspect dependencies |
Views from one Notebook receive the same Python variables and supported
browser input values. Each view keeps its own browser runtime, rendered output,
results, errors, dependency graph, and lifecycle.
Python and browser values updating one notebook
Use with notebook agents
The pyobservablejs wheel carries an Agent Skill that matches its Python API.
Any Python process can use observablejs.agent to locate the packaged
instructions:
import observablejs.agent as observablejs_agent
print(observablejs_agent.agent_skill() / "SKILL.md")
See Use pyobservablejs with agents for installed resources, LLM-readable documentation, and the optional marimo code-mode path through marimo pair.
Import a notebook
Notebook cells execute as JavaScript in the host page. Treat imported Notebook Kit HTML, ObservableHQ notebooks, and remote modules as trusted code. See Browser execution and network access.
import observablejs as obs
notebook = obs.Notebook.from_observablehq("@d3/world-tour")
notebook.view()
An imported ObservableHQ notebook
Learn more
Start with the quickstart, then use complete examples, troubleshooting, or the API reference for the next task.
Acknowledgements
Thanks to the Observable team for Notebook
Kit, which provides the notebook
format and runtime. pyobsplot informed
the Python variable API. Trevor Manz's anywidget
composition demo shaped the shared-session design.
License
MIT