Written and maintained by CASRAI Editorial Board
Last updated
The legend in Matplotlib is the key that links each plotted line, marker or patch to a label. You add it with legend(), place it with loc, and move it outside the plot area with bbox_to_anchor or, in a constrained layout, with a loc value that starts with 'outside'. This guide maps every placement query (location, position, loc, outside) to the exact argument, using the current official Matplotlib documentation (checked 2026-10-29).
Which argument answers which question
| You want to | Use | What the documentation says |
|---|---|---|
| Pick one of nine standard spots inside the axes | loc='upper left' (a string) |
String locations place the legend within the bounding box, which by default is the full axes area. |
| Use a numeric code instead of a string | loc=2 (an integer) |
Codes: best 0, upper right 1, upper left 2, lower left 3, lower right 4, right 5, center left 6, center right 7, lower center 8, upper center 9, center 10. |
| Put the legend’s lower-left corner at an exact point | loc=(0.6, 0.1) (a 2-tuple) |
The tuple is the lower-left corner of the legend in axes coordinates, and bbox_to_anchor is then ignored. |
| Anchor a chosen corner of the legend at a point | loc='upper right', bbox_to_anchor=(0.5, 0.5) |
A 2-tuple places the corner of the legend specified by loc at that (x, y). |
| Place the legend inside a region (x, y, width, height) | bbox_to_anchor=(0.5, 0., 0.5, 0.5) (a 4-tuple) |
The 4-tuple defines a box; the official example pairs it with loc='best'. |
| Put the legend outside, with automatic room made for it | fig.legend(loc='outside upper right') with layout='constrained' |
The legend is drawn outside the Axes on the (sub)figure. |
What it is used for in research
A figure with more than one data series needs a key. Matplotlib builds that key from the label of each plotted artist: when you call legend() with no arguments, the documentation states that the elements to be added are automatically determined. Anything that is not drawn with a label does not appear in the legend. For how legends fit into figure choices more broadly, see scientific figure rules for journal submission and types of graphs in statistics.
Install or access
The Matplotlib installation page gives these commands for an official release:
pip install matplotlib
conda install -c conda-forge matplotlib
The same page shows the python -m pip form, python -m pip install -U matplotlib, and suggests adding --prefer-binary if an install tries to compile Matplotlib from source and fails. Source: matplotlib.org installation guide, checked 2026-10-29.
Step by step: add a legend and place it
Legend in Matplotlib: the basic call
- Give every artist you want in the legend a label, for example
ax.plot(x, y1, label='Control')andax.plot(x, y2, label='Treated'). - Call
ax.legend(). With no arguments the entries are determined automatically from those labels. - Add
locto choose a position, for exampleax.legend(loc='upper left').
The same function accepts legend(handles, labels), legend(handles=handles) and legend(labels). Calling legend() is equivalent to handles, labels = ax.get_legend_handles_labels() followed by ax.legend(handles, labels).
Legend location in Matplotlib (loc and location)
The default for loc is rcParams["legend.loc"], which is 'best'. The nine fixed string locations form a 3 by 3 grid:
| left | center | right | |
|---|---|---|---|
| top | 'upper left' |
'upper center' |
'upper right' |
| middle | 'center left' |
'center' |
'center right' |
| bottom | 'lower left' |
'lower center' |
'lower right' |
One alias exists: 'center right' may also be written 'right'. No other string has an alias.
Legend position: what ‘best’ does and does not do
'best' places the legend at the location, among the nine defined, with the minimum overlap with other drawn artists. The documentation notes it does not consider inset axes, titles or axis labels, and that the computation can be expensive for plots with a lot of data. If speed becomes a concern, give a specific location instead.
Legend outside the plot in Matplotlib (bbox_to_anchor)
bbox_to_anchor is described as an advanced option for free placement; for most uses loc alone is enough. Two examples from the official legend guide:
ax.legend(bbox_to_anchor=(1.05, 1), loc='upper left', borderaxespad=0.)
This puts the legend to the right of the axes: the upper-left corner of the legend sits at x = 1.05, y = 1 in axes coordinates, and borderaxespad=0. removes the default padding (the default is 0.5, in font-size units).
ax.legend(bbox_to_anchor=(0., 1.02, 1., .102), loc='lower left', ncols=2, mode="expand", borderaxespad=0.)
This places a two-column legend above the axes, expanded to the axes width.
Legend outside the plot with constrained layout
The legend guide states that with constrained layout, starting the loc string with 'outside' draws the legend outside the Axes on the (sub)figure. Its example:
fig, axs = plt.subplot_mosaic([['left', 'right']], layout='constrained')
# ... plot on axs['left'] and axs['right'] ...
fig.legend(loc='outside upper right')
Word order matters: the guide notes that 'outside right upper' is different from 'outside upper right'. The valid forms are outside upper, lower left, center or right (for example 'outside upper right') and outside left or right upper, center or lower (for example 'outside right upper').
Output and how to read it
Each legend row pairs a label with a sample of the artist’s style (line colour and style, marker, or patch). The legend title is None by default and can be set with title=. Other documented defaults: ncols is 1 (use ncols rather than the discouraged ncol), and frameon follows rcParams["legend.frameon"], which is True. In a result with many series, check that each row matches the series you intended before the figure leaves your hands; see scatter plots in Python for a worked plotting example and seaborn colour palettes for colour choices that the legend will display.
Troubleshooting
A series is missing from the legend
The legend guide states that artists with an empty string as the label, or a label starting with an underscore (_), are ignored. Rename the label, or pass the artists explicitly: ax.legend(handles=[line_up, line_down]).
The entries have the wrong names or order
Pass handles to choose and order entries, or pass both lists to rename them: ax.legend([line_up, line_down], ['Line Up', 'Line Down']).
The legend covers data or is slow to draw
Switch from 'best' to a fixed loc, or move the legend outside with bbox_to_anchor. The documentation recommends a specific location when the best-position search is slow on large data.
My bbox_to_anchor has no effect
If loc is a 2-tuple of floats, bbox_to_anchor is ignored. Use a string for loc when you also set bbox_to_anchor.
An ‘outside’ location raises an error or lands in the wrong place
Check the word order ('outside upper right' is not 'outside right upper') and that the figure uses constrained layout.
Free alternatives for legend control
| Tool | How the legend is positioned | Source |
|---|---|---|
| seaborn | seaborn.move_legend(obj, loc, **kwargs) recreates a plot’s legend at a new location; loc is as in matplotlib.axes.Axes.legend() and extra keyword arguments such as bbox_to_anchor pass through. Example: sns.move_legend(ax, "upper left", bbox_to_anchor=(1, 1)). |
seaborn documentation, checked 2026-10-29 |
| Plotly (Python) | The legend has an anchor point set with layout.legend.xanchor and yanchor, positioned with layout.legend.x and y in paper coordinates; orientation="h" makes it horizontal. |
Plotly legend documentation, checked 2026-10-29 |
FAQ
How do I change the legend location in Matplotlib?
Pass loc to legend(), for example ax.legend(loc='lower right'). The default is 'best'.
What are the legend loc options?
Nine strings (upper/center/lower crossed with left/center/right, plus 'best'), the alias 'right' for 'center right', matching numeric codes 0 to 10, or a 2-tuple of axes coordinates.
How do I put the legend outside the plot in Matplotlib?
Use ax.legend(bbox_to_anchor=(1.05, 1), loc='upper left', borderaxespad=0.) for the right side, or fig.legend(loc='outside upper right') with layout='constrained'.
What does bbox_to_anchor do?
It sets the box the legend is placed against. A 2-tuple (x, y) puts the corner named by loc at that point; a 4-tuple gives (x, y, width, height). By default coordinates are axes coordinates for Axes.legend and figure coordinates for Figure.legend.
Can I use the number codes instead of strings?
Yes. For example 1 is upper right and 2 is upper left.
Sources
- matplotlib.pyplot.legend, Matplotlib documentation, checked 2026-10-29.
- Legend guide, Matplotlib documentation, checked 2026-10-29.
- Installation, Matplotlib documentation, checked 2026-10-29.
- seaborn.move_legend, seaborn documentation, checked 2026-10-29.
- Legends in Python, Plotly documentation, checked 2026-10-29.
Related CASRAI guides: graphical abstract examples and guidelines.








