How to Change Fonts in Matplotlib: A Complete Guide
Matplotlib gives you fine-grained control over typography — but the font system has enough layers that it can feel confusing at first. Whether you want to change the font across an entire figure, tweak a single label, or load a custom typeface, understanding how Matplotlib handles fonts makes the difference between guessing and knowing exactly what to change.
How Matplotlib Handles Fonts
Matplotlib manages fonts through its rcParams system — a global dictionary of rendering settings that controls everything from figure size to font family. When you create a plot, Matplotlib pulls font information from these defaults unless you override them explicitly.
The key font-related rcParams include:
font.family— the font category (e.g.,serif,sans-serif,monospace)font.style— normal, italic, or obliquefont.weight— light, normal, bold, or numeric values (100–900)font.size— the base font size in pointsaxes.titlesize,axes.labelsize,xtick.labelsize,ytick.labelsize— size overrides for specific plot elements
These settings cascade. Change font.size globally and most text elements update automatically, unless a more specific parameter overrides them.
Method 1: Change the Font Globally with rcParams 🎨
The simplest approach applies a font change across your entire script or notebook session:
import matplotlib.pyplot as plt import matplotlib as mpl mpl.rcParams['font.family'] = 'serif' mpl.rcParams['font.size'] = 14 Or use the shorthand plt.rcParams, which points to the same dictionary:
plt.rcParams.update({ 'font.family': 'sans-serif', 'font.sans-serif': 'Arial', 'font.size': 12 }) Note that font.family sets the category, while font.sans-serif, font.serif, and font.monospace let you specify the preferred typeface within that category. Matplotlib works through the list in order and falls back to the next available font if the first isn't found.
Method 2: Use rc_context for Scoped Changes
If you only want a font change to apply to one specific figure — not everything in your script — use rc_context as a context manager:
with mpl.rc_context({'font.family': 'monospace', 'font.size': 11}): fig, ax = plt.subplots() ax.plot([1, 2, 3]) ax.set_title("This figure uses monospace") Once the with block exits, your previous settings are restored. This is useful in notebooks or scripts that produce multiple figures with different visual styles.
Method 3: Override Font on Individual Text Elements
Every text object in Matplotlib accepts font properties directly. This gives you element-level control without touching global settings:
ax.set_title("My Title", fontsize=18, fontfamily='serif', fontweight='bold') ax.set_xlabel("X Axis", fontsize=12, fontstyle='italic') You can also use the FontProperties object from matplotlib.font_manager for more precise control, especially when working with custom font files:
from matplotlib.font_manager import FontProperties custom_font = FontProperties(fname='/path/to/MyFont.ttf', size=14) ax.set_title("Custom Font Title", fontproperties=custom_font) This approach lets different text elements within the same figure use completely different typefaces.
Method 4: Load a Custom Font File
If you're using a font that isn't installed system-wide, Matplotlib can load it directly from a .ttf or .otf file:
from matplotlib import font_manager font_manager.fontManager.addfont('/path/to/MyCustomFont.ttf') mpl.rcParams['font.family'] = 'MyCustomFont' After calling addfont(), the font becomes available by name for the duration of your session. The font name you use in rcParams must match the actual font family name embedded in the file, not the filename — so if the font registers itself as "Roboto Condensed", use that exact string.
Comparing the Main Approaches
| Method | Scope | Best For |
|---|---|---|
rcParams global update | Entire session | Consistent style across all figures |
rc_context | Single figure block | Mixed styles in one script |
| Per-element font args | Individual text objects | Fine-tuned control |
FontProperties with fname | Individual text objects | Custom/external font files |
addfont() + rcParams | Entire session | Custom fonts used everywhere |
Variables That Affect Your Results 🖥️
Font behavior in Matplotlib isn't entirely uniform — a few factors shape what you'll actually see:
Font availability by OS. Fonts like Arial, Helvetica, and Times New Roman are common on Windows and macOS but may be missing on Linux distributions. Matplotlib falls back silently to a default (usually DejaVu Sans), which can cause unexpected visual results if you're not checking output across environments.
Backend matters. The rendering backend — Agg, PDF, SVG, TkAgg — can affect how fonts are embedded or rendered. Vector formats like SVG and PDF embed font outlines, which matters for print-quality output. Bitmap backends rasterize text, so fine typographic details may look different.
Notebook vs. script context. In Jupyter notebooks, font changes made mid-session via rcParams affect subsequent cells, not previous ones. Managing state across cells requires care — rc_context or resetting to defaults with mpl.rcdefaults() can help.
Font cache. Matplotlib builds an internal font cache on first use. If you add new fonts and they don't appear, clearing the cache (typically a .json file in your Matplotlib config directory) forces a rebuild on next run.
The Spectrum of Use Cases
Someone building quick exploratory data plots has different needs than a researcher preparing publication-quality figures or a developer generating branded charts programmatically. A global rcParams change covers the first scenario efficiently. Publication workflows often combine custom FontProperties objects with vector export backends. Automated pipelines generating consistent branded output typically set rcParams once at the top of the script and never touch individual elements.
The method that works cleanly depends on how many figures you're producing, whether fonts need to match a brand or style guide, which operating systems the code will run on, and how much per-element variation you actually need. Each combination of those factors points toward a different balance of these tools.