> ## Documentation Index
> Fetch the complete documentation index at: https://docs.runpulse.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Charts

> Read the numbers behind a parse's charts as data, and export them as Excel, CSV or LAS files.

Charts reads every chart in a completed parse as data: its type, its axes, and each series as a list of points. It can also export them as Excel, CSV and LAS (well log) files. For a sentence that describes a chart, ask the [parse](https://docs.runpulse.com/v2/parse.md) for figure descriptions.

## Read a parse's charts

This example parses a report, then reads its charts and saves them as Excel and CSV files:

```python Python theme={null}
import base64
import os
from pulse import Pulse

client = Pulse(api_key=os.environ["PULSE_API_KEY"])

parse = client.parse.run(file_url="https://example.com/annual-report.pdf", config={"model": "ultra-2"})
job = client.charts.run(
    parse_id=parse.parse_id,
    config={"data_points": 50, "export_formats": ["excel", "csv"]},
)
result = client.charts.get_result(job.charts_id)

for chart in result.charts:
    print(chart.element_id, chart.page, chart.type, chart.title)
for export in result.exports:
    with open(export.filename, "wb") as file:
        file.write(base64.b64decode(export.content_base64))
```

```typescript TypeScript theme={null}
import { writeFileSync } from "node:fs";
import { PulseClient } from "@pulse-software/sdk";

const client = new PulseClient({ apiKey: process.env.PULSE_API_KEY! });

const { parseId } = await client.parse.run({
  fileUrl: "https://example.com/annual-report.pdf",
  config: { model: "ultra-2" },
});
const { chartsId } = await client.charts.run({
  parseId,
  config: { dataPoints: 50, exportFormats: ["excel", "csv"] },
});
const result = await client.charts.getResult({ chartsId });

for (const chart of result.charts) {
  console.log(chart.elementId, chart.page, chart.type, chart.title);
}
for (const file of result.exports) {
  writeFileSync(file.filename, Buffer.from(file.contentBase64, "base64"));
}
```

For a document with many charts, send `async: true` and poll the job: see [Jobs and results](https://docs.runpulse.com/v2/jobs.md). An expired or deleted parse gets `400` or `410`: parse the document again.

> [!NOTE]
>
> Charts must be turned on for your organization. Until it is, `POST /charts` returns `404`, as a route that doesn't exist, and a [pipeline](https://docs.runpulse.com/v2/pipelines.md) with a Charts step returns `400`. To turn it on, contact [support](https://docs.runpulse.com/v2/support.md).

***

## What Charts reads

Each `Figure` element on the pages you select that is a chart becomes one entry in `charts`:

* In a PDF or image, Charts reads the figure's pixels and keeps up to `data_points` points per series, with a `confidence` from 0 to 1.
* In an Excel workbook (`.xlsx` or `.xlsm`), it reads the workbook's own chart data: every point, exactly, with `confidence: null`. Charts in an `.xls` workbook are skipped.

> [!NOTE]
>
> Charts reads a Word, PowerPoint or HTML document's charts from the figure images saved with the parse, as for a PDF, so parse it with `enhancements.figures.include: true`. Without them, Charts skips every figure in the document.

Charts doesn't see a chart the parse read as a table. The parse's `layout` refine pass fixes that.

## Choose options

All options in `config` are optional:

| Option | Default | What it does |
| - | - | - |
| `page_range` | Every page | Reads charts on these pages only, numbered as in the parse. A range past the last page is refused with a `400`. |
| `data_points` | `20` | Keeps up to this many points per series, from 2 to 500, for a chart read from pixels. |
| `export_formats` | `["excel"]` | `excel` and `csv` each build one file that holds every chart, and `las` builds one file per well-log chart. `"all"` builds all three. |
| `enhancements.zoom` | `false` | Re-reads small or dense parts of each chart up close: more accurate, but slower. Workbook charts ignore it. |

***

## Read the result

`GET /charts/{charts_id}/result` (`client.charts.get_result`) returns the charts, in the order of their figures, and the export files:

```json theme={null}
{
  "charts_id": "charts-5e1b7a90-3c2d-4f8e-b6a1-9d0c4e2f7a13",
  "exports": [
    {
      "format": "excel",
      "filename": "chart-data.xlsx",
      "media_type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
      "content_base64": "UEsDBBQABgAIAAAAIQBi7p1oXgEAAJAEAAATAAgCW0NvbnRlbnRfVHlwZXNd..."
    }
  ],
  "charts": [
    {
      "element_id": "Figure-12",
      "page": 4,
      "bbox": [0.12, 0.31, 0.88, 0.31, 0.88, 0.62, 0.12, 0.62],
      "type": "bar",
      "title": "Revenue by segment",
      "x_axis": { "scale": "categorical", "title": null },
      "y_axis": { "scale": "linear", "title": "USD millions" },
      "series": [
        {
          "name": "2025",
          "color": "#1f77b4",
          "data": [["Cloud", 412.5], ["Devices", 198.0], ["Services", 87.25]]
        }
      ],
      "confidence": 0.91
    }
  ],
  "usage": {
    "request": { "pages_processed": 1, "credits_used": 1.0 }
  },
  "warnings": [
    { "code": "FIGURE_SKIPPED", "message": "Figure-7: not a chart type the reader supports" }
  ],
  "history": {
    "file_name": "annual-report.pdf",
    "previous_step": "parse-0a4d8e21-6b3f-4c9a-8e75-2f1d9c6b0e48"
  }
}
```

A series' `data` holds `[x, y]` points, and `y` is `null` where it couldn't be read. An axis that couldn't be calibrated has `scale: "normalized"` and values from 0 to 1: treat them as relative, not as the chart's units.

The result's `warnings` can include:

| Warning | What happened |
| - | - |
| `FIGURE_SKIPPED` | The figure isn't a chart, its points couldn't be read, or its image wasn't available. |
| `FIGURE_FAILED` | Reading the figure failed. The other figures are still read. |
| `EXPORT_LAS` | A LAS file couldn't be built or is incomplete, as when no chart is a well log. |

A `FIGURE_SKIPPED` or `FIGURE_FAILED` message starts with the figure's id, such as `Figure-7`. If the chart reader can't be reached at all, the job fails with a `503` and isn't billed. Run it again later.

> [!WARNING]
>
> If your organization deletes each result on its first read, the export files are deleted with the result. Save them the first time you read it.

## Pricing

Charts costs 1 credit per chart returned. Skipped and failed figures and the export files cost nothing ([Pricing](https://docs.runpulse.com/v2/pricing.md)).

## Next steps

> [card] [Parse](https://docs.runpulse.com/v2/parse.md)
>
> Describe figures, save their images, and fix their layout.

> [card] [Charts API reference](https://docs.runpulse.com/api-reference/v2/charts/run-charts.md)
>
> Every option, field and limit.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.