Use ax.text() for text at a position, ax.text() with a bbox for a boxed note, ax.annotate() to label a specific point (optionally with an arrow), and fig.text() for text positioned relative to the entire figure. The key choice is the coordinate system: data coordinates follow the plotted data, while axes and figure coordinates keep wording in a stable relative location.
Choose the right Matplotlib text method
| Goal | Use | Position is relative to |
|---|---|---|
| Put a label at a plotted coordinate | ax.text(x, y, "label") |
The data coordinates by default |
| Keep a note in a fixed spot inside one axes | ax.text(..., transform=ax.transAxes) |
The axes rectangle, from 0 to 1 on each axis |
| Connect a label to a particular point | ax.annotate(...) |
The target and label can use separate coordinate systems |
| Add wording for the whole figure | fig.text(...) |
The figure, from 0 to 1 across and up by default |
Add plain text at a data location
Axes.text(x, y, s, **kwargs) adds text to an Axes and returns a Text object. Its default coordinates are data coordinates, so the label is positioned at the supplied x and y values and moves with the data view when limits change.
fig, ax = plt.subplots()
ax.plot(x, y)
ax.text(x_label, y_label, "Important value")
Replace x_label and y_label with coordinates in the same units as the plotted data. If you instead want a note to remain at a consistent spot inside the axes, use axes-fraction coordinates.
Keep a text box fixed inside an axes
Pass transform=ax.transAxes to interpret the text position as a fraction of the axes rectangle: (0, 0) is its lower-left and (1, 1) its upper-right. This is useful for a statistic or explanatory note that should stay in the same relative location when the data limits change.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →#1 Best Overall
ax.text(0.03, 0.97, "Peak season",
transform=ax.transAxes,
ha="left", va="top",
bbox=dict(boxstyle="round,pad=0.3",
facecolor="white", alpha=0.8))
The bbox dictionary adds and styles a rectangular background behind the text. Here, the rounded box has a partly transparent white fill. Text styling such as fontsize and color can be passed as keyword arguments; alignment is controlled with ha (horizontal) and va (vertical).
Annotate a point, with or without an arrow
Use ax.annotate() when the text explains a particular target. Its xy argument identifies the target point, while xytext sets the label position. Add arrowprops to draw a connector between them.
Rank #2
ax.annotate("local maximum",
xy=(x_peak, y_peak),
xytext=(12, 12),
textcoords="offset points",
arrowprops=dict(arrowstyle="->"),
ha="left", va="bottom")
In this example, xy is the peak’s data position. textcoords="offset points" makes xytext a typographic offset from that target rather than another data-coordinate position. If you omit xytext, the text is placed at xy; an arrow is optional.
The annotation API also supports independent coordinate choices for the target and text, including data, axes-fraction, figure-fraction, and offset-point coordinates. If a target lies outside the axes, annotation_clip controls whether the annotation is drawn; by default, clipping is conditional when the target uses data coordinates.
Recommended Free Tools
Rank #3
Place text relative to the whole figure
Use fig.text(x, y, s) for wording that belongs to the entire figure rather than a particular axes, such as a figure-wide note. Its default coordinates are figure fractions from 0 to 1 across and up, and it accepts text styling and a bbox argument.
fig.text(0.5, 0.02, "Source: annual report",
ha="center")
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Which coordinate system should you choose?
- Use data coordinates when the label identifies a position in the plotted values and should follow that position as the view changes.
- Use
ax.transAxeswhen the note belongs to one axes and should stay at a fixed relative location within its rectangle. - Use
ax.annotate()when you need to distinguish a point from the place where its label appears, especially when an arrow helps show the relationship. - Use
fig.text()when the wording belongs to the overall figure, not an individual panel.
For figures with multiple panels, use the relevant Axes object for panel-specific text. Reserve fig.text() for genuinely figure-level wording.
Quick Recap
Rank #4
References
- Matplotlib Axes.text API
- Matplotlib Axes.annotate API
- Matplotlib Figure.text API
- Matplotlib Text properties and alignment
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




