Matplotlib can draw figures through desktop windows or through file-only renderers. Headless scripts need a file-rendering backend so scheduled jobs, SSH sessions, CI workers, and containers can save plots without trying to open a GUI window.
The Agg backend renders PNG output without a display server. Select it before importing matplotlib.pyplot, because pyplot initializes the backend when it creates figures or connects to a plotting session.
Use a script-level backend selection when the script always runs without a desktop. MPLBACKEND can override the backend for one launch, but avoid putting it in shell startup files because it overrides local matplotlibrc choices and can surprise interactive sessions.
Related: How to save a Matplotlib figure
Related: How to set an interactive Matplotlib backend
Steps to set Matplotlib backend for headless scripts:
- Add the Agg backend selection before importing matplotlib.pyplot.
- headless_plot.py
from pathlib import Path import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt output = Path("headless-plot.png") fig, ax = plt.subplots(layout="constrained") ax.plot([1, 2, 3, 4], [2, 4, 3, 5], marker="o") ax.set_title("Headless Matplotlib") ax.set_xlabel("Run") ax.set_ylabel("Value") fig.savefig(output, dpi=150) plt.close(fig) print(f"backend: {matplotlib.get_backend()}") print(f"saved: {output.name}") print(f"bytes: {output.stat().st_size}")
Call matplotlib.use(“Agg”) before any pyplot import or figure creation. If the backend has already been initialized, Matplotlib may fail to switch or raise an import error.
- Run the script from the same Python environment used by the scheduled job or CI worker.
$ python headless_plot.py backend: Agg saved: headless-plot.png bytes: 44494
For an uneditable script, run one launch with MPLBACKEND=Agg python existing_plot.py. The environment variable overrides matplotlibrc backend settings for that process, so avoid exporting it globally unless every Matplotlib process in that account should use Agg.
- Verify that the saved plot file exists.
$ python - <<'PY' from pathlib import Path path = Path("headless-plot.png") print(f"verified: {path.name} exists={path.is_file()} size={path.stat().st_size}") PY verified: headless-plot.png exists=True size=44494 - Remove the smoke-test files if they are not part of your project.
$ rm headless_plot.py headless-plot.png
Mohd Shakir Zakaria is a cloud architect with deep roots in software development and open-source advocacy. Certified in AWS, Red Hat, VMware, ITIL, and Linux, he specializes in designing and managing robust cloud and on-premises infrastructures.