JSON to Excel

How to convert JSON to Excel, nested JSON included

rows.page flattens nested JSON up to 8 levels deep into a CSV that Excel opens, free with no signup, up to Excel's 1,048,576-row sheet limit. It doesn't write .xlsx, so you save the workbook in Excel. Excel's From JSON connector and pandas are the other routes, and they hit the same limit.

.json.jsonl
Drop a file here
Stays in your browserUp to 1.5 GB

No file handy? Open Every country, as nested JSON (250 rows, 1.4 MB).

Three ways to get JSON into Excel

Pick a route by how deeply nested your records are and whether you write code. Excel can read a JSON file itself, rows.page flattens it in your browser and exports CSV, and pandas writes .xlsx from a script.

Ways to convert JSON to Excel
RouteNested JSONRow limitCost
Excel Power Query (From JSON)Detects the table; you expand Record and List columns by hand1,048,576 rows per sheetIncluded with Excel
rows.page, then Excel From Text/CSVFlattens objects up to 8 levels and 200 child fields; lists export as JSON textNo limit in rows.page; 1,048,576 rows in ExcelFree, no signup
pandas with openpyxlpd.json_normalize flattens objects; lists stay as text1,048,576 rows per sheetFree, open source

Open JSON in Excel with Power Query

Excel has a JSON connector in Microsoft 365 on Windows and Mac. Power Query detects the table in the file and flattens what it can.

  1. In Excel, choose Data > Get Data > From File > From JSON.
  2. Pick the .json file and select Open. The Power Query Editor opens with the detected table.
  3. If a column still shows Record or List, click the expand button in its header to pick fields or turn list items into rows.
  4. Select Close & Load to put the table on a worksheet.

The connector doesn't read JSON Lines as is; Microsoft's workaround is M code with Lines.FromBinary and Json.Document. For JSONL files, or JSON with many nested levels, flatten the file in rows.page first.

Convert JSON to Excel with rows.page

rows.page opens .json, .jsonl, .ndjson and .ldjson files in your browser with DuckDB-WASM, or raw JSON you paste with Paste data. Nothing is uploaded unless you press Share.

  1. Drop the file on rows.page. A .json file can be up to 1.5 GB per browser tab; a bigger JSONL file loads its first rows.
  2. Check the columns: nested objects become dot-path columns such as user.address.city, and a wrapper like {"data": [...]} is unwrapped to its biggest list.
  3. Hide fields you don't need in the Columns panel, or narrow the rows with the filter box.
  4. Choose Export > CSV.
  5. In Excel, choose Data > Get Data > From File > From Text/CSV, pick the CSV, set File Origin to 65001: Unicode (UTF-8) and select Load. Then use File > Save As to save the workbook as .xlsx.

The File Origin step matters because Excel only assumes UTF-8 when a CSV starts with a byte order mark (BOM), and rows.page exports UTF-8 without one. Double-clicking the CSV instead can turn é into é. Text cells that start with =, +, - or @ get a leading apostrophe so Excel doesn't run them as formulas.

Arrays, row limits and trimming before export

Arrays inside a record stay as list columns: the grid shows the first 6 items and +N, and the CSV export writes each list as JSON text in one cell. For one row per array item, run SQL in the filter box, with double quotes around column names that contain dots:

sql
SELECT
  id,
  "user.address.city" AS city,
  unnest(tags) AS tag
FROM data

Rows whose list is empty drop out of an unnest result. A SQL result shows and exports up to 1,000,000 rows, which fits in one Excel sheet.

An Excel sheet holds 1,048,576 rows by 16,384 columns, while the rows.page grid has no row limit. A filtered view exports every matching row, so narrow a big file below that limit first: filter with country:NL, price:>20, name:* (has a value) or -name:* (is empty), or click a histogram bar or top value in the Columns panel.

Convert JSON to .xlsx in Python with pandas

pandas writes .xlsx files directly through openpyxl (pip install pandas openpyxl), with no CSV step:

python
import json
import pandas as pd

with open("input.json", "r", encoding="utf-8") as f:
    records = json.load(f)

pd.json_normalize(records).to_excel("out.xlsx", index=False)

pd.json_normalize joins nested keys with dots, like user.address.city in rows.page; pass record_path when the records sit under a wrapper key. Lists are written as Python text such as ['a', 'b'], not JSON. to_excel raises an error when the DataFrame has more than 1,048,576 rows or 16,384 columns.

rows.page limits and prices

WhatLimit or price
Open a file in your browserFiles up to 1.5 GB, $0, no account, nothing uploaded
Share a link without an account$0, files up to 100 MB, link deleted 7 days after creation
Free account$0, 10 datasets kept, last 3 versions
Pro$12/month, 100 datasets, files up to 500 MB, private links
Max$39/month, 1,000 datasets, files up to 2 GB, private links

Questions

Does rows.page upload my JSON file to a server?

No. rows.page reads the file inside your browser with DuckDB-WASM. Nothing is uploaded unless you press Share ("Upload and get a link") or push the file from a terminal with curl -T.

Why do accents look broken when I double-click the exported CSV in Excel?

rows.page exports CSV as UTF-8 without a BOM, and Excel only assumes UTF-8 when the file starts with one. Open the file with Data > Get Data > From File > From Text/CSV and set File Origin to 65001: Unicode (UTF-8) instead.

How big a JSON file can rows.page open?

A .json file up to 1.5 GB per browser tab; a larger one is refused with "Too big for this browser". A JSONL file over 1.5 GB loads its first rows with a note instead. Excel still stops at 1,048,576 rows per sheet.

What if my JSON is a single object like {"data": [...]} instead of an array?

rows.page unwraps a single top-level object to its biggest list, up to 4 levels deep, and loads the items as rows with the note: Showing the N items in "data"; the other top-level fields were skipped.

Can I open a JSON file from a public URL without downloading it?

Yes. Put the URL after https://rows.page/, for example https://rows.page/https://example.com/data.json; raw GitHub, Hugging Face /resolve/ and S3 presigned links work. If the host blocks cross-origin requests, rows.page fetches the file through its proxy (up to 100 MB, 30 seconds, 5 redirects) and stores nothing.