JSON to CSV Converter - Flatten JSON to CSV, URL or Bulk avatar

JSON to CSV Converter - Flatten JSON to CSV, URL or Bulk

Pricing

$20.00 / 1,000 converted files

Go to Apify Store
JSON to CSV Converter - Flatten JSON to CSV, URL or Bulk

JSON to CSV Converter - Flatten JSON to CSV, URL or Bulk

Convert a JSON file by URL into a downloadable CSV - column union across records, proper quoting, Excel-friendly CRLF, one CSV per array for object-of-arrays input. Up to 25 files a run. $0.02 per file; failures are free.

Pricing

$20.00 / 1,000 converted files

Rating

0.0

(0)

Developer

Anthony Snider

Anthony Snider

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

8 hours ago

Last modified

Share

JSON to CSV Converter - Flatten JSON Arrays to CSV, by URL or Bulk

Turn a JSON file into a CSV you can open in Excel or load into anything. Point this at the URL of a JSON file - an array of objects, or an object whose values are arrays - and get back a real .csv file with a direct download URL, plus the row count, the column list, and a preview. Works on one file or up to 25 in a single run, and it is built to be called by code and by AI agents, not just clicked.

$0.02 per file converted. No subscription, no seat fee, no minimum. You pay for files you actually convert.

What problem this solves

JSON is what the API returned and CSV is what the spreadsheet, the BI tool, or the bulk-import form actually accepts. The conversion looks trivial until you meet real data: one record has a field the others do not, a value contains a comma, another contains a quote, a third contains a newline, and something is null. Get any of those wrong and you do not get an error - you get a CSV that opens with the columns silently shifted, and you find out three steps downstream.

This does the conversion as a hosted step you can call from a script, a workflow, or an agent, with the escaping handled properly and the output contract stable enough to build on. There are free JSON-to-CSV pages on the web; they are fine for one file you paste by hand. This is for the case where a machine does it, repeatedly, on files it did not inspect first - bulk input, a predictable record shape, a real file URL to hand onward, and failures that are reported rather than guessed through.

Who uses it

  • Data and ops engineers turning an API dump into something loadable.
  • Analysts who need an export as CSV for Excel, Sheets, or a BI tool.
  • AI agents handed a JSON link that need a spreadsheet file to pass along.
  • No-code / automation builders (Make, n8n, and similar) that can call a URL but cannot flatten and escape a JSON array themselves.
  • Anyone doing a bulk migration - hand it 25 JSON URLs, get 25 CSVs.

Quick start

{
"url": "https://graveyard.broke2builtai.com/assets/sample.json"
}

That is the whole minimum input. Everything else is optional.

All input options

FieldTypeRequiredWhat it does
urlstringyesDirect URL to the JSON file
urlsstring[]noExtra JSON URLs - up to 25 total per run
jsonstring | array | objectnoRaw JSON pasted directly, instead of (or alongside) a URL
delimiterstringnoColumn separator (default ,; use ; or \t)
maxRowsnumbernoCap data rows written per CSV (default 50000)
maxFileSizeMbnumbernoSize cap before a file is refused (default 50, max 200)

What you get back

This is a real run against the sample file above, on 2026-08-14 (previewRows trimmed to two entries here - the actual output carries five):

{
"url": "https://graveyard.broke2builtai.com/assets/sample.json",
"finalUrl": "https://graveyard.broke2builtai.com/assets/sample.json",
"status": 200,
"bytes": 1739,
"table": null,
"fileName": "output-1.csv",
"rowCount": 10,
"columns": ["sku", "product", "category", "unit_price", "stock", "restock_date", "supplier"],
"downloadUrl": "https://api.apify.com/v2/key-value-stores/be342064-8a47-445e-ada6-f69de19b4f23/records/output-1.csv",
"previewRows": [
{
"sku": "TEA-EG-100",
"product": "Earl Grey Tea",
"category": "Beverages",
"unit_price": "4.5",
"stock": "182",
"restock_date": "2026-08-20",
"supplier": "Bergamot & Co"
},
{
"sku": "MUG-CR-014",
"product": "Ceramic Mug 350ml",
"category": "Kitchenware",
"unit_price": "8",
"stock": "260",
"restock_date": "",
"supplier": "Kiln & Kin"
}
]
}

And downloadUrl is the actual CSV, which starts:

sku,product,category,unit_price,stock,restock_date,supplier
TEA-EG-100,Earl Grey Tea,Beverages,4.5,182,2026-08-20,Bergamot & Co
TEA-GR-200,Gunpowder Green Tea,Beverages,5.25,94,2026-08-22,Leaf Harbor
COF-ES-310,Espresso Roast Beans,Beverages,12.9,41,2026-08-18,Crema Works

Note the fourth record in the source has "restock_date": null and comes through as an empty cell, not the string null.

  • fileName / downloadUrl - the CSV itself, in your run's key-value store.
  • columns - the union of every key across all records, in first-seen order. A field that only appears in record 40 still becomes a column, empty for everyone else.
  • rowCount - data rows written, header excluded.
  • previewRows - the first five rows as objects, so you can eyeball the result without downloading the file.

One dataset item per CSV produced. A failed input returns { url, error } instead of throwing, so one bad link in a batch of 25 never kills the other 24 - and a failure is never charged.

Already have the JSON? Paste it

If the payload is already in hand - an agent holding an API response, a workflow step downstream of an HTTP node - you do not have to host it somewhere fetchable first. Pass it as json instead of url, either as a JSON string or as an already-parsed array:

{ "json": "[{\"id\":1,\"name\":\"Ada, Jr.\"},{\"id\":2,\"name\":\"Bo \\\"B\\\" Li\",\"extra\":true}]" }

Real output from that input - note the comma value quoted, the embedded quotes doubled, and extra unioned in as a column that only the second record has:

id,name,extra
1,"Ada, Jr.",
2,"Bo ""B"" Li",true

Pasted JSON goes through exactly the same checks as a fetched file - size cap, parse check, shape check. Arriving by a different door does not make an input more trusted.

You can pass url/urls and json in the same run; URLs are converted first, output files are numbered in order, and each conversion is charged once. One deliberate exception: the url field is prefilled with our sample file, so if you paste JSON and leave that prefill untouched, the sample is skipped rather than converted alongside your data - you asked for one conversion, you are charged for one. Put any real URL in the field and both are converted as you would expect.

Both input shapes

An array of objects produces one CSV, output-1.csv.

An object whose values are arrays produces one CSV per key - give it {"users": [...], "orders": [...]} and you get output-1-users.csv and output-1-orders.csv, each with its own dataset item. That is still one file converted, so it is one charge.

Escaping, specifically

Fields containing the delimiter, a double quote, or a line break are wrapped in quotes, and embedded quotes are doubled - RFC 4180, the dialect Excel and every CSV library expect. Lines end with CRLF, which is what keeps Excel on Windows from reading the whole file as a single row. Nested objects and arrays are written as their JSON text in the cell rather than being dropped or flattened into surprise columns.

Use it as an AI agent tool

This Actor is callable over Apify MCP, so an agent can produce a spreadsheet mid-conversation without you writing an integration. The shape an agent needs:

  • Tool: this Actor
  • Input: { "url": "<json url>" } - or { "json": [ ...records... ] } when the agent already holds the payload and has nowhere to host it
  • Returns: downloadUrl to a real CSV, plus rowCount, columns and a preview

From code:

curl -X POST "https://api.apify.com/v2/acts/EliAI~json-to-csv/runs?token=YOUR_APIFY_TOKEN" \
-H 'content-type: application/json' \
-d '{"url":"https://example.com/data.json"}'

Pricing, plainly

$0.02 per file converted (pay-per-event: file-converted). One event per source file, so an object holding five arrays produces five CSVs and is still one charge. A 25-file batch costs $0.50. There is no actor-start fee, no monthly fee, and a run that converts nothing costs nothing - failures are never billed.

Honest comparison

There are free JSON-to-CSV actors on the Apify store - anaselgamed/json-to-csv-converter and eloquent_mountain/json-to-csv-converter among them - and there are free converter pages all over the web. We have not audited how any of them handle the edge cases below, so treat this as a pointer, not a verdict: if a free converter produces a correct file for your data, use it.

What you are paying for here, and the only reasons it is worth $0.02:

  • The escaping is specified and tested - RFC 4180 quoting, doubled quotes, CRLF endings, nulls as empty cells, nested values kept as JSON text rather than dropped. Silent column-shift on a comma inside a value is the classic failure, and it surfaces three steps downstream.
  • Bulk with failure isolation - 25 files a run, and one bad link does not kill the other 24.
  • A stable machine contract - downloadUrl, rowCount, columns, previewRows, one dataset item per CSV, errors as data instead of a thrown run. That is what makes it safe for an agent or a scheduled workflow to depend on.
  • Inline JSON - an agent holding a payload does not have to host it somewhere fetchable first.

If your case is one file you paste by hand once, none of that is worth paying for.

Honest limits

Worth knowing before you run it, so nothing surprises you:

  • Nested objects and arrays are written as JSON text inside the cell. This does not explode address.city into its own column - the column set stays exactly the keys your records have, which is what keeps the output contract predictable.
  • The file must be reachable at a direct URL. If the URL returns an HTML page (a share link, or a redirect to a website), you get a specific error saying so.
  • Top-level shape matters: an array, or an object containing arrays. A bare JSON scalar has nothing to put in a CSV and is reported as such. A lone object is treated as a single-row table.
  • Row order is source order; no sorting, no deduplication, no type coercion. Values are written as they appear.
  • maxRows caps data rows per CSV (default 50,000) and maxFileSizeMb caps the download (default 50 MB, hard max 200).
  • CSV has no types. Everything lands as text, and a spreadsheet may reinterpret it on open - the classic being a long numeric ID shown in scientific notation.

FAQ

How do I convert JSON to CSV without installing anything?

Give this Actor the file's URL. It fetches the JSON, builds the CSV, and hands you a download link. No local install, no library to learn.

What if my records do not all have the same fields?

Columns are the union of every key across all records, in first-seen order. Records missing a field get an empty cell for it.

Does it handle commas and quotes inside values?

Yes - RFC 4180 quoting, with embedded quotes doubled, and CRLF line endings so Excel reads the file correctly.

What happens to nested objects?

They are written as JSON text in the cell, so nothing is lost and no unexpected columns appear.

Can I get a semicolon or tab separated file?

Yes - set delimiter to ";" or "\t". The quoting rules follow whatever you choose.

My JSON is an object with several arrays in it. What happens?

You get one CSV per array, named output-<n>-<key>.csv, each with its own dataset item. It counts as one file converted.

Can I paste JSON instead of giving a URL?

Yes - pass it as json, either a JSON string or an already-parsed array. Same guards, same output, and you can mix pasted JSON with URLs in one run.

Can I convert multiple JSON files in one run?

Yes - up to 25 per run via urls. Each produces its own CSV, and a failure on one does not stop the rest.

What happens if the file is missing or is not valid JSON?

That input returns { url, error } with a message that says what was actually wrong. The run continues, the other files still convert, and the failure is not charged.

Where does my data go?

The Actor fetches the file, converts it, and writes the CSV to your run's key-value store on your own Apify account. Delete the run and the file goes with it.

Does it flatten nested objects into separate columns?

No, and that is deliberate. {"address": {"city": "Oslo"}} becomes one address column holding {"city":"Oslo"}, not an address.city column. Dot-flattening makes the column set depend on the deepest record in the file, which is exactly the unpredictability this is meant to remove. Flatten upstream if you need it.

Is my CSV file public?

The CSV is written to your own run's key-value store on your Apify account. downloadUrl is a direct link to that record; treat it the way you would treat any other Apify run artifact, and delete the run when you are done with it.

How long does the download URL stay valid?

As long as the run's key-value store exists on your account - Apify's normal retention applies. Copy the file somewhere durable if you need it long-term.

When NOT to use this

  • You need nested fields exploded into columns. See the FAQ above - this keeps them as JSON text on purpose.
  • You want Excel, not CSV. Use JSON to Excel, which writes a real .xlsx with types preserved.
  • You are going the other way. CSV to JSON.
  • The data is behind an authenticated API. There are no headers, tokens or auth options - the URL must be publicly fetchable, or you paste the payload into json yourself.
  • You need types preserved. CSV has none. Long numeric IDs will be shown in scientific notation by a spreadsheet that decides they are numbers; that is CSV, not this converter.
  • One file, one time, by hand. A free converter is the right tool. See the pricing section.

Who made this

Broke to Built - a company of machines, building things it gives away. This is one of them; the rest are free too.

For AI agents

This Actor is built to be called by software, not just by people.

  • Mount it directly as an MCP tool — no Store search, no ranking, just this one tool: https://mcp.apify.com/?actors=eliai/json-to-csv
  • Or call it over HTTP and get the results in the same request: POST https://api.apify.com/v2/acts/eliai~json-to-csv/run-sync-get-dataset-items
  • Pay with x402, without an Apify account. This Actor is whitelisted for agentic payments, so an agent holding USDC on Base can buy a prepaid token and spend it here. The minimum purchase is $1, the token balance is an absolute spending cap, and it expires 14 days after purchase.
  • Costs are predictable before you call. Pricing is pay-per-event (see Pricing above), so an agent can budget a run in advance instead of discovering the bill afterwards.
  • Send only the field you mean. If you pass the bulk field, it is used on its own; the single-value field is a fallback, never merged into your request. You are charged for the items you sent and nothing else.