# Dataset Charts & Report (Chart Images + PDF from Any Data) (`nerolabs/dataset-charts-report`) Actor

Turns any Apify dataset, CSV/Excel/JSON file URL or JSON array into chart images (bar, line, area, pie, scatter as PNG and SVG) and an optional PDF or HTML report with KPIs and a plain-English summary. Define charts by field names. Charged per chart and per report; agent-ready via x402 and MCP.

- **URL**: https://apify.com/nerolabs/dataset-charts-report.md
- **Developed by:** [Adam Pearce](https://apify.com/nerolabs) (community)
- **Categories:** Developer tools, Automation, Agents
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $30.00 / 1,000 chart rendereds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

**You have the data. You need the chart, or the one-page report, now, without opening a spreadsheet.** Dataset Charts & Report takes any Apify dataset, a CSV, Excel or JSON file by URL, a Google Sheet, or rows you paste in, and turns it into finished **chart images** (bar, line, area, pie, donut, scatter, as PNG and SVG) and an optional **PDF or HTML report** with KPIs, one-line captions, a data preview and, if you want it, a plain-English summary. You name the fields; it groups, aggregates, draws and files. No browser, no design tool, no code.

Built for people who need a chart in Slack, an email or a slide, and for **AI agents that cannot draw**: one call turns rows into image and PDF links the agent can hand back.

### Why use Dataset Charts & Report?

Every scraper and every pipeline ends in rows. Rows are not what you show a client, a boss or a customer. The usual fix is a spreadsheet, a screenshot and twenty minutes, every time the data changes. This Actor is that last step as a reusable, scheduled, API-callable job:

- **The weekly report**: chain it after any scraper on a schedule and get a PDF with the same four charts every Monday.
- **A chart in Slack or Notion**: point the webhook at a Slack incoming webhook or a Make/Zapier/n8n hook and the PNG link arrives the moment the run finishes.
- **Client-ready deliverables**: title, subtitle, KPIs, charts with captions and a data table on A4, in your accent colour, light or dark.
- **Agents and automations**: an AI agent that has scraped or cleaned data can call this Actor to visualise it, then read the returned image and report URLs. Pay per chart, no account setup, agent-ready via x402 and MCP.
- **Any data shape**: grouping and aggregation (sum, count, mean, median, min, max, distinct) happen inside the chart definition, dates are bucketed by day, week, month, quarter or year automatically, numbers like "£3,120" or "49 USD" are read correctly, and long tails are folded into "Other".

Because it runs on Apify you get scheduling, API access, integrations and run history for free, and it fits directly after the other Nero Labs dataset tools (listed at the end of this page).

### How to use Dataset Charts & Report

1. Click **Try for free** (or **Start**) on this Actor.
2. Bring in your rows: pick a **dataset**, paste a **File URL** (CSV, Excel, JSON, JSON Lines or a Google Sheet shared as "Anyone with the link can view"), or paste rows into **Data (inline)**.
3. Define your **charts** as a short JSON list. Each chart needs an `x` field; add a `y` field to aggregate a number, or leave `y` out to count rows.
4. Choose the image formats, size and theme, and whether you want the **report** (PDF and/or HTML) with a title.
5. Run. Every chart comes back as a row with its PNG and SVG links, the report as a row with its PDF and HTML links, and all files sit in the run's key-value store.

The default input draws three charts (revenue by category, revenue by month, jobs by region) from twelve sample rows and builds a two-format report in a few seconds, so you can see exactly what you get before pointing it at your own data.

### Defining charts

```json
[
  { "type": "bar", "title": "Revenue by category", "x": "category", "y": "revenue", "aggregate": "sum" },
  { "type": "line", "title": "Revenue by month", "x": "date", "y": "revenue", "timeUnit": "month" },
  { "type": "donut", "title": "Jobs by region", "x": "region" },
  { "type": "stackedBar", "title": "Units by region and category", "x": "region", "y": "units", "series": "category" },
  { "type": "scatter", "title": "Units vs revenue", "x": "units", "y": "revenue", "series": "category" }
]
```

| Key | What it does | Default |
|---|---|---|
| `type` | `bar`, `horizontalBar`, `stackedBar`, `line`, `area`, `pie`, `donut`, `scatter` | `bar` |
| `x` | The field for the categories, the dates, or the horizontal axis. Dotted paths like `address.city` work | required |
| `y` | The numeric field to aggregate. Leave out to count rows | none, so count |
| `aggregate` | `sum`, `count`, `mean`, `median`, `min`, `max`, `distinct` | `sum` if `y` is set, else `count` |
| `series` | A field to split into coloured series (up to 10, the rest merged into Other) | none |
| `sort` | `desc` or `asc` by value, `x` by label or date | `desc`, `x` for line and area |
| `limit` | Show the top N categories and fold the rest into "Other" | all, up to 60 |
| `timeUnit` | `auto`, `day`, `week`, `month`, `quarter`, `year`, or `none` to treat dates as labels | `auto` |
| `title`, `xTitle`, `yTitle` | Text for the chart title and axes | built from the field names |
| `color` | Hex colour for a single-series chart | the run's accent colour |
| `yFormat` | A d3 number format for the value axis, e.g. `,.0f`, `$,.2f`, `.1%` | automatic |

Scatter charts plot raw rows (both fields must be numbers) and never aggregate. Everything else groups rows by `x` first. Blank `x` values and non-numeric `y` values are skipped and counted in the run log, never guessed.

### Example output

One row per chart, one row for the report. From the default input:

```json
{
  "kind": "chart",
  "index": 1,
  "title": "Revenue by category",
  "chartType": "bar",
  "x": "category",
  "y": "revenue",
  "aggregate": "sum",
  "rowsUsed": 12,
  "categories": 3,
  "width": 800,
  "height": 450,
  "pngUrl": "https://api.apify.com/v2/key-value-stores/.../records/chart-1.png?signature=...",
  "svgUrl": "https://api.apify.com/v2/key-value-stores/.../records/chart-1.svg?signature=...",
  "caption": "Top: Electrical (12,495). 25,575 in total across 3 categories."
}
```

```json
{
  "kind": "report",
  "title": "Jobs and revenue, January to May 2026",
  "chartCount": 3,
  "rowCount": 12,
  "pdfUrl": "https://api.apify.com/v2/key-value-stores/.../records/report.pdf?signature=...",
  "htmlUrl": "https://api.apify.com/v2/key-value-stores/.../records/report.html?signature=...",
  "aiSummary": null
}
```

The links are signed, so anyone you send them to can open the file without an Apify account. The run summary (`CHARTS_REPORT_SUMMARY` in the key-value store) repeats every link, the KPIs and any warnings.

### What the report contains

- **Title and subtitle** you set, the generation time and the data source.
- **KPIs** computed from the charts themselves: row count, totals and averages of the charted values, the top category of each chart.
- **Every chart** at full width with a one-line caption written from its numbers ("Top: Electrical (12,495). 25,575 in total across 3 categories.").
- **Optional plain-English summary** of 3 to 6 sentences, written by a model that sees only the KPIs and chart values, never the raw rows, and is told never to invent a number.
- **Data preview**: the first rows in a table, the charted fields first, up to 7 columns.

The PDF is A4 with page numbers and embeds the same font as the charts. The HTML report is one self-contained file with crisp SVG charts, good for sharing a link, embedding, or printing to PDF from a browser with your own header.

### Pricing

Pay per event, nothing else:

| Event | Price | When |
|---|---|---|
| Chart rendered | $0.03 | Once per chart that had data to draw, whatever image formats you chose |
| Report generated | $0.40 | Once per run that produced a report (PDF, HTML or both) |
| Webhook delivery | $0.02 | Only on a confirmed HTTP 2xx from your endpoint |

A chart with nothing to draw (no numeric values, a misspelled field) is a warning in the log and is never charged. Concrete examples:

- **A weekly client report**, 4 charts plus a PDF: 4 x $0.03 + $0.40 = **$0.52 a week**, about $2.25 a month.
- **A chart in Slack every morning**: $0.03 a day, **about $0.90 a month**.
- **Ten charts and an HTML report for a board pack**: $0.30 + $0.40 = **$0.70**.

The optional AI summary also bills the model tokens to your Apify account through Apify's official [OpenRouter proxy](https://apify.com/apify/openrouter), about $0.002 per report on the default model (Claude Haiku 4.5); free Apify plans pay 10x the token rate. Platform compute for a typical run is under a cent.

### For AI agents

This Actor is agent-ready: pay per event, limited permissions, no standby mode, so agents can discover it through Apify's MCP server and pay via x402 without an Apify account. The input is plain JSON (field names, chart types, a title) and the output is a list of rows with direct URLs to PNG, SVG, PDF and HTML files, which an agent can return to its user or post onward. Use `data` for rows the agent already holds, `datasetId` for the output of a previous Actor run, or `fileUrl` for a file it found.

### Limits

- Up to 20 charts per run, 50,000 rows loaded, files up to 100 MB.
- Up to 60 categories per chart (the rest folded into "Other"), 10 series, 5,000 scatter points.
- Chart size 320 to 2,000 px wide, 200 to 1,400 px tall, PNG at 1x to 3x.
- Text renders in DejaVu Sans, which covers Latin, Greek and Cyrillic scripts. Other scripts (for example Chinese or Arabic) are not rendered in the images.

### The rest of the toolkit

- [Dataset Cleaner & Exporter](https://apify.com/nerolabs/dataset-cleaner-exporter): dedupe (exact, normalized or fuzzy), flatten nested JSON, clean emails, phones and URLs, then export CSV or Excel.
- [Dataset Filter & Transform](https://apify.com/nerolabs/dataset-filter-transform): keep the rows you want and reshape the fields (dates, replace, split, hash, 25 ops), sort, dedupe, limit.
- [Dataset Join & Merge](https://apify.com/nerolabs/dataset-join-merge): VLOOKUP-style joins and unions across two datasets, files or Google Sheets on a key field.
- [Dataset Aggregate, Group By & Pivot](https://apify.com/nerolabs/dataset-aggregate-pivot): counts, sums, averages and pivot tables per group.
- [Dataset Diff & Change Detector](https://apify.com/nerolabs/dataset-diff-detector): what was added, removed or changed since last time.
- [Dataset AI Enrich](https://apify.com/nerolabs/dataset-ai-enrich): add LLM-generated columns (classify, extract, summarise) to every row, no API key needed.
- **Dataset Charts & Report** (this one): chart images (PNG, SVG) and a PDF or HTML report from any data.
- [Dataset to Postgres, Supabase & MySQL](https://apify.com/nerolabs/dataset-to-database): write the rows straight into a database table, creating it if needed.
- [Dataset to REST API](https://apify.com/nerolabs/dataset-to-rest-api): send every row to any API as its own request, with templating and auth presets.
- [Actor Pipeline Runner](https://apify.com/nerolabs/actor-pipeline-runner): chain several of these together in one run, each step fed the previous step's dataset.

A common pipeline: a scraper, then Cleaner, then Filter & Transform, then Join to enrich from a sheet, then Aggregate for the weekly summary, with Diff watching what changed and Charts & Report turning the numbers into the Monday PDF. Pipeline Runner runs that whole chain in one call.

### FAQ

**Does it aggregate my data or do I have to pre-aggregate?**
It aggregates inside each chart: rows are grouped by `x` and the `y` values summed, counted or averaged as you choose. Feed it raw scraper output directly. If you want the aggregated numbers as a dataset rather than a picture, that is what [Dataset Aggregate & Pivot](https://apify.com/nerolabs/dataset-aggregate-pivot) is for; the two chain well.

**My dates are strings like "14/03/2026". Will the time axis work?**
Yes. ISO dates, Unix timestamps, "March 14, 2026" and day-first "14/03/2026" are all read. Ambiguous slash dates are read month-first, the way a US spreadsheet would. Buckets are chosen from the date span (days, weeks, months or years) unless you set `timeUnit`.

**Can I brand the charts?**
Set `accentColor` for single-series charts, `color` per chart, and `theme` light or dark. Multi-series charts use a fixed ten-colour palette chosen to stay distinguishable for colour-blind readers.

**Is the summary reliable?**
It only ever sees the KPIs and the aggregated points the charts already show, with the instruction to use nothing else and never invent a number. Read it before you send it, as you would any summary. It is off by default.

**Can I get the raw SVG to edit?**
Yes, add `svg` to the image formats. The SVG is the exact drawing, editable in Figma, Illustrator or Inkscape.

**Something did not draw. Why?**
The run log names the chart and the reason: a misspelled field (the log lists the fields that do exist), a `y` field with no numbers in it, or an `x` field that is blank in every row. Nothing is charged for a chart that did not draw.

**Did this save you a spreadsheet session?** A short review on this page helps other people find it, and tells me which chart types to improve next.

# Actor input Schema

## `datasetId` (type: `string`):

Pick an existing Apify dataset (for example the output of any scraper run). Use this OR 'File URL' OR 'Data (inline)' below. Declaring it this way lets the Actor run with limited permissions: it may read the dataset you point at and nothing else on your account.

## `fileUrl` (type: `string`):

Instead of a dataset, download the rows from a public link: a CSV or TSV file, an Excel .xlsx file (first sheet, header row), a JSON array or JSON Lines file, or a Google Sheet (paste the normal sheet link with sharing set to 'Anyone with the link can view'). Format detected automatically. Up to 100 MB.

## `fileFormat` (type: `string`):

Only needed if automatic detection gets the file URL's format wrong.

## `data` (type: `array`):

A JSON array of records to chart, for ad-hoc data instead of a dataset ID or file URL.

## `maxRows` (type: `integer`):

A cost and memory guard. Rows beyond this are not loaded. Hard ceiling 50,000 per run.

## `charts` (type: `array`):

A JSON list of charts, up to 20. Each: {"type": bar | horizontalBar | stackedBar | line | area | pie | donut | scatter, "title", "x": field, "y": field (omit to count rows), "series": field to split into colours, "aggregate": sum | count | mean | median | min | max | distinct, "sort": desc | asc | x, "limit": top N categories (the rest become 'Other'), "timeUnit": auto | day | week | month | quarter | year, "xTitle", "yTitle", "color": hex, "yFormat": d3 format like ',.0f' or '$,.2f'}. Only 'x' is required.

## `width` (type: `integer`):

The drawing area width. The PNG is rendered at this width times 'PNG scale'.

## `height` (type: `integer`):

The drawing area height.

## `theme` (type: `string`):

Light (white background) or dark (near-black background) charts and HTML report.

## `accentColor` (type: `string`):

Hex colour for single-series charts, e.g. #2a78d6. Multi-series charts use a fixed 10-colour palette. A chart's own 'color' overrides this.

## `imageFormats` (type: `array`):

PNG (default, for Slack, email, docs and slides) and/or SVG (crisp at any size, editable).

## `scale` (type: `integer`):

1 = the chart width in pixels, 2 = twice that (sharp on retina screens, the default), 3 = print quality.

## `generateReport` (type: `boolean`):

On (default): build the report in the formats below. Off: charts only.

## `reportTitle` (type: `string`):

Shown at the top of the report. Defaults to the first chart's title or 'Data report'.

## `reportSubtitle` (type: `string`):

Optional second line, for example the client name or the period covered.

## `reportFormats` (type: `array`):

PDF (A4, ready to send) and/or HTML (a single self-contained page with crisp SVG charts, good for sharing a link or printing).

## `tableRows` (type: `integer`):

How many of the first rows to show in the report's data table (up to 7 columns, the charted fields first). 0 hides the table.

## `aiSummary` (type: `boolean`):

Off by default. On: a model writes 3 to 6 sentences from the KPIs and chart values only, never from the raw rows, and never invents numbers. The model tokens (about $0.002 per report on the default model) are billed to your Apify account through Apify's official OpenRouter proxy; no API key is needed. Free Apify plans pay 10x the token rate.

## `aiModel` (type: `string`):

Any OpenRouter model id. Claude Haiku 4.5 is the default and is plenty for a summary.

## `summaryInstructions` (type: `string`):

Extra guidance for the summary: the audience, the language to write in, what to focus on.

## `webhookUrl` (type: `string`):

Optional. If set, the chart and report links, KPIs and captions are POSTed here as JSON the moment the run finishes. Works with a Zapier/Make/n8n catch-hook, your own API, or a Slack incoming webhook. Only charged on a confirmed HTTP 2xx; a failed delivery is a warning and costs nothing.

## Actor input object example

```json
{
  "fileFormat": "auto",
  "data": [
    {
      "date": "2026-01-14",
      "region": "North",
      "category": "Electrical",
      "revenue": 1840,
      "units": 12
    },
    {
      "date": "2026-01-27",
      "region": "South",
      "category": "Plumbing",
      "revenue": 960,
      "units": 7
    },
    {
      "date": "2026-02-03",
      "region": "North",
      "category": "Electrical",
      "revenue": 2210,
      "units": 15
    },
    {
      "date": "2026-02-18",
      "region": "East",
      "category": "Roofing",
      "revenue": 3120,
      "units": 4
    },
    {
      "date": "2026-02-25",
      "region": "South",
      "category": "Electrical",
      "revenue": 1275,
      "units": 9
    },
    {
      "date": "2026-03-06",
      "region": "West",
      "category": "Plumbing",
      "revenue": 1430,
      "units": 11
    },
    {
      "date": "2026-03-19",
      "region": "North",
      "category": "Roofing",
      "revenue": 2890,
      "units": 3
    },
    {
      "date": "2026-03-28",
      "region": "East",
      "category": "Electrical",
      "revenue": 1990,
      "units": 13
    },
    {
      "date": "2026-04-09",
      "region": "West",
      "category": "Electrical",
      "revenue": 2450,
      "units": 16
    },
    {
      "date": "2026-04-21",
      "region": "South",
      "category": "Roofing",
      "revenue": 3560,
      "units": 5
    },
    {
      "date": "2026-05-02",
      "region": "North",
      "category": "Plumbing",
      "revenue": 1120,
      "units": 8
    },
    {
      "date": "2026-05-17",
      "region": "East",
      "category": "Electrical",
      "revenue": 2730,
      "units": 18
    }
  ],
  "maxRows": 5000,
  "charts": [
    {
      "type": "bar",
      "title": "Revenue by category",
      "x": "category",
      "y": "revenue",
      "aggregate": "sum"
    },
    {
      "type": "line",
      "title": "Revenue by month",
      "x": "date",
      "y": "revenue",
      "aggregate": "sum",
      "timeUnit": "month"
    },
    {
      "type": "donut",
      "title": "Jobs by region",
      "x": "region",
      "aggregate": "count"
    }
  ],
  "width": 800,
  "height": 450,
  "theme": "light",
  "imageFormats": [
    "png",
    "svg"
  ],
  "scale": 2,
  "generateReport": true,
  "reportTitle": "Jobs and revenue, January to May 2026",
  "reportFormats": [
    "pdf",
    "html"
  ],
  "tableRows": 15,
  "aiSummary": false,
  "aiModel": "anthropic/claude-haiku-4.5"
}
```

# Actor output Schema

## `results` (type: `string`):

One row per chart rendered (with PNG and SVG links) plus one row for the report (with PDF and HTML links).

## `firstChartPng` (type: `string`):

The first chart as a PNG image. Further charts are chart-2.png, chart-3.png and so on.

## `pdfReport` (type: `string`):

The report as a PDF, if requested.

## `htmlReport` (type: `string`):

The report as a single self-contained HTML page, if requested.

## `runSummary` (type: `string`):

Counts, KPIs, the charts rendered, warnings and every download link.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "data": [
        {
            "date": "2026-01-14",
            "region": "North",
            "category": "Electrical",
            "revenue": 1840,
            "units": 12
        },
        {
            "date": "2026-01-27",
            "region": "South",
            "category": "Plumbing",
            "revenue": 960,
            "units": 7
        },
        {
            "date": "2026-02-03",
            "region": "North",
            "category": "Electrical",
            "revenue": 2210,
            "units": 15
        },
        {
            "date": "2026-02-18",
            "region": "East",
            "category": "Roofing",
            "revenue": 3120,
            "units": 4
        },
        {
            "date": "2026-02-25",
            "region": "South",
            "category": "Electrical",
            "revenue": 1275,
            "units": 9
        },
        {
            "date": "2026-03-06",
            "region": "West",
            "category": "Plumbing",
            "revenue": 1430,
            "units": 11
        },
        {
            "date": "2026-03-19",
            "region": "North",
            "category": "Roofing",
            "revenue": 2890,
            "units": 3
        },
        {
            "date": "2026-03-28",
            "region": "East",
            "category": "Electrical",
            "revenue": 1990,
            "units": 13
        },
        {
            "date": "2026-04-09",
            "region": "West",
            "category": "Electrical",
            "revenue": 2450,
            "units": 16
        },
        {
            "date": "2026-04-21",
            "region": "South",
            "category": "Roofing",
            "revenue": 3560,
            "units": 5
        },
        {
            "date": "2026-05-02",
            "region": "North",
            "category": "Plumbing",
            "revenue": 1120,
            "units": 8
        },
        {
            "date": "2026-05-17",
            "region": "East",
            "category": "Electrical",
            "revenue": 2730,
            "units": 18
        }
    ],
    "charts": [
        {
            "type": "bar",
            "title": "Revenue by category",
            "x": "category",
            "y": "revenue",
            "aggregate": "sum"
        },
        {
            "type": "line",
            "title": "Revenue by month",
            "x": "date",
            "y": "revenue",
            "aggregate": "sum",
            "timeUnit": "month"
        },
        {
            "type": "donut",
            "title": "Jobs by region",
            "x": "region",
            "aggregate": "count"
        }
    ],
    "imageFormats": [
        "png",
        "svg"
    ],
    "reportTitle": "Jobs and revenue, January to May 2026",
    "reportFormats": [
        "pdf",
        "html"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("nerolabs/dataset-charts-report").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "data": [
        {
            "date": "2026-01-14",
            "region": "North",
            "category": "Electrical",
            "revenue": 1840,
            "units": 12,
        },
        {
            "date": "2026-01-27",
            "region": "South",
            "category": "Plumbing",
            "revenue": 960,
            "units": 7,
        },
        {
            "date": "2026-02-03",
            "region": "North",
            "category": "Electrical",
            "revenue": 2210,
            "units": 15,
        },
        {
            "date": "2026-02-18",
            "region": "East",
            "category": "Roofing",
            "revenue": 3120,
            "units": 4,
        },
        {
            "date": "2026-02-25",
            "region": "South",
            "category": "Electrical",
            "revenue": 1275,
            "units": 9,
        },
        {
            "date": "2026-03-06",
            "region": "West",
            "category": "Plumbing",
            "revenue": 1430,
            "units": 11,
        },
        {
            "date": "2026-03-19",
            "region": "North",
            "category": "Roofing",
            "revenue": 2890,
            "units": 3,
        },
        {
            "date": "2026-03-28",
            "region": "East",
            "category": "Electrical",
            "revenue": 1990,
            "units": 13,
        },
        {
            "date": "2026-04-09",
            "region": "West",
            "category": "Electrical",
            "revenue": 2450,
            "units": 16,
        },
        {
            "date": "2026-04-21",
            "region": "South",
            "category": "Roofing",
            "revenue": 3560,
            "units": 5,
        },
        {
            "date": "2026-05-02",
            "region": "North",
            "category": "Plumbing",
            "revenue": 1120,
            "units": 8,
        },
        {
            "date": "2026-05-17",
            "region": "East",
            "category": "Electrical",
            "revenue": 2730,
            "units": 18,
        },
    ],
    "charts": [
        {
            "type": "bar",
            "title": "Revenue by category",
            "x": "category",
            "y": "revenue",
            "aggregate": "sum",
        },
        {
            "type": "line",
            "title": "Revenue by month",
            "x": "date",
            "y": "revenue",
            "aggregate": "sum",
            "timeUnit": "month",
        },
        {
            "type": "donut",
            "title": "Jobs by region",
            "x": "region",
            "aggregate": "count",
        },
    ],
    "imageFormats": [
        "png",
        "svg",
    ],
    "reportTitle": "Jobs and revenue, January to May 2026",
    "reportFormats": [
        "pdf",
        "html",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("nerolabs/dataset-charts-report").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "data": [
    {
      "date": "2026-01-14",
      "region": "North",
      "category": "Electrical",
      "revenue": 1840,
      "units": 12
    },
    {
      "date": "2026-01-27",
      "region": "South",
      "category": "Plumbing",
      "revenue": 960,
      "units": 7
    },
    {
      "date": "2026-02-03",
      "region": "North",
      "category": "Electrical",
      "revenue": 2210,
      "units": 15
    },
    {
      "date": "2026-02-18",
      "region": "East",
      "category": "Roofing",
      "revenue": 3120,
      "units": 4
    },
    {
      "date": "2026-02-25",
      "region": "South",
      "category": "Electrical",
      "revenue": 1275,
      "units": 9
    },
    {
      "date": "2026-03-06",
      "region": "West",
      "category": "Plumbing",
      "revenue": 1430,
      "units": 11
    },
    {
      "date": "2026-03-19",
      "region": "North",
      "category": "Roofing",
      "revenue": 2890,
      "units": 3
    },
    {
      "date": "2026-03-28",
      "region": "East",
      "category": "Electrical",
      "revenue": 1990,
      "units": 13
    },
    {
      "date": "2026-04-09",
      "region": "West",
      "category": "Electrical",
      "revenue": 2450,
      "units": 16
    },
    {
      "date": "2026-04-21",
      "region": "South",
      "category": "Roofing",
      "revenue": 3560,
      "units": 5
    },
    {
      "date": "2026-05-02",
      "region": "North",
      "category": "Plumbing",
      "revenue": 1120,
      "units": 8
    },
    {
      "date": "2026-05-17",
      "region": "East",
      "category": "Electrical",
      "revenue": 2730,
      "units": 18
    }
  ],
  "charts": [
    {
      "type": "bar",
      "title": "Revenue by category",
      "x": "category",
      "y": "revenue",
      "aggregate": "sum"
    },
    {
      "type": "line",
      "title": "Revenue by month",
      "x": "date",
      "y": "revenue",
      "aggregate": "sum",
      "timeUnit": "month"
    },
    {
      "type": "donut",
      "title": "Jobs by region",
      "x": "region",
      "aggregate": "count"
    }
  ],
  "imageFormats": [
    "png",
    "svg"
  ],
  "reportTitle": "Jobs and revenue, January to May 2026",
  "reportFormats": [
    "pdf",
    "html"
  ]
}' |
apify call nerolabs/dataset-charts-report --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nerolabs/dataset-charts-report"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/ogAfwDT99ceBUMBKk/builds/2QMNnpGxZRCLgix3x/openapi.json
