A real-estate client wanted the Matplotlib scatter plot legend facecolor solid so it stood out from the colored points. The answer is ax.legend(facecolor=..., framealpha=1).
Their first try only passed facecolor, and the box still looked washed out. That’s because Matplotlib draws it at 80% opacity.
Quick answer: set color and opacity together:
ax.legend(facecolor="lightyellow", edgecolor="black", framealpha=1)
In this tutorial, I’ll color the legend box, fix the faded look, restyle an existing legend, match a dark theme and set a default.
Set the scatter plot legend facecolor with legend()
My sample is Riverbend Realty’s 2026 Austin listings: 60 homes each in Hyde Park, Mueller and Zilker, run on Python 3.12.5 and Matplotlib 3.11.2. You pass facecolor to legend(), not scatter():
import matplotlib.pyplot as plt
import numpy as np
rng = np.random.default_rng(7)
areas = {"Hyde Park": (1650, 640), "Mueller": (1900, 590),
"Zilker": (2200, 910)} # mean sq ft, mean price $K
fig, ax = plt.subplots(figsize=(8, 5))
for name, (sqft, price) in areas.items():
x = rng.normal(sqft, 420, 60)
y = price + (x - sqft) * 0.32 + rng.normal(0, 70, 60)
ax.scatter(x, y, s=28, alpha=0.8, label=name)
ax.set_xlabel("Living area (sq ft)")
ax.set_ylabel("List price (thousand USD)")
ax.set_title("Riverbend Realty - Austin listings, 2026")
ax.legend(loc="upper left", facecolor="lightyellow",
edgecolor="black", title="Neighborhood")
plt.tight_layout()
plt.show()

Any color format works. If you still need the legend itself, start with adding a legend to a Matplotlib scatter plot.
Why does my legend facecolor look faded?
Same listings, two panels: default opacity on the left, framealpha=1 on the right:
import matplotlib.pyplot as plt
import numpy as np
# rng and areas from example 1
fig, axes = plt.subplots(1, 2, figsize=(11, 4.5), sharey=True)
for ax, alpha in zip(axes, (None, 1.0)):
rng = np.random.default_rng(7)
for name, (sqft, price) in areas.items():
x = rng.normal(sqft, 420, 60)
y = price + (x - sqft) * 0.32 + rng.normal(0, 70, 60)
ax.scatter(x, y, s=28, alpha=0.8, label=name)
leg = ax.legend(loc="upper left", facecolor="navy",
labelcolor="white", framealpha=alpha)
ax.set_title(f"framealpha={alpha} -> {leg.get_frame().get_alpha()}")
plt.tight_layout()
plt.show()

The titles show it: None falls back to 0.8, so the white plot tints the navy. Want a see-through box on purpose? See transparent plot backgrounds and legend styling.
Change the legend facecolor after the legend exists
When a helper builds the legend, get_frame() hands you its background patch:
import matplotlib.pyplot as plt
import numpy as np
# rng and areas from example 1
fig, ax = plt.subplots(figsize=(8, 5))
for name, (sqft, price) in areas.items():
x = rng.normal(sqft, 420, 60)
y = price + (x - sqft) * 0.32 + rng.normal(0, 70, 60)
ax.scatter(x, y, s=28, alpha=0.8, label=name)
ax.set_xlabel("Living area (sq ft)")
ax.set_ylabel("List price (thousand USD)")
leg = ax.legend(loc="upper left")
frame = leg.get_frame()
frame.set_facecolor("#e8f4ea") # mint green
frame.set_edgecolor("#2e7d32")
frame.set_boxstyle("round", pad=0.4)
print(frame.get_facecolor())
plt.tight_layout()
plt.show()
Output:
(0.9098039215686274, 0.9568627450980393, 0.9176470588235294, 0.8)

The printed RGBA tuple ends in 0.8, so the default opacity still applies. To grow the labels inside the box, see changing the Matplotlib legend font size.
Match the legend to a dark background
On a dark chart, facecolor="inherit" copies the axes color so the legend doesn’t glow white:
import matplotlib.pyplot as plt
import numpy as np
plt.style.use("dark_background")
print("legend.facecolor:", plt.rcParams["legend.facecolor"])
# rng and areas from example 1
fig, ax = plt.subplots(figsize=(8, 5))
for name, (sqft, price) in areas.items():
x = rng.normal(sqft, 420, 60)
y = price + (x - sqft) * 0.32 + rng.normal(0, 70, 60)
ax.scatter(x, y, s=28, alpha=0.8, label=name)
ax.set_xlabel("Living area (sq ft)")
ax.set_ylabel("List price (thousand USD)")
ax.set_facecolor("#1b2631")
ax.legend(loc="upper left", facecolor="inherit",
edgecolor="gold", framealpha=1)
plt.tight_layout()
plt.show()
Output:
legend.facecolor: inherit

inherit reads axes.facecolor, so set the axes color first. If the box still covers points, putting the legend outside the plot is the cleaner fix.
Set a default legend facecolor with rcParams
For a whole report, change the defaults once:
import matplotlib.pyplot as plt
print("default:", plt.rcParams["legend.facecolor"])
plt.rcParams.update({"legend.facecolor": "whitesmoke",
"legend.framealpha": 1})
fig, ax = plt.subplots()
ax.scatter([1, 2], [3, 4], label="Mueller")
leg = ax.legend()
print("now:", leg.get_frame().get_facecolor())
Output:
default: inherit
now: (0.9607843137254902, 0.9607843137254902, 0.9607843137254902, 1.0)
The stock value is inherit; new legends now get whitesmoke at full opacity. With several panels, legends in Matplotlib subplots shows where to place each one.
Common errors and how to fix them with legend colors
- Facecolor does nothing:
frameon=Falsehides the box. Remove it. - Markers changed, not the legend: move
facecolorfromscatter()tolegend(). - Color looks lighter than the hex code: add
framealpha=1. - Faded legend markers: that’s
scatter(alpha=...); see transparent scatter plots.
For more scatter styling, try these:
- Matplotlib scatter markers
- Colormaps and outlines in Matplotlib scatter plots
- Scatter plots from a pandas DataFrame
- Save a Matplotlib chart as a PNG
Frequently asked questions
How do I change the legend background color in Matplotlib?
Pass it to legend(): ax.legend(facecolor="lightyellow").
Why is my legend color lighter than I set?
The default framealpha is 0.8. Add framealpha=1.
Can I change the facecolor after creating the legend?
Yes: ax.get_legend().get_frame().set_facecolor(c).
How do I make the legend match the plot background?
Use facecolor="inherit", which takes the axes facecolor.
How do I set a legend facecolor for all charts?
Set plt.rcParams["legend.facecolor"] once.
Where is the legend facecolor option documented?
See Axes.legend() in the Matplotlib docs.

Bijay Kumar is a 13-time Microsoft MVP with more than 18 years in software development, and the founder of Python Guides and TSinfo Technologies. He started out building .NET and SharePoint solutions at HP, TCS and KPIT before moving into Python, machine learning and AI, and he also builds web apps with TypeScript and React. He writes the tutorials here himself, and every example is run before publishing so you see the real output. More about Bijay · Microsoft MVP profile · LinkedIn