Skip to main content

XY-shaped probability field shown as a binned scatter chart.

CI CodSpeed Python 3.11+ Docs

XY is an extremely fast, interactive, customizable Python charting library for the web, notebooks, and static exports.

Charts are composed declaratively or through matplotlib conventions. You can fully customize them with Python, CSS, or Tailwind.

With small charts, every point is sent to the browser. For large charts, the Rust core computes only what the screen needs to display, based on its resolution. Pan, zoom, hover, and selection can show full details by running the same process for the new range, and a selection returns the original rows.

XY is early alpha, and is receiving frequent enhancements. Any contributions are appreciated!

Is XY right for me?

XY is for Python users who want one flexible charting library for everything from everyday plots to custom application visuals and large datasets. Build a chart once, then use it in notebooks and web apps or export it as HTML, PNG, SVG, or PDF.

Installation

pip install xy

# or, with uv
uv add xy

Getting started

A chart is a container plus the marks inside it. Any sequence works; NumPy is optional.

import xy

chart = xy.line_chart(xy.line([1, 2, 3, 4, 5], [120, 180, 165, 240, 310]))
# chart.to_html("chart.html")
# chart.to_png("chart.png")
# chart.to_svg("chart.svg")
chart  # notebooks render it

The same API scales to a hundred million points as a density surface:

A hundred-million-point spiral rendered as a density surface, then zoomed until the surface resolves into individual points.

import numpy as np

import xy

rng = np.random.default_rng(7)
n = 100_000_000

r = 6.0 * rng.beta(1.2, 3.0, n)
theta = 2.9 * np.log1p(r) + rng.integers(0, 4, n) * (np.pi / 2) + rng.normal(0, 0.045 + 0.016 * r, n)

chart = xy.scatter_chart(
    xy.scatter(
        r * np.cos(theta),
        r * np.sin(theta),
        color=np.exp(-r / 2.2),
        colormap="magma_r",
        density=True,
        opacity=0.85,
        # Grow and solidify markers once a view drills through to real rows.
        size=2.5,
        zoom_size_factor=2.6,
        zoom_opacity=0.95,
    ),
    xy.theme(
        background="#ffffff", plot_background="#ffffff", grid_color="#e6e6e1",
        axis_color="#c3c2b7", text_color="#0b0b0b",
    ),
    title="100 million points",
)
chart

Coming from matplotlib

For common pyplot workflows, change the import and keep the plotting code:

import numpy as np
import xy.pyplot as plt

x = np.linspace(0, 10, 200)
fig, ax = plt.subplots()
ax.plot(x, np.sin(x), "r--", label="signal")
ax.legend()
plt.show()

See the compatibility guide; not all charts and functionality are supported yet.

Customize every layer

Use Python to control the chart, from marks and axes to interactions and layout.

  • Marks: Control color, size, opacity, symbols, gradients, strokes, curves, and colormaps.
  • Guides: Customize axes, ticks, grids, annotations, legends, colorbars, and tooltips.
  • Interaction: Add pan, zoom, hover, selections, crosshairs, callbacks, and linked charts.
  • Layout: Create layers and facets, set responsive dimensions, and apply themes.
chart = xy.line_chart(
    xy.line(x, y, color="#7c3aed", width=3),
    class_name="rounded-xl bg-white",
    class_names={"tooltip": "rounded-lg bg-zinc-900 text-white"},
)

See the styling guide for examples. For a detailed breakdown of what can be customized, see the capability matrix.

Benchmarks

Cold-render time for a 10-million-point chart in XY, Matplotlib, and Plotly. Lower is better.

In the recorded 10-million-point launch baseline, XY wrote a static PNG in 0.018 s against 2.7 s for Matplotlib and 9.6 s for Plotly, and reached first interactive render 16–18× sooner. The baseline uses identical seeded data, a 900×420 output, and three isolated cold runs.

For the environment, methodology, and raw results, see the launch report, benchmark runbook, and competitive benchmark specification.

Embed XY in a Reflex app

The reflex-xy adapter turns any XY chart into a regular Reflex component, with no JavaScript, iframe, or separate chart service. It ships as its own package and pulls in xy and reflex:

pip install reflex-xy

# or, with uv
uv add reflex-xy

Register the adapter once:

# rxconfig.py
import reflex as rx
import reflex_xy

config = rx.Config(
    app_name="dashboard",
    plugins=[reflex_xy.XYPlugin()],
)

Then add a chart anywhere in the component tree:

import reflex as rx
import reflex_xy
import xy

signups = xy.line_chart(
    xy.line([1, 2, 3, 4, 5], [120, 180, 165, 240, 310]),
    title="Weekly signups",
)


def index() -> rx.Component:
    return rx.card(
        rx.heading("Growth"),
        reflex_xy.chart(signups, height="320px"),
        width="100%",
    )


app = rx.App()
app.add_page(index)

Hover, pan, and zoom keep working. For charts driven by Reflex state, events, or live streams, see the Reflex integration guide and the runnable example app.

Examples

Each notebook fetches its rows from the linked public source; no raw datasets are stored in this repository. Counts describe the featured chart, and the notebooks scale further. See the example guide for sources, workload controls, and setup.

Gaia DR3 · HR diagram
250,000 plotted stars

Gaia DR3 stellar color versus absolute magnitude.

Open notebook
gnomAD v4.1 · allele frequency
164,000 plotted variants

gnomAD allele frequency across all autosomes.

Open notebook
Pan-UKBB · Manhattan plot
814,294 plotted variants

Pan-UKBB standing-height associations across all autosomes.

Open notebook
Dukascopy · EUR/USD ticks
101,427 plotted ticks

Dukascopy EUR/USD midpoint quotes.

Open notebook
LIGO · GW150914 strain
16,777,216 raw · 3,441 shown

GWOSC reconstructed Hanford waveform for GW150914.

Open notebook
NYC TLC · taxi pickup density
300,000 pickup records

Locally projected NYC yellow-taxi pickup hexbin density.

Open notebook

How it works

Most chart stacks serialize every value as JSON and ask the browser to draw every mark. XY keeps exact values in a ColumnStore, computes a level of detail in Rust, and transfers typed binary buffers. Decimated and density views are bounded by the visible result.

flowchart TB
    API["Python API<br/>Build the chart"]
    STORE["ColumnStore<br/>Keep canonical f64 columns"]
    CORE["Native Rust compute<br/>Direct · decimated · density"]
    PAYLOAD["Compact payload<br/>Data-less JSON spec + typed binary buffers"]
    RENDER["Browser or notebook<br/>WebGL2 marks · Canvas axes · DOM interface"]

    API --> STORE --> CORE --> PAYLOAD --> RENDER

So a dense overview can aggregate while a narrow view returns exact points. With a live host, pan and zoom request a refined payload. Canonical f64 data stays in Python, so hover and selection still return original rows.

For the full design, see the design dossier.

Roadmap

Broad 2D coverage first, then geographic, 3D, and volume visualization. Queued next, no dates implied:

  • Categorical distributions: strip, swarm, beeswarm, boxen, rug
  • Regression diagnostics: trendline, residual, QQ, PP
  • Scatter matrix and joint plots: SPLOM, pair grid, marginal histograms
  • Pie / donut: in xy.pyplot today, promoting to xy.pie_chart(xy.pie(...))
  • Candlestick / OHLC and finance overlays: SMA, VWAP, Bollinger, RSI, MACD; prototyped, awaiting a fresh landing
  • Waterfall and funnel
  • Treemap, sunburst, and icicle
  • Radar / polar and gauge: needs polar axes first
  • Slope, bump, and dumbbell
  • 3D and volume: scatter, surfaces, meshes, isosurfaces, and volumetric views

The full ranked backlog is in the chart roadmap. Want a chart or feature that isn't listed? Open an issue.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

xy-0.0.4.tar.gz (11.8 MB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

xy-0.0.4-py3-none-win_arm64.whl (1.4 MB view details)

Uploaded Python 3Windows ARM64

xy-0.0.4-py3-none-win_amd64.whl (1.5 MB view details)

Uploaded Python 3Windows x86-64

xy-0.0.4-py3-none-win32.whl (1.4 MB view details)

Uploaded Python 3Windows x86

xy-0.0.4-py3-none-pyemscripten_2026_0_wasm32.whl (1.2 MB view details)

Uploaded PyEmscripten 2026.0 wasm32Python 3

xy-0.0.4-py3-none-musllinux_1_2_x86_64.whl (1.5 MB view details)

Uploaded Python 3musllinux: musl 1.2+ x86-64

xy-0.0.4-py3-none-musllinux_1_2_armv7l.whl (1.5 MB view details)

Uploaded Python 3musllinux: musl 1.2+ ARMv7l

xy-0.0.4-py3-none-musllinux_1_2_aarch64.whl (1.5 MB view details)

Uploaded Python 3musllinux: musl 1.2+ ARM64

xy-0.0.4-py3-none-manylinux_2_17_x86_64.whl (1.5 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

xy-0.0.4-py3-none-manylinux_2_17_armv7l.whl (1.5 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARMv7l

xy-0.0.4-py3-none-manylinux_2_17_aarch64.whl (1.5 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64

xy-0.0.4-py3-none-macosx_11_0_arm64.whl (1.4 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

xy-0.0.4-py3-none-macosx_10_12_x86_64.whl (1.5 MB view details)

Uploaded Python 3macOS 10.12+ x86-64

File details

Details for the file xy-0.0.4.tar.gz.

File metadata

  • Download URL: xy-0.0.4.tar.gz
  • Upload date:
  • Size: 11.8 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for xy-0.0.4.tar.gz
Algorithm Hash digest
SHA256 83458c16993350ebab09fb5a8a560d1d95956485847bb013d84652875d7fe2bf
MD5 550faa54c15ef0794dc2ac848c299fd2
BLAKE2b-256 b97a28a1b3e2ce81c2338a073c1a171b092046eb39add7a42b86dc9049a5f598

See more details on using hashes here.

Provenance

The following attestation bundles were made for xy-0.0.4.tar.gz:

Publisher: release.yml on reflex-dev/xy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file xy-0.0.4-py3-none-win_arm64.whl.

File metadata

  • Download URL: xy-0.0.4-py3-none-win_arm64.whl
  • Upload date:
  • Size: 1.4 MB
  • Tags: Python 3, Windows ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for xy-0.0.4-py3-none-win_arm64.whl
Algorithm Hash digest
SHA256 2c8423c543b891991747912808c2530631e23d4c010b8bc6223abc60b2b0a734
MD5 c5f2449af08cd8593e237daa85f7e765
BLAKE2b-256 58f10b4a98edddbad5ca49ae3a21a7575b685f82974bfc6e69bd515c945c9faf

See more details on using hashes here.

Provenance

The following attestation bundles were made for xy-0.0.4-py3-none-win_arm64.whl:

Publisher: release.yml on reflex-dev/xy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file xy-0.0.4-py3-none-win_amd64.whl.

File metadata

  • Download URL: xy-0.0.4-py3-none-win_amd64.whl
  • Upload date:
  • Size: 1.5 MB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for xy-0.0.4-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 ba1d3fd3f00c3bb5793224cda8c8022c48136be95b05a074413e73570a870869
MD5 e27024a3be49157151b400393a538f6f
BLAKE2b-256 e54cc2c5698c15c85ad1963de97e2846c13f462c584820c6fb440bbde1e5b250

See more details on using hashes here.

Provenance

The following attestation bundles were made for xy-0.0.4-py3-none-win_amd64.whl:

Publisher: release.yml on reflex-dev/xy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file xy-0.0.4-py3-none-win32.whl.

File metadata

  • Download URL: xy-0.0.4-py3-none-win32.whl
  • Upload date:
  • Size: 1.4 MB
  • Tags: Python 3, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for xy-0.0.4-py3-none-win32.whl
Algorithm Hash digest
SHA256 0c3e506df03ee3f24074dbda60ac01fae453086b98b24a51934bfd6a6c96a436
MD5 725617413abc83e6aeef405aaac9b400
BLAKE2b-256 d3fcf8dd93f1888bf2011efdf9c0541a9c9984dd204033942b6f7850831b009d

See more details on using hashes here.

Provenance

The following attestation bundles were made for xy-0.0.4-py3-none-win32.whl:

Publisher: release.yml on reflex-dev/xy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file xy-0.0.4-py3-none-pyemscripten_2026_0_wasm32.whl.

File metadata

File hashes

Hashes for xy-0.0.4-py3-none-pyemscripten_2026_0_wasm32.whl
Algorithm Hash digest
SHA256 860daa1873f782810218409a05497d07ea39d339929be55fd008a2f48b7e5531
MD5 fb8a106e778b56de018ccf9ccd804fcc
BLAKE2b-256 a1d374d125493fe0e236609f20754538cb8bd256bb8454537f9df94b6a293f62

See more details on using hashes here.

Provenance

The following attestation bundles were made for xy-0.0.4-py3-none-pyemscripten_2026_0_wasm32.whl:

Publisher: release.yml on reflex-dev/xy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file xy-0.0.4-py3-none-musllinux_1_2_x86_64.whl.

File metadata

  • Download URL: xy-0.0.4-py3-none-musllinux_1_2_x86_64.whl
  • Upload date:
  • Size: 1.5 MB
  • Tags: Python 3, musllinux: musl 1.2+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for xy-0.0.4-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 b34684adabca764c0d07c8b7b4bdd8bace03f40fe25423e33a7097fcf98ffb0f
MD5 c7f92e8949319ce795c70a5f883b0177
BLAKE2b-256 9f355a1af2b15175f22c08775adda05cca062919a982e2d4554ae5c0c7606f94

See more details on using hashes here.

Provenance

The following attestation bundles were made for xy-0.0.4-py3-none-musllinux_1_2_x86_64.whl:

Publisher: release.yml on reflex-dev/xy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file xy-0.0.4-py3-none-musllinux_1_2_armv7l.whl.

File metadata

  • Download URL: xy-0.0.4-py3-none-musllinux_1_2_armv7l.whl
  • Upload date:
  • Size: 1.5 MB
  • Tags: Python 3, musllinux: musl 1.2+ ARMv7l
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for xy-0.0.4-py3-none-musllinux_1_2_armv7l.whl
Algorithm Hash digest
SHA256 7106a607079d160fec84b0b218a7e784da1037b5b401190a20a2bc8b75b4b133
MD5 a25af93538d8a681ffe3eea8665afbcc
BLAKE2b-256 1bf169d3b41929c4286d46ff5d6a3ed984e1d6c18cc203d9003aa3ae1880882a

See more details on using hashes here.

Provenance

The following attestation bundles were made for xy-0.0.4-py3-none-musllinux_1_2_armv7l.whl:

Publisher: release.yml on reflex-dev/xy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file xy-0.0.4-py3-none-musllinux_1_2_aarch64.whl.

File metadata

  • Download URL: xy-0.0.4-py3-none-musllinux_1_2_aarch64.whl
  • Upload date:
  • Size: 1.5 MB
  • Tags: Python 3, musllinux: musl 1.2+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for xy-0.0.4-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 196b22d072f94b49d4d561bfba07d45d4702213b1837d3fc5e7c265a52765027
MD5 9e4ccb560daa3c113db4addeddda804c
BLAKE2b-256 fd0541aa3ababfcc347d066d78473f639aa5758d635c300109354950ea43be8d

See more details on using hashes here.

Provenance

The following attestation bundles were made for xy-0.0.4-py3-none-musllinux_1_2_aarch64.whl:

Publisher: release.yml on reflex-dev/xy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file xy-0.0.4-py3-none-manylinux_2_17_x86_64.whl.

File metadata

  • Download URL: xy-0.0.4-py3-none-manylinux_2_17_x86_64.whl
  • Upload date:
  • Size: 1.5 MB
  • Tags: Python 3, manylinux: glibc 2.17+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for xy-0.0.4-py3-none-manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 e0778cf7da68c944f941af3b2463ccd1e55727bdf5c74caff13048024a3c03ab
MD5 aa156061fae4dfc2ef76b5972ba74e40
BLAKE2b-256 b5e8a324d225a6fde7fc9ae15710d012227ed53de54dac063da0b28cd20be831

See more details on using hashes here.

Provenance

The following attestation bundles were made for xy-0.0.4-py3-none-manylinux_2_17_x86_64.whl:

Publisher: release.yml on reflex-dev/xy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file xy-0.0.4-py3-none-manylinux_2_17_armv7l.whl.

File metadata

  • Download URL: xy-0.0.4-py3-none-manylinux_2_17_armv7l.whl
  • Upload date:
  • Size: 1.5 MB
  • Tags: Python 3, manylinux: glibc 2.17+ ARMv7l
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for xy-0.0.4-py3-none-manylinux_2_17_armv7l.whl
Algorithm Hash digest
SHA256 630baa5da7d893fe28ab3c1599e8581e09bc9cd2a35c14fda0d53c91a098db43
MD5 acfe0bd86c697c419a931d843f9046b7
BLAKE2b-256 b1d5eef8b4c1ad54aa49a252ae2d8a433df80f6557c269bcbe89854bc1e43a70

See more details on using hashes here.

Provenance

The following attestation bundles were made for xy-0.0.4-py3-none-manylinux_2_17_armv7l.whl:

Publisher: release.yml on reflex-dev/xy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file xy-0.0.4-py3-none-manylinux_2_17_aarch64.whl.

File metadata

  • Download URL: xy-0.0.4-py3-none-manylinux_2_17_aarch64.whl
  • Upload date:
  • Size: 1.5 MB
  • Tags: Python 3, manylinux: glibc 2.17+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for xy-0.0.4-py3-none-manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 2840da145cacff640e293439f405009acefdae7c9906f7d3eef24387b95006b2
MD5 51c502c993a07c69cfd0b35282820474
BLAKE2b-256 978c01ef11b8cf76c3b03a319cdd16eb7bb586ffb954e6c84bf0cecfe482ef36

See more details on using hashes here.

Provenance

The following attestation bundles were made for xy-0.0.4-py3-none-manylinux_2_17_aarch64.whl:

Publisher: release.yml on reflex-dev/xy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file xy-0.0.4-py3-none-macosx_11_0_arm64.whl.

File metadata

  • Download URL: xy-0.0.4-py3-none-macosx_11_0_arm64.whl
  • Upload date:
  • Size: 1.4 MB
  • Tags: Python 3, macOS 11.0+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for xy-0.0.4-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 2d82af3913dcaf4d18ee50eaad511891b508eaec67cd3f83f4652ca6657675b4
MD5 eac6bb4cc49697233391e9d36f8154b0
BLAKE2b-256 f36a7459adf466f019bc91712aa80a88bbcc2650359992e9d2663c9bcb2df764

See more details on using hashes here.

Provenance

The following attestation bundles were made for xy-0.0.4-py3-none-macosx_11_0_arm64.whl:

Publisher: release.yml on reflex-dev/xy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file xy-0.0.4-py3-none-macosx_10_12_x86_64.whl.

File metadata

  • Download URL: xy-0.0.4-py3-none-macosx_10_12_x86_64.whl
  • Upload date:
  • Size: 1.5 MB
  • Tags: Python 3, macOS 10.12+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for xy-0.0.4-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 4a627a018b3fe6f61dfcb14e82033f29ff80eb86f9e33e7a264d4527c1399b1c
MD5 3388d5b43ba46a24987de1810a54f940
BLAKE2b-256 edd350a6a18cc469ef6d9ba8535f46e80cc8b9e0e11891afbb76807032346bfd

See more details on using hashes here.

Provenance

The following attestation bundles were made for xy-0.0.4-py3-none-macosx_10_12_x86_64.whl:

Publisher: release.yml on reflex-dev/xy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page