JSON to CSV Converter - Flatten JSON to CSV, URL or Bulk
Pricing
$20.00 / 1,000 converted files
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
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
8 hours ago
Last modified
Categories
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
| Field | Type | Required | What it does |
|---|---|---|---|
url | string | yes | Direct URL to the JSON file |
urls | string[] | no | Extra JSON URLs - up to 25 total per run |
json | string | array | object | no | Raw JSON pasted directly, instead of (or alongside) a URL |
delimiter | string | no | Column separator (default ,; use ; or \t) |
maxRows | number | no | Cap data rows written per CSV (default 50000) |
maxFileSizeMb | number | no | Size 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,supplierTEA-EG-100,Earl Grey Tea,Beverages,4.5,182,2026-08-20,Bergamot & CoTEA-GR-200,Gunpowder Green Tea,Beverages,5.25,94,2026-08-22,Leaf HarborCOF-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,extra1,"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:
downloadUrlto a real CSV, plusrowCount,columnsand 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.cityinto 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.
maxRowscaps data rows per CSV (default 50,000) andmaxFileSizeMbcaps 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
.xlsxwith 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
jsonyourself. - 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.
Related actors
- JSON to Excel - the same job,
.xlsxoutput with types - CSV to JSON - the reverse direction
- Excel to JSON - spreadsheets into JSON
- CSV to Excel - CSV into a real
.xlsx
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.