# JSON to CSV Converter (`automation-lab/json-to-csv-converter`) Actor

Convert pasted JSON, public JSON files, and API responses into flattened CSV rows with configurable paths, columns, arrays, and delimiters.

- **URL**: https://apify.com/automation-lab/json-to-csv-converter.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#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

## JSON to CSV Converter

Turn pasted JSON, public JSON files, and API responses into a clean CSV file with an Apify dataset summary for every converted source.

This **JSON to CSV converter** handles nested objects, record paths, arrays, selected columns, and spreadsheet-friendly delimiters without requiring Python or a local conversion tool.

Use it for one-off exports or schedule it as a repeatable step in a data pipeline.

### What does JSON to CSV Converter do?

The Actor can:

- parse JSON pasted directly into the input;
- download JSON from up to 20 public HTTP(S) URLs;
- select records from nested responses with a dot or bracket path;
- flatten nested objects into columns such as `customer.name`;
- stringify, join, or expand arrays;
- preserve a requested column order;
- write comma, semicolon, tab, or pipe-delimited files;
- add a UTF-8 BOM for Excel;
- stop at a configured row limit;
- fail closed or skip individual invalid sources;
- save the finished file as `OUTPUT.csv`;
- push one dataset summary with a row preview for every converted source.

No browser or proxy is used.

### Who is this converter for?

#### Data analysts

Convert API snapshots and vendor exports into CSV for Excel, Google Sheets, Power BI, or Tableau.

#### Developers

Replace a small JSON-to-CSV Python script with an API-callable Actor that has scheduling, logs, storage, and webhooks.

#### Operations teams

Normalize recurring JSON feeds into a predictable set of columns before importing them into a CRM or reporting workflow.

#### AI agents

Call the Actor through Apify MCP, then retrieve a CSV artifact or structured source summary for the next tool step.

### Why use it on Apify?

A browser-only online converter is useful for a small manual file.

This Actor is designed for repeatable automation:

1. inputs are saved as reusable Tasks;
2. runs can be scheduled;
3. results have stable API links;
4. each converted source has a typed dataset summary and row preview;
5. webhooks can trigger downstream systems;
6. invalid inputs produce explicit run failures instead of silent partial files.

Input data is processed only for the run and stored in the run's Apify storage.

### Getting started

1. Open the Actor input page.
2. Paste JSON into **Paste JSON**, or add one or more public JSON URLs.
3. Set **Record path** when the records are nested inside an API envelope.
4. Choose how nested objects and arrays should be handled.
5. Optionally list the exact columns and their order.
6. Set a safe **Maximum output rows** value.
7. Click **Start**.
8. Download **OUTPUT.csv** from the Output tab.
9. Use the default dataset when a downstream integration needs source-level counts, columns, and row previews.

The prefilled input converts two real biographical names under the `records` path and succeeds without network access.

### Input parameters

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `jsonText` | string | prefilled JSON | JSON array, object, or response pasted as text. |
| `jsonUrls` | array | empty | Up to 20 public HTTP(S) JSON file or API URLs. |
| `recordPath` | string | `records` | Dot/bracket path to the records, such as `data.items` or `[1]`. Empty means the JSON root. |
| `flatten` | boolean | `true` | Flatten nested objects into named columns. |
| `flattenSeparator` | string | `.` | Separator between nested field names. |
| `arrayMode` | string | `stringify` | Store arrays as JSON, join values, or expand them into rows. |
| `arrayJoinSeparator` | string | `|` | Separator used by `join` array mode. |
| `columns` | string\[] | all discovered | Ordered allowlist of output columns. |
| `delimiter` | string | `comma` | `comma`, `semicolon`, `tab`, or `pipe`. |
| `includeBom` | boolean | `false` | Add a UTF-8 BOM for Excel compatibility. |
| `maxRows` | integer | `10000` | Global row limit from 1 to 100,000. |
| `onError` | string | `fail` | Fail the run or skip bad sources. |

Provide at least one of `jsonText` or `jsonUrls`.

When both are provided, the inline JSON is processed first and every source uses the same conversion settings.

### Selecting records with `recordPath`

Many APIs wrap records in an envelope.

Given:

```json
{
  "meta": { "page": 1 },
  "data": {
    "items": [
      { "id": 101, "status": "open" },
      { "id": 102, "status": "closed" }
    ]
  }
}
```

Use:

```json
{
  "recordPath": "data.items"
}
```

Bracket notation is also supported:

- `[1]` selects the second element of a top-level array;
- `results[0].items` selects a nested array;
- `data["items"]` selects a named property.

A missing path fails with the exact path segment that could not be resolved.

### Flattening nested JSON

With `flatten: true`, this record:

```json
{
  "id": 1,
  "customer": {
    "name": "Ada Lovelace",
    "country": "GB"
  }
}
```

becomes these CSV columns:

```text
id,customer.name,customer.country
```

Change `flattenSeparator` to `_` to produce `customer_name` instead.

With flattening disabled, nested objects are stored as JSON strings in their parent column.

### Handling arrays

#### Stringify

`stringify` preserves the complete array as compact JSON in one cell.

This is the safest default for arrays of objects.

#### Join

`join` combines array values in one cell with `arrayJoinSeparator`.

Objects inside an array are JSON-encoded before joining.

#### Expand

`expand` creates one row per array value.

When several columns contain arrays, expansion produces their Cartesian combinations.

Use `maxRows` to bound that result.

A single source cannot expand beyond 100,000 intermediate rows.

### Choosing and ordering columns

Leave `columns` empty to use every field in first-seen order.

Provide `columns` when a downstream system expects a stable schema:

```json
{
  "columns": [
    "id",
    "customer.name",
    "status",
    "updated_at"
  ]
}
```

Missing requested fields are written as empty CSV cells and `null` values in dataset row previews.

Extra source fields are omitted.

### Output

Each successful run creates three outputs:

1. **CSV file** — `OUTPUT.csv` in the default key-value store;
2. **source summaries** — one item per converted source in the default dataset;
3. **run summary** — `OUTPUT` in the default key-value store.

A representative dataset item is:

```json
{
  "source": "https://api.worldbank.org/v2/country/USA/indicator/NY.GDP.MKTP.CD?format=json&per_page=10",
  "rowCount": 10,
  "columns": ["country.value", "indicator.value", "date", "value"],
  "preview": [
    {
      "country.value": "United States",
      "indicator.value": "GDP (current US$)",
      "date": "2025",
      "value": 30769700000000
    }
  ]
}
```

| Output field | Meaning |
| --- | --- |
| `source` | `inline:jsonText` or the public URL converted successfully. |
| `rowCount` | Number of rows this source contributed to `OUTPUT.csv`. |
| `columns` | Ordered CSV columns shared by the final file. |
| `preview` | Up to three normalized rows from this source. |

The run summary includes total row and column counts, column names, input and converted source counts, skipped-source errors, and a direct CSV download URL.

### CSV correctness and types

The renderer follows common RFC 4180 conventions:

- fields containing delimiters, quotes, or newlines are quoted;
- embedded quotes are doubled;
- rows use CRLF line endings;
- `null` and missing values become empty cells;
- numbers and booleans remain typed in dataset row previews;
- the CSV file contains their textual form.

The downloadable filename is always `OUTPUT.csv`, including when tab or pipe is selected.

### How much does it cost to convert JSON to CSV?

Pricing has one **$0.0005 start event** per run plus one event for each JSON source converted successfully.

Pasted `jsonText` counts as one source. Each successful `jsonUrls` entry counts as one source, regardless of how many rows it contains. Failed, empty, or skipped sources do not emit the source event.

Current source prices decrease by Apify subscription tier:

| Tier | Price per converted source |
| --- | ---: |
| Free | $0.0184 |
| Bronze | $0.016 |
| Silver | $0.01248 |
| Gold | $0.0096 |
| Platinum | $0.0064 |
| Diamond | $0.00448 |

Examples before any Apify platform-usage tax:

| Sources in one run | Free tier | Bronze tier |
| ---: | ---: | ---: |
| 1 | $0.01890 | $0.01650 |
| 5 | $0.09250 | $0.08050 |
| 20 | $0.36850 | $0.32050 |

A 1,000-row file and a 10-row file each use one source event when converted successfully.

### Public URL safety and limits

Only `http://` and `https://` URLs are accepted.

The Actor rejects:

- URLs containing embedded usernames or passwords;
- localhost and private-network destinations;
- redirects to private-network destinations;
- responses larger than 10 MB;
- more than five redirects;
- non-success HTTP responses;
- invalid JSON response bodies.

Each request has a 30-second timeout.

HTTP 429 and 5xx responses are retried twice with bounded backoff.

The Actor does not use an Apify proxy and cannot access authenticated or private APIs.

### Error handling

The default `onError: fail` behavior is best for trustworthy pipelines.

The run fails when any source is invalid, unavailable, oversized, or missing the selected record path.

Use `onError: skip` only when partial output is acceptable.

Skipped source names and error messages are written to the `OUTPUT` summary.

If every source fails or produces no rows, the run fails even in skip mode.

No source event is emitted for failed, empty, or skipped input.

### Scheduling recurring conversions

Create an Apify Task with a stable public API URL and fixed columns.

Then:

1. set an hourly, daily, or weekly schedule;
2. configure a webhook for `ACTOR.RUN.SUCCEEDED`;
3. send the CSV download URL or source-summary dataset ID to your destination;
4. retain run storage according to your Apify plan;
5. compare successive datasets with your preferred diff workflow.

The Actor converts the current response on every run; it does not maintain change history or send alerts by itself.

### Spreadsheet and data-pipeline workflows

Common patterns include:

- JSON API → scheduled Actor Task → Google Sheets integration;
- vendor JSON file → `OUTPUT.csv` → S3 or cloud drive;
- webhook payload archive → `OUTPUT.csv` → data warehouse;
- World Bank API → selected indicators → BI dashboard;
- GitHub issues API → joined labels → recurring operations report;
- Apify MCP → conversion run → CSV link returned to an AI assistant.

Use `columns` to prevent schema drift when an upstream API adds fields.

### API usage with cURL

Start a run and wait for completion:

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~json-to-csv-converter/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonUrls": [{"url": "https://api.github.com/repos/apify/apify-sdk-js/releases?per_page=5"}],
    "recordPath": "",
    "columns": ["tag_name", "name", "published_at", "html_url"],
    "maxRows": 5
  }'
```

The synchronous dataset endpoint returns one source summary per successful input. Retrieve `OUTPUT.csv` for all normalized rows.

Use the run's default key-value store to retrieve `OUTPUT.csv`.

### API usage with JavaScript

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });

const run = await client.actor('automation-lab/json-to-csv-converter').call({
    jsonText: JSON.stringify({ records: [{ id: 1, status: 'active' }] }),
    recordPath: 'records',
    columns: ['id', 'status'],
});

const summary = await client
    .keyValueStore(run.defaultKeyValueStoreId)
    .getRecord('OUTPUT');

console.log(summary.value.csvDownloadUrl);
```

### API usage with Python

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])

run = client.actor("automation-lab/json-to-csv-converter").call(run_input={
    "jsonUrls": [{
        "url": "https://api.worldbank.org/v2/country/USA/indicator/NY.GDP.MKTP.CD?format=json&per_page=10"
    }],
    "recordPath": "[1]",
    "columns": ["country.value", "date", "value"],
    "maxRows": 10,
})

record = client.key_value_store(run["defaultKeyValueStoreId"]).get_record("OUTPUT.csv")
with open("world-bank-gdp.csv", "wb") as file:
    file.write(record["value"])
```

### Use with Apify MCP

#### Claude Code

Add the Actor to Claude Code:

```bash
claude mcp add --transport http apify \
  "https://mcp.apify.com?tools=automation-lab/json-to-csv-converter"
```

#### Claude Desktop, Cursor, and VS Code

Claude Desktop, Cursor, and VS Code clients can use this HTTP MCP configuration:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=automation-lab/json-to-csv-converter"
    }
  }
}
```

Example prompts:

- “Convert this public World Bank JSON URL to CSV and keep country, date, and value.”
- “Flatten the pasted response at `data.items`, join tags, and return the CSV download URL.”
- “Create an Apify Task that exports these GitHub issues to CSV every Monday.”

### Legality and responsible use

Only submit data that you are authorized to process.

For public URLs, respect the source's terms, access policies, rate limits, privacy requirements, and applicable law.

Do not use this Actor to bypass authentication or access controls.

Avoid placing secrets in URL query strings because run inputs and logs may be retained in your Apify account.

For sensitive inline JSON, configure appropriate storage retention and access controls.

### Limitations

- JSON Lines / NDJSON is not supported; input must be one valid JSON document.
- Each inline or downloaded source is limited to 10 MB.
- A run accepts at most 20 URLs and 100,000 output rows.
- Input sources are processed sequentially.
- URLs must be publicly reachable without credentials.
- `expand` can multiply rows when several arrays exist in one record.
- Object keys are used as column names; duplicate paths after custom separator changes may overwrite one another.
- CSV cannot preserve JSON type distinctions as fully as the typed values shown in dataset previews.
- The Actor does not write directly to Google Sheets or a database.
- The Actor does not monitor changes or send alerts without an Apify schedule and downstream integration.

### Troubleshooting

#### “Provide jsonText or at least one jsonUrls entry”

Add pasted JSON or at least one public JSON URL.

#### “Record path was not found”

Inspect the response shape and set the path to the array or object containing records.

Use an empty path when the JSON root is already the desired array.

#### A URL works in my browser but fails here

Confirm it is public, returns JSON without cookies or authentication, stays below 10 MB, and does not redirect to a private address.

#### The CSV has one row instead of many

Set `recordPath` to the array inside the response rather than its parent object.

#### The CSV has too many rows

Switch array handling from `expand` to `stringify` or `join`, or lower `maxRows`.

#### Excel displays non-English characters incorrectly

Enable `includeBom`.

#### I need stable columns between runs

Supply an explicit ordered `columns` list.

### FAQ

#### Can I convert a local JSON file?

Upload the file somewhere publicly reachable or paste its content into `jsonText`.

Apify key-value-store record URLs also work when they are publicly accessible.

#### Can I combine multiple JSON files?

Yes. Add up to 20 URLs. Their converted rows are appended in source order and share one CSV header.

#### Does it support a top-level JSON object?

Yes. A single object becomes one CSV row unless `recordPath` selects an array.

#### Does it preserve nested objects?

Yes. Flatten them into named columns or disable flattening to store them as JSON strings.

#### Are failed sources charged?

No source event is emitted for input that fails parsing or fetching, or produces no accepted rows.

The one-time run start event still applies.

#### Can it produce TSV?

Yes. Select the tab delimiter. The storage key remains `OUTPUT.csv`.

#### Can it infer and enforce data types?

Numbers and booleans remain typed in Apify dataset row previews, but this Actor does not infer a separate schema or validate business-level types.

#### Is a proxy required?

No. The Actor uses direct requests to public JSON URLs only.

### Related Automation Lab Actors

- [XML to JSON Converter](https://apify.com/automation-lab/xml-to-json-converter) for XML ingestion workflows.
- [VCF Contact File Parser](https://apify.com/automation-lab/vcf-contact-file-parser) for contact-file normalization.
- [CSV Diff Tool](https://apify.com/automation-lab/csv-diff-tool) for comparing recurring tabular exports.
- [Dataset Dedup](https://apify.com/automation-lab/dataset-dedup) for removing duplicate records in downstream datasets.

Choose JSON to CSV Converter when the source is already valid JSON and the goal is a normalized tabular export.

# Actor input Schema

## `jsonText` (type: `string`):

A JSON array, object, or API response pasted as text. You can combine it with JSON URLs.

## `jsonUrls` (type: `array`):

Up to 20 public HTTP(S) URLs that return JSON. Each response is converted with the same settings.

## `recordPath` (type: `string`):

Optional dot/bracket path to the array or object to convert, for example records, data.items, or \[1]. Leave empty to use the JSON root.

## `flatten` (type: `boolean`):

Turn nested fields into columns such as customer.name. When disabled, nested objects are stored as JSON strings.

## `flattenSeparator` (type: `string`):

Text placed between nested field names when flattening.

## `arrayMode` (type: `string`):

Stringify arrays as JSON, join their values into one cell, or expand array values into separate rows.

## `arrayJoinSeparator` (type: `string`):

Separator used when Array handling is set to Join.

## `columns` (type: `array`):

Optional ordered list of flattened column names. Leave empty to include every discovered column.

## `delimiter` (type: `string`):

Choose comma, semicolon, tab (TSV), or pipe output.

## `includeBom` (type: `boolean`):

Add a UTF-8 byte-order mark so non-ASCII text opens reliably in some Excel versions.

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

Stop after this many converted rows across all sources. Array expansion counts toward this limit.

## `onError` (type: `string`):

Fail immediately on invalid JSON or fetch errors, or skip bad sources and list them in the OUTPUT summary.

## Actor input object example

```json
{
  "jsonText": "{\"records\":[{\"id\":1,\"customer\":{\"name\":\"Ada Lovelace\"},\"status\":\"active\"},{\"id\":2,\"customer\":{\"name\":\"Grace Hopper\"},\"status\":\"active\"}]}",
  "jsonUrls": [],
  "recordPath": "records",
  "flatten": true,
  "flattenSeparator": ".",
  "arrayMode": "stringify",
  "arrayJoinSeparator": " | ",
  "delimiter": "comma",
  "includeBom": false,
  "maxRows": 20,
  "onError": "fail"
}
```

# Actor output Schema

## `convertedRows` (type: `string`):

Default dataset containing one typed summary and row preview for each converted JSON source.

## `csvFile` (type: `string`):

Direct link to the generated OUTPUT.csv file in the run key-value store.

## `summary` (type: `string`):

JSON summary with row and column counts, source count, column names, download URL, and skipped-source errors.

# 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 = {
    "jsonText": "{\"records\":[{\"id\":1,\"customer\":{\"name\":\"Ada Lovelace\"},\"status\":\"active\"},{\"id\":2,\"customer\":{\"name\":\"Grace Hopper\"},\"status\":\"active\"}]}",
    "jsonUrls": [],
    "recordPath": "records",
    "flatten": true,
    "flattenSeparator": ".",
    "arrayMode": "stringify",
    "arrayJoinSeparator": " | ",
    "delimiter": "comma",
    "includeBom": false,
    "maxRows": 20,
    "onError": "fail"
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/json-to-csv-converter").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 = {
    "jsonText": "{\"records\":[{\"id\":1,\"customer\":{\"name\":\"Ada Lovelace\"},\"status\":\"active\"},{\"id\":2,\"customer\":{\"name\":\"Grace Hopper\"},\"status\":\"active\"}]}",
    "jsonUrls": [],
    "recordPath": "records",
    "flatten": True,
    "flattenSeparator": ".",
    "arrayMode": "stringify",
    "arrayJoinSeparator": " | ",
    "delimiter": "comma",
    "includeBom": False,
    "maxRows": 20,
    "onError": "fail",
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/json-to-csv-converter").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 '{
  "jsonText": "{\\"records\\":[{\\"id\\":1,\\"customer\\":{\\"name\\":\\"Ada Lovelace\\"},\\"status\\":\\"active\\"},{\\"id\\":2,\\"customer\\":{\\"name\\":\\"Grace Hopper\\"},\\"status\\":\\"active\\"}]}",
  "jsonUrls": [],
  "recordPath": "records",
  "flatten": true,
  "flattenSeparator": ".",
  "arrayMode": "stringify",
  "arrayJoinSeparator": " | ",
  "delimiter": "comma",
  "includeBom": false,
  "maxRows": 20,
  "onError": "fail"
}' |
apify call automation-lab/json-to-csv-converter --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/json-to-csv-converter"
        }
    }
}

```

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/vO32fmfvIYEUculOr/builds/bqtnkEnj1mxjcvdhC/openapi.json
