How to convert an api response json to csv for excel
- Step 1Capture the API response — Save the response body to a file. In Postman use Save Response → Save to a file; with
curlredirect to a file (curl https://api.example.com/orders -o orders.json); in the browser open DevTools → Network, click the request, copy the Response, and save it as.json. Pretty-printed or minified both work. - Step 2Drop the JSON onto the converter — Drag the
.jsonfile onto the dropzone above (or a.ndjson/.jsonl/.txtfile). Parsing happens locally with no upload. The free limit is 2 MB per file; larger responses need Pro. - Step 3Pick the input format — Leave it on Auto detect for a normal JSON document — it parses the whole file as JSON first and only falls back to NDJSON if that fails. Choose JSON array when you know the file is
[ {...}, {...} ], or NDJSON / JSONL for one-object-per-line log-style exports. - Step 4Keep Flatten nested objects on — With flattening on (the default),
customer: { address: { city: "..." } }becomes acustomer.address.citycolumn. Turn it off only if you want each nested object preserved verbatim as a JSON string inside a single cell. - Step 5Choose how arrays should look — Set Array values to JSON literal to keep
["a","b"]re-parseable, Pipe joined fora|b, or Comma joined fora, b. Arrays are always written to one cell — the tool does not fan an array out across extra rows or columns. - Step 6Convert, then download the Excel-Ready CSV — Click Convert to CSV, check the Records in / Rows out / Columns / CSV size stats and the first-10-rows preview, then use Excel-Ready CSV (BOM + CRLF) so the file opens cleanly in Excel. Use plain Download CSV for Python/awk pipelines that prefer LF.
How each API response shape converts
The converter wraps or unwraps your payload according to its top-level type. Behaviour is identical whether you paste pretty-printed or minified JSON.
| Response shape | Example | What you get |
|---|---|---|
| Array of objects | [ {"id":1}, {"id":2} ] | One CSV row per array element — the common, clean case |
| Envelope with one array | { "data": [ {...}, {...} ] } | Top-level values that are all arrays get concatenated into rows; data rows are emitted |
Envelope with array plus a scalar meta | { "data": [...], "meta": {...} } | Mixed top level: not all values are arrays, so the whole object becomes a single row with data and meta flattened — extract data first (see edge cases) |
| Single object | { "id": 1, "name": "A" } | Wrapped as one record → a one-row CSV |
| Bare primitive / array of primitives | [1, 2, 3] | Each primitive becomes a row under a single value column |
Converter options for API exports
The four controls exposed in the tool above, with the default each ships with.
| Option | Values | Default | When to change it |
|---|---|---|---|
| Input format | Auto / JSON array / NDJSON | Auto detect | Force NDJSON for line-delimited log exports that start with { |
| Flatten nested objects | On / Off | On | Off to keep customer as one JSON-string cell instead of dot-notation columns |
| Array values | JSON / Pipe / Comma | JSON literal | Pipe or Comma for human-readable tags columns in Excel |
| Delimiter | Comma / Semicolon / Tab | Comma | Semicolon for EU-locale Excel; Tab for paste-into-Sheets |
Cookbook
Real API response shapes and the exact CSV the converter produces. Token and email fields anonymised.
Paginated list endpoint with a data envelope
ExampleA typical GET /orders response wraps rows in data. Because every top-level value here is an array, the converter concatenates them into rows automatically — no need to strip the envelope first.
Input:
{ "data": [
{ "id": 101, "total": 49.0, "customer": { "email": "a@x.com" } },
{ "id": 102, "total": 12.5, "customer": { "email": "b@x.com" } }
] }
Output CSV:
id,total,customer.email
101,49,a@x.com
102,12.5,b@x.comSparse fields across records
ExampleOne order has a discount, the next does not. The union-of-keys header keeps both columns; the record without a discount gets an empty cell rather than a shifted row.
Input:
[
{ "id": 1, "total": 20, "discount": 5 },
{ "id": 2, "total": 30 }
]
Output CSV:
id,total,discount
1,20,5
2,30,Tags array as human-readable text
ExampleSet Array values to Comma joined so a tags array reads cleanly in an Excel column instead of staying as a JSON literal.
Input:
[ { "id": 1, "tags": ["vip", "eu"] } ]
Array values = JSON literal:
id,tags
1,"[""vip"",""eu""]"
Array values = Comma joined:
id,tags
1,"vip, eu"Keeping a nested object intact
ExampleTurn Flatten nested objects off when a consumer downstream wants the original JSON for one field rather than exploded columns.
Input:
[ { "id": 1, "address": { "city": "NYC", "zip": "10001" } } ]
Flatten OFF:
id,address
1,"{""city"":""NYC"",""zip"":""10001""}"
Flatten ON:
id,address.city,address.zip
1,NYC,10001Semicolon delimiter for EU-locale Excel
ExampleEuropean Excel installs treat the comma as a decimal separator, so a comma-delimited CSV all lands in column A. Switch the delimiter to Semicolon for a clean import.
Input:
[ { "id": 1, "price": "12,50" } ]
Delimiter = Semicolon:
id;price
1;"12,50"Errors and edge cases
Real errors and silent failures sourced from each platform's own documentation. Match the wording to the row, fix what the row says to fix.
Response wraps rows in `data` alongside a `meta` object
By designIf the top level is { "data": [...], "meta": {...} }, not every value is an array, so the converter treats the whole object as a single record and flattens meta plus the entire data array into one wide row. To get one row per item, extract the data array first with json-path-extractor (path $.data), then convert that.
File over the free 2 MB limit
BlockedFree conversions cap at 2 MB / 500 rows. A large paginated export exceeding that is blocked until you upgrade to Pro (100 MB / 100,000 rows) or split the response into smaller files.
Invalid JSON pasted from a truncated copy
Invalid JSONA response copied mid-stream from DevTools can be truncated. The parser reports Invalid JSON with the underlying position. Re-copy the complete body, or if it is NDJSON the error names the first bad line number.
Deeply nested arrays of objects
PreservedAn array of objects (e.g. line_items: [ {...}, {...} ]) is serialised into one cell as a JSON literal — it is not expanded into child rows. If you need each line item on its own row, extract that array path first and convert it separately.
Numbers losing precision in Excel
ExpectedThe CSV stores the exact value, but Excel auto-coerces a 16-digit order ID to scientific notation on open. The data is intact in the file — format the column as Text in Excel, or use Data → From Text/CSV and set the column type before import.
Unicode names showing as é in Excel
PreservedPlain Download CSV is UTF-8 without a BOM, which Windows Excel can misread. Use the Excel-Ready CSV button instead — it prepends a UTF-8 BOM and CRLF line endings so José and Müller render correctly.
Empty response body
ExpectedAn empty file or whitespace-only input produces zero records and an empty CSV — no error. Confirm your saved file actually contains the response body.
Null values inside records
By designnull and missing keys both render as an empty cell. There is no separate sentinel for null — if you need nulls distinguished from empties, strip or mark them first with json-null-stripper.
Frequently asked questions
Do I need to strip the `data` envelope before converting?
Usually no. If the top-level object's values are all arrays (the common { "data": [...] } case), the converter concatenates them into rows automatically. You only need to extract the array first when the envelope mixes the array with scalar fields like meta or pagination.
Will nested customer fields become separate columns?
Yes, with Flatten nested objects on (the default). customer.address.city becomes its own column using dot-notation. Turn flattening off to keep the nested object as a single JSON-string cell.
What happens to arrays like `tags` or `line_items`?
Arrays are written into a single cell. Choose JSON literal to keep them re-parseable, or Pipe / Comma joined for readable text. Arrays of objects are not split into extra rows — extract that path separately if you need one row per element.
Why are some cells empty?
Headers are the union of every key across all records. If one record lacks a field that another has, the cell is left empty so columns stay aligned. Null values also render as empty.
Is my API response uploaded anywhere?
No. Parsing and conversion run entirely in your browser via JavaScript. The payload — including any tokens, emails, or order data — never leaves your machine.
What is the difference between Download CSV and Excel-Ready CSV?
Download CSV is UTF-8 with LF line endings, ideal for code pipelines. Excel-Ready CSV prepends a UTF-8 BOM and uses CRLF so Excel on Windows opens it with correct encoding and no shifted rows.
How big a response can I convert for free?
The free tier handles files up to 2 MB and 500 output rows. Pro raises this to 100 MB and 100,000 rows.
Does it handle NDJSON / JSON Lines responses?
Yes. Auto detect falls back to NDJSON when whole-document JSON fails, or you can force the NDJSON / JSONL input format for one-object-per-line exports.
Can I change the delimiter for European Excel?
Yes — switch the delimiter to Semicolon (or Tab). EU-locale Excel treats commas as decimal separators, so semicolon-delimited output imports into separate columns correctly.
Why did a long numeric ID change in Excel?
Excel coerces long numbers to scientific notation on open. The CSV value itself is exact — format the column as Text, or use Data → From Text/CSV and set the column type before import.
Can I rename or reorder the generated columns?
Not in this tool — column order follows first-seen key order and names are the original keys. Convert first, then rename headers with json-key-renamer on the source JSON, or reorder in your spreadsheet.
I need to go the other way — CSV back to JSON. Is there a tool?
Yes, use csv-to-json. For pulling specific fields out of a large response before converting, json-path-extractor handles the path selection.
Privacy first
Conversion runs locally in your browser. No file is uploaded — only metadata counters are saved for signed-in dashboard stats.