mrkeyoor.com_
Sat 19 Sept 15:48 UTC
PyPIDataupdated 19 Sept 2026

plotly review

Plotly 7.0.0 creates browser-rendered charts from Python. Plotly Express maps dataframe columns to visual properties with short calls; `graph_objects` exposes traces, axes, annotations, shapes, maps, and layout details. A figure can display in notebooks, travel as interactive HTML, export through Kaleido, or become part of a Dash app. Version 7 moves to plotly.js 4, adds quiver traces, changes automatic map fitting, and removes the old Mapbox trace family, several deprecated figure factories, Orca export, pre-1.0 Kaleido, and the image `engine` argument. Our measured install was 6.9.0, the immediately preceding release.

Verdict

Plotly 6.9.0 installed in 1.2 seconds and consumed 46 MB across 3 packages with 0 audit findings in our sandbox; current 7.0.0 then removed several legacy map and export APIs. Install v7 for interactive, portable figures after checking those removals, or choose Matplotlib when the final artifact is static.

We installed it

Lab card: what happened when we installed plotlyScreenshot of plotly documentation
Install✓ · 1.2s3 packages on disk · 46 MB
Importimport _plotly_utils in 0.02s · pure Python · requires Python >=3.8
Known vulns0(pip-audit)

Answers from our run

Does plotly install cleanly?

Yes. In a fresh container with an empty cache, pip install plotly finished in 1 seconds, leaving 3 packages and 46 MB on disk. pip-audit reported no known vulnerabilities.

What does plotly need to run?

Python >=3.8, and nothing compiled: it is pure Python. In our run import _plotly_utils succeeded in 0.02s.

plotly or matplotlib: which should you use?

matplotlib: Choose it for static figures, detailed print control, and established scientific publication workflows. Plotly 6.9.0 installed in 1.2 seconds and consumed 46 MB across 3 packages with 0 audit findings in our sandbox; current 7.0.0 then removed several legacy map and export APIs.

When should you not use plotly?

The output is print-first or journal artwork; Matplotlib has a deeper static publishing workflow and Plotly image export adds Kaleido plus Chrome

API stability3/5Express functions, `graph_objects.Figure`, trace constructors, and update methods remain the main authoring routes, but 7.0 is a substantial cleanup. It removes 12 deprecated figure factories, the Mapbox trace family, Orca, Kaleido below 1.0, and image-export `engine` arguments. The plotly.js 4 update also changes accepted color strings and map fitting, so a major-version test pass is required even for code that imports successfully.
Docs5/5The official Python site has example-led sections for chart families, Express, graph objects, renderers, HTML, static export, hover text, subplots, templates, maps, animation, and performance. A generated figure reference exposes the large schema. Migration details live in the changelog rather than every topical page, so v6 users should read the 7.0 removal list before following an isolated example.
Maintenance5/5PyPI published 7.0.0 on August 25, 2026, and GitHub records its latest push that same day. The repository is unarchived with 18,754 stars and 772 combined open issues and pull requests. The release synchronizes with plotly.js 4, fixes map and HTML behavior, and completes announced removals, showing active work while also exposing the regression surface of a large Python-to-JavaScript schema.
Ecosystem5/5The stored download snapshot records 15,512,350 weekly downloads. Figures work in Jupyter, marimo, standalone HTML, Dash, and static export through Kaleido, and dataframe support includes Narwhals-backed inputs. The surrounding system is broad but segmented: interactive rendering depends on plotly.js, widget use adds `anywidget`, static files add Kaleido and Chrome, and Dash supplies the application layer.

Use it if

  • Readers need hover details, zoom, pan, legend toggles, selections, or animation in a notebook or HTML report
  • A dataframe should drive color, size, facets, hover fields, and frames without handwritten browser code
  • The work needs scientific, financial, geographic, 3D, Sankey, sunburst, or vector-field traces in one figure model
  • Figures will be reused between notebooks, standalone HTML, static exports, and Dash
Skip it if

Setup reality

We installed Plotly 6.9.0, the release immediately before current 7.0.0, in a fresh Python 3.12 Bookworm container in 1.2 seconds. It left 3 packages using 46 MB, and pip-audit reported 0 known vulnerabilities. The measured distribution was pure Python, required Python 3.8 or newer, carried the MIT license, and had 71 direct requirement entries. It did not ship py.typed. import _plotly_utils completed in 0.02 seconds.

The base install can construct figures and open HTML. Jupyter widget mode also needs Jupyter and anywidget. Static PNG, SVG, PDF, and WebP output needs Kaleido 1.0 or newer plus Chrome or Chromium; version 7 removes Orca and the old engine selector. Slim CI containers must install that browser and its system libraries. County choropleth factory data has historically required the separate plotly-geo package, but several deprecated factories are gone in 7.

Plotly Express works most predictably with long-form data. It returns a graph_objects.Figure, so customization moves into update_traces(), update_layout(), and trace constructors. Hover templates use plotly.js placeholders and d3 number formats. Subplot grids accept traces rather than complete figures. Version 7 removes scattermapbox, choroplethmapbox, and densitymapbox; migrate to their *map replacements and review the new automatic fitting defaults.

write_html() embeds plotly.js by default for offline viewing. include_plotlyjs='cdn' produces a smaller document that needs network access. WebGL traces handle denser scatters than SVG but still consume browser memory and WebGL contexts. Fix axis ranges across animation frames or the visual scale jumps. Plotly 7 also drops decimal-fraction RGB strings, HSV color strings, and MathJax 2 support through its plotly.js 4 upgrade, so snapshot-test custom colors and equation rendering during migration.

Patterns

Make an interactive bar chart from arrays create-bar-chart

import plotly.express as px

fig = px.bar(
    x=['alpha', 'beta', 'gamma'],
    y=[4, 7, 3],
    labels={'x': 'Team', 'y': 'Open items'},
)
fig.show()

Plotly Express is the short route for a single-table chart. The result is still a `graph_objects.Figure`, so later trace and layout edits use the lower-level API.

Bind dataframe columns to size and color plot-dataframe

import plotly.express as px

fig = px.scatter(
    frame, x='revenue', y='margin',
    color='region', size='orders',
    hover_name='account', log_x=True,
)
fig.show()

Column references are resolved at runtime. Validate or rename required columns before chart construction if upstream schemas can change independently.

Overlay actual and forecast series compose-traces

import plotly.graph_objects as go

fig = go.Figure()
fig.add_trace(go.Scatter(x=dates, y=actual, name='Actual', mode='lines'))
fig.add_trace(go.Scatter(
    x=dates, y=forecast, name='Forecast',
    mode='lines', line={'dash': 'dot'},
))
fig.show()

Graph objects expose trace properties directly and are more verbose than Express. Use this route when the figure mixes trace types or needs exact per-trace control.

Set figure-level presentation once customize-layout

fig.update_layout(
    title='Monthly revenue',
    template='plotly_white',
    height=440,
    margin={'l': 50, 'r': 20, 't': 60, 'b': 50},
    legend={'orientation': 'h', 'y': -0.2},
)
fig.update_xaxes(showgrid=False)

Layout owns figure-wide structure. Markers, line styles, trace opacity, and hover templates belong on traces or in `update_traces()`.

Format a custom hover label format-hover

fig = px.scatter(frame, x='revenue', y='margin', custom_data=['account'])
fig.update_traces(
    hovertemplate=(
        '%{customdata[0]}<br>'
        'Revenue: %{x:$,.0f}<br>'
        'Margin: %{y:.1%}<extra></extra>'
    )
)

The placeholders and number formats come from plotly.js and d3, not Python formatting. An empty `<extra>` element suppresses the separate trace-name box.

Add traces to a two-cell grid create-subplots

from plotly.subplots import make_subplots
import plotly.graph_objects as go

fig = make_subplots(rows=1, cols=2, subplot_titles=['Volume', 'Price'])
fig.add_trace(go.Bar(x=days, y=volume), row=1, col=1)
fig.add_trace(go.Scatter(x=days, y=price), row=1, col=2)

`make_subplots()` accepts traces. When starting from an Express figure, add entries from `express_figure.data` instead of inserting the complete figure into one cell.

Wrap regional small multiples facet-data

fig = px.scatter(
    frame, x='revenue', y='margin',
    facet_col='region', facet_col_wrap=3,
)
fig.for_each_annotation(
    lambda item: item.update(text=item.text.split('=')[-1])
)

Express prefixes facet labels with the source field. Wrapped grids often need an explicit height and spacing so lower rows and annotations remain readable.

Keep axes fixed across animated years animate-frames

fig = px.scatter(
    frame, x='income', y='life_expectancy', size='population',
    color='continent', animation_frame='year',
    range_x=[100, 150000], range_y=[20, 90], log_x=True,
)

Fixed ranges make positions comparable from frame to frame. The animation remains interactive HTML and cannot be represented by one static PNG.

Switch a dense scatter to WebGL render-webgl

fig = px.scatter(
    frame, x='x', y='y', color='group',
    render_mode='webgl',
)
fig.update_traces(marker={'size': 4, 'opacity': 0.5})

WebGL raises the practical point count but has different styling support and consumes a browser graphics context. Aggregate or sample if interaction still stalls.

Save a smaller network-dependent report write-html

fig.write_html(
    'report.html',
    include_plotlyjs='cdn',
    full_html=True,
    config={'displaylogo': False},
)

CDN mode avoids embedding the plotly.js runtime and therefore needs network access when opened. Use the default embedded mode for a genuinely offline file.

Render a high-resolution PNG with Kaleido export-image

# pip install 'plotly[kaleido]'
fig.write_image('chart.png', width=1200, height=700, scale=2)

Plotly 7 requires Kaleido 1.0 or newer and a discoverable Chrome or Chromium installation. The old `engine=` argument and Orca route have been removed.

Use the v7 quiver trace for vector data draw-vector-field

import plotly.graph_objects as go

fig = go.Figure(go.Quiver(
    x=x, y=y, u=u, v=v,
    scale=0.2, arrow_scale=0.3,
))
fig.show()

Quiver is new with the plotly.js 4 schema used by Plotly 7. Pin 7.0 or newer anywhere that reads or renders the saved figure specification.

Alternatives

PackageRegistryPick it when
matplotlibPyPIChoose it for static figures, detailed print control, and established scientific publication workflows.
altairPyPIChoose it when a concise Vega-Lite grammar fits the analysis better than direct trace mutation.
bokehPyPIChoose it for interactive plots connected to Python callbacks and streaming through a Bokeh server.
plotninePyPIChoose it when a ggplot2-style grammar matters more than browser interaction.

More data guides

numpy · fsspec · pandas · pyarrow · sqlalchemy · s3fs · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.