Annotations direct attention to what matters, such as a target, an incident window or an outlier.
Plotly has convenience methods for the most common highlights:
fig.add_hline(y=100, line_dash="dash", annotation_text="target")andfig.add_vline(x=...)draw lines across the whole plot.fig.add_hrect(y0=..., y1=...)andfig.add_vrect(x0="2026-03-01", x1="2026-03-08", fillcolor="red", opacity=0.15, line_width=0)shade bands, ideal for incidents or weekends.fig.add_annotation(x=..., y=..., text="peak", showarrow=True, arrowhead=2, ax=0, ay=-40)labels a point;ax/ayare the arrow tail offset in pixels.
On faceted or subplot figures these accept row= and col= (or "all") to target panels.
Under the hood they add entries to fig.layout.shapes and fig.layout.annotations. Positions are interpreted through xref and yref: "x"/"y" mean data coordinates, "paper" means fractions of the plotting area (0 to 1), and "x domain" means fractions of one axis's domain. add_hline uses xref="x domain" so the line always spans the full width regardless of zoom.
add_shape(type="rect" | "line" | "circle" | "path", ...) draws arbitrary shapes, and layer="below" puts them behind the data. fig.add_layout_image places logos.
Annotations also work as free text, for example a source note at xref="paper", yref="paper", x=0, y=-0.15.
Example
import plotly.express as px
df = px.data.stocks()
fig = px.line(df, x="date", y="AAPL")
fig.add_hline(y=1.0, line_dash="dash", line_color="gray",
annotation_text="start value", annotation_position="bottom right")
fig.add_vrect(x0="2018-10-01", x1="2018-12-31", fillcolor="red",
opacity=0.12, line_width=0, annotation_text="Q4 selloff")
peak = df.loc[df["AAPL"].idxmax()]
fig.add_annotation(x=peak["date"], y=peak["AAPL"], text="peak",
showarrow=True, arrowhead=2, ax=0, ay=-40)
fig.add_annotation(text="Source: px.data.stocks", xref="paper", yref="paper",
x=0, y=-0.15, showarrow=False)
print(len(fig.layout.shapes), len(fig.layout.annotations)) # 2 4
print(fig.layout.shapes[0].xref) # x domain
fig.write_html("annotated.html")Remember
add_hline/add_vline/add_hrect/add_vrectcover most highlightsadd_annotationlabels points;ax/ayoffset the arrow in pixelsxref/yrefchoose data, paper or axis-domain coordinates
Watch out for
- Positioning a note with data coordinates when it should stay fixed relative to the plot area (use xref='paper').