Static vs Interactive Matplotlib in Jupyter: Choosing the Right %matplotlib Mode
Choose between %matplotlib inline and %matplotlib widget in Jupyter. Learn how the backends differ, what ipympl requires, and how to verify interactive plotting works.
07 Sept 2025, 21:37 UTC

The decision: static inline or interactive widget
You run plt.plot(...) in a notebook and either get a frozen image or a blank cell with a JavaScript error. The %matplotlib magic controls this, but choosing the wrong mode—or enabling it without the right packages—leaves you stuck.
Use %matplotlib inline for static, reproducible plots that render as PNG or SVG. Use %matplotlib widget when you need pan, zoom, and tooltips in the browser. Widget mode requires the ipympl package and a compatible browser-based frontend such as JupyterLab or classic Notebook.
What the magic actually does
The %matplotlib magic calls matplotlib.use() behind the scenes, swapping the active backend. A backend is the layer that translates figure drawing commands into visible output.
inline selects the Agg canvas. Agg rasterizes the figure and passes it to IPython's display formatters, which embed a static PNG or SVG directly in the notebook output cell. Nothing remains interactive after rendering.
widget activates ipympl's backend_nbagg. This keeps the figure alive in the Python kernel and synchronizes its state to the browser over Jupyter comm messages—bidirectional channels between kernel and frontend. Because the figure object persists, the browser can send mouse events back to update the view.
Worked example: enabling widget mode
Run the following in a notebook cell. You need ipympl installed in the same kernel environment as matplotlib. If it is not installed, run pip install ipympl in the terminal that manages your kernel environment, or use !pip install ipympl inside a notebook cell. Use a virtual environment or the --user flag if you lack system-level write permissions.
%matplotlib widget
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.plot([1, 2, 3])
plt.show()
If ipympl is missing, the backend may fall back silently or raise an error. Verify the installation and the active backend immediately after the magic:
import matplotlib
matplotlib.get_backend()
Expected check: for widget mode, the returned string should reference ipympl or nbagg. For inline mode, it should reference agg. To confirm the package is present in the active kernel, run !pip show ipympl in a notebook cell, or pip show ipympl in the terminal used to launch the kernel.
Limits and common mistakes
Inline mode is intentionally static. It produces no zoom controls, no tooltips, and no live updates. Widget mode adds latency and memory overhead because every figure maintains a live kernel object and a comm channel; large datasets can make the browser tab sluggish.
The legacy %matplotlib notebook magic behaves inconsistently across classic Notebook and JupyterLab versions. Prefer inline or widget instead.
- Missing
ipympl: Installingmatplotlibalone does not provide widget mode. Installipymplexplicitly, and ensure its version is compatible with your installed JupyterLab major version. - Calling the magic too late: Run
%matplotlibbefore creating figures. Figures created under a different backend may not switch cleanly when the magic runs afterward. - Assuming inline is interactive: Inline output is a static image. If you need interactivity, switch to widget mode or export to a separate interactive tool.
- Non-browser frontends: Widget mode requires a browser-based frontend. It will not work in
jupyter consoleor other terminal-based interfaces. - Mixing backend calls: Do not combine
%matplotlibwith manualmatplotlib.use()in the same session. Conflicting backend switches can leave the figure manager in an undefined state.
Checking the result
After configuring widget mode, confirm the backend string with matplotlib.get_backend(). Check jupyter --version and the JupyterLab extension list to confirm frontend compatibility, then open the notebook in both classic Notebook and JupyterLab to compare rendering; extension requirements differ between the two frontends.
In headless containers, interactive backends may fail without a virtual framebuffer such as xvfb. If the cell hangs or the widget area stays blank, check that ipympl is installed, that the frontend is browser-based, and that the backend string matches your intended mode.
To return to static output, run %matplotlib inline in a new cell. This changes the backend for subsequent figures; existing static images remain unchanged.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.