charted is a zero-dependency chart generation library for Python and AI agents, with the core goal of turning data into images in the simplest way possible: pass in a set of numbers, get back a chart, with no need for numpy, pandas, or configuration files. Inspired by mermaid.js, it generates customizable SVG charts from data structures in pure Python.
Main capabilities
- Zero runtime dependencies: the core library is pure Python and does not depend on numpy/pandas. PNG export and the MCP server are optional add-ons that bring in their own dependencies, while the base library stays clean.
- 15 chart types: Bar, Column, Line, Scatter, Pie, Area, Radar, Box Plot, Histogram, Heatmap, Gantt, Bubble, Combo, Polar Area, Sankey.
- Multi-series support: supports stacked, side-by-side, and grouped layouts.
- Negative value handling: includes correct zero-baseline calculation.
- Output formats: native SVG; PNG via the optional cairosvg (pip install charted[png]).
- Theme system: 3 built-in presets (light, dark, high-contrast) plus custom theme combinations.
- Per-series styling: fine-grained control via the SeriesStyle builder.
- Data loading: built-in CSV/JSON parsers.
- Markdown export: generates markdown snippets that can be embedded directly.
- Command-line tool: create charts without writing Python code.
- Jupyter support: charts render inline automatically.
- Base Chart class: a unified API that allows dynamically selecting the chart type at runtime.
Usage All chart types share the same simple interface: pass in data, labels, dimensions, and a title. For example:
from charted import BarChart chart = BarChart(data=[1, 2, 3], labels=["A", "B", "C"], title="My Chart") chart.save("chart.svg")
Command-line usage (no Python required):
python -m charted --type bar --data "1,2,3" --labels "A,B,C" --title "My Chart" --output chart.svg
When a --config file is also passed, --title, --width, and --height override values of the same names in the file.
CSV format (default): the first column is the x-axis labels, and each remaining column is a data series. Wide-table CSV can use --transpose: if the CSV is laid out horizontally, with one series per row and x values in the header, pass --transpose; the corner cell is ignored, the rest of the header becomes the x-axis labels, and each subsequent row is a series named by its first cell. Omitting --transpose will cause the axes to be reversed, so this flag is specified explicitly rather than guessed automatically.
MCP server (AI agent integration) charted includes a built-in MCP server that lets AI agents (Claude Code, Cursor, etc.) generate charts without writing Python. It can be run without installation using uvx:
uvx charted[mcp]
This command pulls charted with the MCP add-on into a temporary environment and starts the server over stdio. The server exposes four tools: create_chart, list_chart_types, list_themes, and chart_from_csv. create_chart and chart_from_csv accept an output_format parameter, which can be svg, html, data_url, or png; when output_format="png", a rasterized PNG image is returned, allowing the agent to display the chart inline in the chat interface instead of forwarding raw SVG markup. The mcp add-on includes cairosvg, so PNG output works out of the box. PNG rasterization requires the cairo system library, which can be installed on Debian/Ubuntu with apt install libcairo2.
Claude Skill The chart Skill can be installed with a one-line command.
Sankey diagrams Nodes are assigned to columns according to alignment, then relaxed over multiple iterations so that connected nodes align and ribbon crossings are minimized. Link thickness is proportional to the flow value; the stacked width of each nodeThe sum of degrees equals the height of that node. Links are passed as (source, target, value) tuples or {"source", "target", "value"} dictionaries; endpoints can be node names or indices. Node labels in dense columns are staggered vertically to avoid overlap. The alignment option controls how nodes are assigned to columns: justify (the default, similar to d3-sankey) pushes all sinks to the last column; left keeps each node at its own depth; right aligns by distance to the sink; center keeps the left side and pins sources to the first column. For funnel/conversion data, alignment="left" should be used, because a funnel's drop-off sinks are distributed across multiple different depths, and the default justify pulls them all into the same tall column, flattening the funnel shape.
Themes and styles Three built-in presets (light, dark, high-contrast) plus custom theme combinations. Theme overrides can be applied via chart.style(**kwargs), which returns the chart to support chaining, for example setting background_color or legend_font_size. resolve_palette(name) can convert a built-in palette name into a list of hexadecimal colors for use with the colors= parameter. Built-in palette names include default, viridis, ocean, categorical, rainbow, monochrome, pastel, sunset, forest, inferno, and the colorblind-safe okabe-ito.
Other public APIs
- Automatic chart selection: auto(data, **kwargs) selects a chart type based on the shape of the data (1D becomes a bar chart or pie chart, a matrix becomes a heatmap, etc.) and returns a chart instance; auto_size(data, width, height) returns the (width, height) to which the dataset will be scaled when no size is explicitly specified.
- Building from a dictionary or DataFrame: from_dict({"data": ..., "chart_type": ...}) builds a chart from a configuration dictionary; from_dataframe(df) accepts a pandas DataFrame (or, when pandas is not installed, a plain dictionary of columns to lists), usingthe first numeric column as the data and the index or first string column as the labels.
- Inline and data URL embedding: inline_svg(path) reads an SVG file back as a string for embedding in HTML or notebooks; chart_to_data_url(path) returns a URL-encoded data:image/svg+xml,... URI that can be placed directly in an <img> tag or in a markdown image.
- Saving and restoring configuration: chart.to_config() serializes the chart into a JSON-friendly dictionary (size, data, labels, scales, reference lines, annotations, etc.); Chart.from_config(config, **overrides) rebuilds the chart from that dictionary, with keyword overrides merged into the top level, making it easy to adjust just one value without rebuilding the entire configuration.
- HTML hover tooltips: chart.to_html(tooltips=True) attaches a native SVG <title> to each data mark, so browsers can display built-in hover tooltips without JavaScript. This affects only HTML output; to_svg() and save() are unchanged.
- Reference lines: passing reference_lines=[{"value": 50, "axis": "y", "label": "Target"}] draws a horizontal or vertical line at a certain value with an optional label. axis of "y" means a horizontal line (the default), and "x" means a vertical line.
- Annotations: pass annotations=[...], using LineAnnotation, BoxAnnotation, or LabelAnnotation to mark the chart with lines, shaded regions, or text.
- Logarithmic and time scales: pass x_scale= or y_scale= as "log" for a logarithmic axis, or "time" for a time axis (accepting dates, datetimes, or ISO date strings as x values). The default is "linear". The value axis of bar charts or column charts rejects logarithmic and time scales, because these charts fill from a zero baseline.
Installation and dependency notes
- Library use (imported in code): install using uv add or pip install.
- CLI or MCP server (standalone tools, no project installation required):uvx or pipx can be used. Note: packages installed with uvx/pipx run in an isolated environment and cannot be imported into project code.
- Optional add-ons add dependencies, while the core library remains zero-dependency.
- PNG export: save directly as PNG using the .png extension, requires cairosvg; if not installed, save() will raise an ImportError with installation instructions.
Limitations and Notes
- The core library is zero-dependency, but PNG export and the MCP server are optional add-ons that introduce additional dependencies.
- PNG rasterization requires the cairo system library.
- Bar/column charts do not support logarithmic and temporal scales on the value axis.
- Wide-table CSV requires explicitly passing --transpose, otherwise the axes will be swapped.
- Funnel/churn data must use alignment="left", otherwise the default justify will flatten the funnel shape.
- Packages installed with uvx/pipx cannot be imported by project code.
Full documentation includes a configuration reference. charted avoids using tkinter by using predefined font metrics in fonts/definitions/, and can generate new font definitions.