What does convert JSON to CSV locally actually mean?
The word locally gets used for three different things, and the difference matters when privacy is the reason you are asking. The first meaning is client-side: a web page that does the conversion inside your browser tab. You are still looking at a website, but the page never sends your data anywhere, because the conversion code runs on your machine. The second meaning is installed software: a program on your computer, like a desktop app or an editor extension, that reads a file and writes a file. The third meaning is a script you run yourself: a few lines of Python, jq, or Node that you control completely and can read before you run.
All three keep the file on your machine. They differ in what you have to install, what you have to learn, and how repeatable the result is. A client-side page needs nothing installed and nothing learned, but you repeat the clicks every time. A script needs a tool installed and a few lines typed, but you can run it on a hundred files with one command and get the same result every time. The rest of this guide treats all three as local, and says which one each method is.
One thing locally does not mean is private by magic. A script you download from a stranger and run without reading can do anything on your machine, including sending your file somewhere. The scripts in this guide are short enough to read in full, and you should read any script before you run it on sensitive data. Local is a property of where the work happens, and you verify it by reading the code or by watching the network, not by trusting a label.
When local is the right call, and when it is not
Local conversion is the right call in four situations. The first is sensitive data: customer lists, internal records, anything under a contract or a privacy rule that says the data stays inside the company. If the file cannot leave the machine, a server-side converter is simply not an option, no matter how convenient. The second is no connection: a plane, a remote site, a network that blocks the tool you wanted. Local tools work exactly the same offline, because there is no server to reach.
The third is repeatability. If you convert the same kind of export every week, a script turns a fifteen minute clicking session into a single command, and the same command gives the same columns in the same order every time. The fourth is size and control: a file with millions of rows, or a file whose columns you need to rename and reorder, is easier to handle with a script you can adjust than with a page whose options are fixed.
Local is the wrong call in three situations. If several people need the same conversion and the same settings, a shared page beats five copies of a script that drift apart. If you have no machine you control, for example a borrowed computer or a locked-down work laptop that cannot install Python or jq, a client-side page is still local and still the better choice. And if the file is bigger than your machine can comfortably hold in memory, no local method helps until you split the file or stream it, which is a different job. Ask one question before you pick: does this file have to stay on this machine, and will I do this again? If both answers are yes, go local and script it. If only the first is yes, a client-side page is enough.
Method 1: the converter on this page is already local
The simplest local method is already in front of you. The converter on this page runs entirely inside your browser tab. When you paste JSON or upload a file, the page parses it, flattens it, and builds the CSV text in your browser, then hands you the result as a downloaded file. There is no upload step and no server waiting for your data, because the conversion code ships with the page and runs on your machine.
You can verify that claim yourself in about thirty seconds, and you should, because a claim about privacy is worth checking. Open the converter, disconnect from the network or turn on airplane mode, then paste JSON and convert it. It still works, because nothing about the conversion needs the network. The only button on the page that touches the network is the optional fetch-from-URL button, which loads JSON from a web address you type in. If you paste or upload instead of fetching, the network is never used.
That makes the page the right local method for one-off conversions and for machines where you cannot install anything. The limits are the same as any page: you repeat the clicks for every file, and very large files will slow the tab down. For a single file, or for a file you only convert once, those limits do not matter. For a weekly export, move to a script below and keep the page as your quick check.
Method 2: Python, the local workhorse, no packages needed
Python is the most useful local method for most people, because it is already installed on most developer machines and the standard library alone is enough. No pandas, no packages, nothing to download. The script below reads a JSON file of objects, takes the column names from the first object, and writes a CSV with the standard csv module, which handles quoting correctly by itself. Save it as json2csv.py and run it with python3 json2csv.py orders.json orders.csv.
import json, csv, sys
with open(sys.argv[1]) as f:
rows = json.load(f)
with open(sys.argv[2], 'w', newline='') as f:
writer = csv.DictWriter(f, fieldnames=rows[0].keys())
writer.writeheader()
writer.writerows(rows)Tested on the sample file used throughout this guide, three orders with id, customer, and tags fields, this script produced a header row plus three data rows. The nested customer object came out as a Python repr string, not JSON text, and the tags list came out as a repr list, because a plain DictWriter does not flatten nested values. That is the honest limit of the short version: flat data converts perfectly, nested data needs one more step. The flattening step is small. A short recursive function that turns nested objects into dot-notation keys, customer.name and customer.city, before writing, gives you the same columns the converter page produces with its flattening toggle on.
The csv module is doing real work for you here. It quotes cells that contain the delimiter, doubles inner quotes, and writes line endings your spreadsheet expects. Do not build CSV by joining values with commas yourself. Hand-rolled joining breaks on the first comma inside a value, and that break is silent: the file looks fine until a column shifts. The standard library version also runs the same on every machine with Python 3, which is why it is the method to reach for when a colleague needs to run your conversion too.
Method 3: jq, the one-liner for people who live in the terminal
If you already use the terminal, jq turns the whole job into one line, for flat data. It reads JSON, picks the keys from the first object as the header, then emits every row as a CSV line, with quoting handled by its @csv formatter. No script file, no loop, no manual quoting. The command below reads a flat orders file, id, city, and total per order, and writes orders.csv. Note the limit, stated plainly: the @csv formatter rejects nested objects and lists, so this one-liner is for flat exports only, and the nested sample from the Python section fails on it with an error instead of a wrong table, which is the safe kind of failure.
jq -r '(.[0] | keys_unsorted) as $keys | $keys, map([.[ $keys[] ]])[] | @csv' orders-flat.json > orders.csvTested on a flat three-order file, the output was a quoted header row, "id","city","total", followed by three data rows with string cells quoted and numbers bare, exactly the shape @csv produces. The keys_unsorted detail matters: plain keys would sort the columns alphabetically, which changes the column order from your file. If your data has nested objects, jq needs a flattening filter first, and the one-liner grows into a small script. For flat exports, which is what most API list responses already are once unwrapped, the one-liner is the whole job, and it runs offline on any machine with jq installed. The nested-data limit was confirmed on the test machine: the same filter on the nested sample fails with an error instead of a wrong table, which is the safe kind of failure.
One caution: jq reads the entire file into memory, so a multi-gigabyte export will strain it just as it strains a browser tab. For ordinary exports, up to tens of megabytes, it is instant. For very large files, split the file first or use a streaming tool, and treat that as a separate problem from conversion.
Method 4: Node, for when the conversion lives inside a project
Node is the right local method when the conversion is part of a project rather than a one-off task: a build step, a data pipeline, a script the team already runs. Node ships with JSON parsing built in, so the only work is turning rows into CSV text, and the small script below does it with a dot-flattening helper so nested objects become dot-notation columns, matching the converter page behavior. Save it as json2csv.mjs and run it with node json2csv.mjs orders.json orders.csv.
import { readFileSync, writeFileSync } from 'node:fs';
const flatten = (obj, prefix = '', out = {}) => {
for (const [k, v] of Object.entries(obj)) {
const key = prefix ? prefix + '.' + k : k;
if (v && typeof v === 'object' && !Array.isArray(v)) flatten(v, key, out);
else out[key] = Array.isArray(v) ? v.join('; ') : v;
}
return out;
};
const rows = JSON.parse(readFileSync(process.argv[2], 'utf8')).map(r => flatten(r));
const cols = [...new Set(rows.flatMap(r => Object.keys(r)))];
const esc = v => v == null ? '' : /[",\n]/.test(String(v)) ? '"' + String(v).replaceAll('"', '""') + '"' : String(v);
const lines = [cols.join(','), ...rows.map(r => cols.map(c => esc(r[c])).join(','))];
writeFileSync(process.argv[3], lines.join('\n'));Tested on the same sample, the script produced the header id,customer.name,customer.city,total and three rows, with the nested customer object flattened to two columns and the tags list joined with a semicolon and a space. The escaping function follows the same rule the converter page uses: quote a cell only when it contains the delimiter, a quote, or a line break, and double any inner quotes. That rule is the whole of CSV quoting, and getting it right is the difference between a file that opens cleanly and a file that silently shifts columns.
The script is deliberately short so you can read it before running it. It takes the union of all columns across rows, so a row missing a field gets an empty cell, which matches the converter page. If you need streaming for huge files, or column renaming, those are additions to this script, not replacements for it.
Method 5: tools you already have, VS Code and Excel offline
Two more local methods need no new install if you already use the tools. In VS Code, an extension converts the open JSON file to CSV from the command palette, which is the fastest local path when you are already editing the file. The full walkthrough, including which extension and the exact commands, is in the VS Code guide linked below. In Excel, Power Query reads a JSON file from your disk and turns it into a table without the file ever leaving the machine: Data, Get Data, From File, From JSON, then expand the columns and load. Both are fully offline once the tool is installed.
These methods trade control for convenience. VS Code and Excel decide column handling for you, and their defaults are usually fine for flat data and occasionally surprising for nested data. If the output looks wrong, the diagnosis is the same as everywhere else: check whether nested values were flattened or left as JSON text, and check the delimiter on open. For a file you convert once, either method beats installing something new. For a file you convert weekly, a script you own beats both.
When local is not enough, and what to do then
Local conversion has three real limits, and naming them keeps you from forcing a local method where it does not fit. The first is collaboration: if five people need the same conversion with the same settings, five scripts drift apart and a shared page stays consistent. The second is machine access: on a borrowed or locked-down computer you may not be able to install Python, jq, or Node, and then the client-side page is still your local method. The third is scale: a file larger than memory will strain every method here, and the fix is splitting the file or streaming it row by row, not a different converter.
There is also a limit people forget: local conversion does not fix bad data. A script converts exactly what the file contains, including missing fields, mixed types, and inconsistent shapes. If the same export sometimes has a field and sometimes does not, every method in this guide gives you the union of columns with blanks, which is honest but may not be what your spreadsheet expects. Fix the source export when you can, and document the blanks when you cannot.
Local file hygiene: four checks before you trust the CSV
A local conversion is only done when the output checks out, and the checks take less than a minute. First, keep the original JSON. Never convert in place by overwriting the source, because a conversion loses information: types become text, nested structure becomes column names, and there is no way back to the original tree from the CSV alone. Second, name the output so it sorts: orders-2026-10-25.csv beats output-final-v2.csv, and the date tells you which export it came from.
Third, count the rows. The CSV should have one header row plus one row per object in the JSON, and a quick count catches the most common failure, which is a row finder picking the wrong list from a wrapped response. Fourth, open the CSV with the right delimiter. A file that opens as a single column is almost never broken data; it is a delimiter mismatch between the file and the spreadsheet, and re-importing with the matching delimiter fixes it. The converter page, the Python csv module, jq, and the Node script above all quote per the active delimiter, so a single-column open is an opening problem, not a conversion problem.
Troubleshooting local conversions
The same four problems show up in every local method, and each has one fix. File not found means the terminal is in a different folder than the file; check the path before anything else. Invalid JSON means the source file is broken near the reported position, usually a missing quote or a trailing comma; validate it and fix the source, because no converter should guess at broken input. A single-column open means a delimiter mismatch on the opening side; re-import and pick the delimiter the file was written with.
Nested data appearing as unreadable JSON text in cells means flattening was skipped: the Python short script and the jq one-liner do not flatten, so use the flattening variants above or the converter page with its flattening toggle on. Columns in a different order than the file means a tool sorted the keys; jq needs keys_unsorted, and the Node script preserves first-seen order. Rows missing entirely means the row finder picked a different list than you intended, which happens with wrapped API responses; point the tool at the list itself, or unwrap the response first.
Related guides
- JSON to CSV Converter Download: What You Should Actually Download (2026 Guide)
- How to JSON to CSV Online: Do It in This Tab in 30 Seconds (2026 Guide)
- How to Flatten JSON to CSV: What the Toggle Actually Does (2026 Guide)
- What Are Ways to Convert JSON to CSV Locally? 6 Methods, Compared (2026 Guide)
- Why Your CSV Opens in One Column in Excel, and How to Fix It (2026 Guide)
- Why Your CSV Shows Weird Characters in Excel, and How to Fix the Encoding (2026 Guide)
- Why Excel Drops the Leading Zeros From Your CSV Codes, and How to Keep Them (2026 Guide)
- Why Excel Changes Your CSV Dates, and How to Keep Them (2026 Guide)
- Why Saving Your CSV in Excel Changes It, and How to Keep the Original Safe (2026 Guide)
- Why Excel Won't Open Your Big CSV File, and What to Do Instead (2026 Guide)
Frequently asked questions
What does convert JSON to CSV locally mean?
It means the conversion runs on your own machine instead of on a server. That can be a client-side converter page running in your browser tab, installed software like VS Code or Excel, or a script you run yourself in Python, jq, or Node. In all three cases the file never has to leave your computer.
Is the converter on this page local?
Yes. Paste or upload JSON and the conversion runs inside your browser tab, with the result handed back as a downloaded file. You can verify it by disconnecting from the network and converting anyway: it still works. The only button that uses the network is the optional fetch-from-URL button, which loads JSON from an address you type in.
Do I need to install anything to convert JSON to CSV locally?
No, if you use the converter page, which needs nothing installed. If you want a repeatable script, Python 3 is already installed on most developer machines and its standard library alone is enough. jq and Node are one install each and both run fully offline once installed.
Which local method is best for sensitive data?
Any method where you can see the code is fine, but a short script you read yourself is the strongest option, because there is nothing hidden to trust. Read the script before running it on sensitive data, keep the original JSON, and prefer a client-side page or a script over any tool that uploads the file.
Can I convert JSON to CSV locally without the internet?
Yes. The converter page works offline once loaded, and Python, jq, Node, VS Code, and Excel all run fully offline. The only step that needs a connection is fetching JSON from a URL, which is optional and separate from the conversion itself.
Why does my local CSV open as a single column?
That is a delimiter mismatch on the opening side, not broken data. Your spreadsheet split the file on a different delimiter than the one it was written with. Re-import the file and choose the matching delimiter, or regenerate the CSV with semicolon or tab, and the columns will appear.
Does converting locally lose any information?
Yes, the same information any conversion loses. Values are preserved but types become text, nested objects become dot-notation columns, and lists become joined cells or JSON text. There is no way back to the original tree from the CSV alone, so always keep the original JSON file.
Try the local method right now
Paste any JSON into the converter on this page and watch it convert inside your browser tab, no upload, no sign-up, nothing leaves your machine. Or copy the Python script and run it on your own files.
Open the JSON to CSV converter