Choosing a Matplotlib Graphics Backend in Spyder: Inline vs. Qt vs. Agg
A decision guide for picking one Matplotlib backend per Spyder console—Inline, interactive Qt, or headless Agg—based on interactivity, reproducibility, and remote use.
23 Sept 2026, 12:00 UTC

The problem: one console, one backend
If you use Spyder for scientific Python work, the Matplotlib graphics backend decides where your figures appear and how much interaction you get. Mixing backends inside a single console—or assuming a script will behave the same on a remote server as it does on your laptop—creates confusing failures. The useful takeaway is simple: choose one backend per Spyder console and make the choice explicit.
Constraints that drive the decision
Before opening Preferences, answer four questions:
- Interactivity: Do you need to zoom, pan, or rotate figures live during exploration?
- Embedding: Must figures appear inside Spyder's Plots pane so they are captured with the notebook-like console history?
- Environment: Does the kernel run headless (no display) or over SSH without X forwarding?
- Automation: Will the same script run unchanged in CI or on a server where no window can open?
Supported options compared
Spyder exposes several backends through its IPython console settings. The table below summarizes the practical differences.
| Backend | Where figures appear | Interaction | Best for | Main limitation |
|---|---|---|---|---|
| Inline | Spyder Plots pane | Static images; limited zoom/pan | Reproducible reports, sharing, headless kernels | No live GUI callbacks; images accumulate |
| Qt5Agg / Qt6Agg | Separate OS window | Full zoom, pan, rotate | Interactive data exploration | Requires a display and Qt bindings; breaks over SSH without X forwarding |
| Agg | No window; files only | None on screen | CI, batch jobs, headless servers | No visual feedback during development |
| Automatic | Depends on installed packages | Varies | Quick local trials | Least predictable; can change when packages update |
Trade-offs in practice
Inline favors reproducibility
The Inline backend embeds figures as static images in the Plots pane. This makes the console history self-contained and easy to share. The cost is that GUI-event-driven callbacks—such as a matplotlib.widgets.Slider—will not behave the same as they do in a native Qt window. If you rely on live widgets, Inline is the wrong tool for that session.
Interactive Qt favors exploration
Qt5Agg or Qt6Agg opens a native window with the full Matplotlib navigation toolbar. This is ideal when you are probing a dataset and need to inspect outliers visually. However, the backend requires both a display server and compatible Qt bindings (PyQt or PySide). Over a plain SSH session, attempting to create a figure can fail with a display-related error. If you must use Qt remotely, X forwarding has to be configured first.
Agg is safest for automation
The Agg backend renders to memory or disk without opening any window. It is the standard choice for scripts that run in CI pipelines, Docker containers, or remote batch queues. Because there is no on-screen window, you get no visual confirmation that a plot looks correct until you open the saved file.
Setting the default in Spyder
To make a choice persist across new consoles, set the global default. These steps modify user-level IDE settings and require no elevated system permissions.
- Open
Preferencesfrom the Spyder menu. - Navigate to
IPython console>Graphics. - Under
Graphics backend, selectInlineor an interactive Qt backend. - Restart the kernel or open a new console.
The exact list of available Qt backends depends on which Qt bindings are installed and on your Spyder and spyder-kernels versions. Do not hard-code a backend name in shared scripts; let the environment or Spyder preferences decide.
Overriding per session
You can change the backend for the current console without editing Preferences. Run these IPython magics directly in the Spyder IPython console:
%matplotlib inline
%matplotlib qt
%matplotlib qt6
%matplotlib agg
In a plain Python script that must run headless, call matplotlib.use() before importing pyplot:
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
Risk: Switching backends after matplotlib.pyplot has already been imported may not take effect until the kernel is restarted. The force=True argument to matplotlib.use() is version-sensitive and should be avoided in shared code.
Validating the active backend
To confirm which backend a console is actually using, run the following in the Spyder IPython console:
import matplotlib
print(matplotlib.get_backend())
Expected checks:
- If you selected Inline, the returned string typically contains
matplotlib_inline(for example,module://matplotlib_inline.backend_inline). - If you selected Qt, it should report
Qt5AggorQt6Aggdepending on your bindings. - If you selected Agg, it should report
Agg.
Then create a minimal figure and observe where it lands:
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.plot([0, 1], [0, 1])
plt.show()
With Inline, the figure should appear in the Plots pane. With Qt, a separate OS window should open. With Agg, no window appears; instead, save the figure explicitly with fig.savefig('check.png') and open the file.
Finally, start a fresh kernel and run matplotlib.get_backend() again. The result should match the default you set in Preferences, confirming the setting persists.
Limitations and version notes
- Backend availability is not guaranteed across environments. A script that works with Qt on a workstation may fail on a headless CI runner.
- Inline images are static by default; interactive widgets and animations behave differently than in a Qt window.
- The
Automaticoption can silently change when you install or upgrade packages, so it is unsuitable for reproducible pipelines. - Because Spyder delegates graphics handling to
spyder-kernelsand Matplotlib, behavior can shift across major version upgrades. Verify the backend after updating either component.
Rolling back a change
If you change the Preferences default and later want to revert, return to Preferences > IPython console > Graphics, select the previous backend, and restart the kernel. If you used a magic command in the console, restarting the kernel clears the override and restores the Preferences default.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.