Convert JSON to CSV

Runs on your device · Your file never leaves your device.

Drop a .json file or paste JSON straight from an API response and get a CSV you can open in Excel, Google Sheets or any import screen. A top-level list gives one row per item; otherwise the longest list of records in the document is used, so {"results": [...], "count": 2} gives one row per result; an object with no list in it becomes one row.

The rules are fixed so the result is predictable: nested objects become dot-separated columns (address.city), a list of plain values is joined with semicolons in one cell, and a list of objects inside a record gets numbered columns (items.0.name). The header row is the union of every key found, in the order they first appear, so records with missing fields simply leave a cell empty.

The CSV is written to RFC 4180 — fields with commas, quotes or line breaks are quoted properly — in UTF-8 with an optional byte-order mark so Excel shows every script, accent and symbol correctly. A cell that begins with =, +, - or @ gets an apostrophe in front, so a spreadsheet shows it as text instead of running it as a formula. You see the first 200 lines before downloading, and nothing leaves your device.

How to convert JSON to CSV

  1. Drop a JSON file, or paste the JSON into the box.
  2. Pick the column separator for the output (comma by default) and whether to add the Excel BOM.
  3. Press Convert to CSV and check the preview of the first lines.
  4. Download the .csv.

Supported formats and limits

Input
JSON (.json) — a file or pasted text, UTF-8
Output
CSV, RFC 4180, UTF-8, CRLF line ends, optional BOM
Nesting
Objects → dot columns; lists of values → joined with ;
Separator
Comma, semicolon, tab or pipe
Where it runs
In your browser; nothing uploaded

Not for: A deeply nested single object with no list inside — it converts, but as one very wide row rather than a table.

Which list becomes the rows

A top-level list is the rows. Otherwise the tool looks through the document, up to eight levels deep, for the longest list of objects. So {"response": {"data": {"items": [...]}}} and {"results": [...], "count": 2, "next": null} both give one row per item, and the line under the result names the list it used, such as results. Values beside that list, like count and next, are not part of any record and are left out.

Of two equally long lists, the one nearer the top wins. For a shorter list, copy it from its [ to its ] and paste only that. A document with no list of objects becomes one row, and wrappers with a single key are skipped, so {"order": {"id": 7, "total": 12}} gives the columns id and total.

How values are written into cells

Text is copied exactly, including dates, which stay in whatever form the JSON has them, such as 2024-01-05T10:00:00Z. true and false are written as words. null, an empty list and an empty object all become an empty cell, so in the CSV they look the same as a field that was missing.

A number is written exactly as the JSON has it: 1.0 stays 1.0, 1e21 stays 1e21, and an ID such as 12345678901234567890 keeps every digit even without quotes. An ordinary JSON reader would turn that ID into 12345678901234567000.

Lists inside lists, and keys that already contain dots

A list of lists is opened one level: "m": [[1, 2], [3]] gives a column m.0 holding 1;2 and a column m.1 holding 3. A list that mixes objects and plain values numbers every entry, so "x": [{"z": 1}, 2] gives x.0.z and x.1.

Column names are made by joining keys with dots, so a key that already contains a dot can meet a nested one: {"a.b": 1, "a": {"b": 2}} would make a.b twice. The second gets a suffix, so the columns are a.b and a.b_2 and both values are kept.

Choosing the separator, and cells that start with =

Comma is the usual choice. Semicolon suits a spreadsheet set to a language that writes decimals with a comma, where a comma-separated file often opens in a single column. Tab and pipe are for systems that ask for them. Whatever the separator, the file is named .csv.

A cell that begins with =, +, - or @ is a formula to a spreadsheet, which would run it on opening. Such a cell gets an apostrophe in front, the mark spreadsheets themselves use for "this is text", so =1+1 is written as '=1+1. Plain numbers such as -5 or +3.5 are left as they are.

Frequently asked questions

Are my files uploaded to a server?
No. This conversion runs inside your browser using your own device’s processing power, and the file is not uploaded. Once a tool has been used once (video, text recognition and background removal download their engine from this site the first time), it keeps working when your connection drops.
What happens to nested objects and arrays?
A nested object is flattened into dot columns: {"address":{"city":"Cairo"}} becomes a column named address.city. A list of plain values ("tags": ["a","b"]) is written as a;b in one cell. A list of objects inside a record gets numbered columns such as items.0.name, items.1.name.
My JSON is an object, not a list — what do I get?
The longest list of records anywhere in it becomes the rows — {"results": [...], "count": 2, "next": null} gives one row per result — and the result line names the list it used. Values beside that list are not part of any record and are left out. An object with no list in it is written as a single row with one column per key.
Why does Excel show strange characters, and how do I fix it?
Excel guesses the encoding unless the file starts with a byte-order mark. The "Add a BOM for Excel" switch is on by default and adds that three-byte marker; turn it off for tools that insist on plain UTF-8.

Related tools

More in Spreadsheets & data

This page in other languages: العربية · Deutsch · Français · Español · Русский · Português · 中文 · हिन्दी · Türkçe · עברית · فارسی · اردو · Bahasa Indonesia · বাংলা