You exported a list from a database, a spreadsheet, an analytics dashboard. It came out as CSV. The thing you need to feed it into wants JSON — an API endpoint, a Node.js seed script, a config file, a no-code workflow. You could write a 5-line Python script. You could also paste the CSV into a free converter and have JSON in three seconds.
This guide covers all three approaches: the browser-only converter, the Excel/Sheets-and-paste workaround, and a one-liner of code for when you happen to have a terminal open. It also covers the parts that actually go wrong — quoted fields with commas inside, leading-zero codes that get mangled, the BOM byte that confuses half of all parsers — so the conversion you do once is the conversion that survives downstream.
The fastest path is at the top: paste, click, copy. The rest is for when the easy path needs sharpening.
Why CSV and JSON keep showing up together
CSV is the universal export format. Every spreadsheet, every database, every analytics tool can dump CSV. JSON is the universal API and modern-tool format — REST APIs return it, Node and Python natively understand it, almost every modern config tool consumes it.
So the conversion that 90% of small-to-medium teams actually do is CSV in, JSON out. Or the reverse — exporting a JSON API response to CSV so a non-technical colleague can open it in Excel. The conversion itself is mechanical, but mechanical does not mean trivial. There are six ways CSV parsing breaks if the converter is naive, and most of them only show up on the specific row that breaks production.
Method 1: the browser-only converter (recommended)
For 95% of conversions, the right answer is paste-into-browser. The CSV to JSON converter handles the parsing edge cases (quoted fields, escaped quotes, embedded newlines, custom delimiters), runs entirely in your browser, and supports both auto-typed and string-only output.
- Paste your CSV into the input box.
- Confirm the delimiter (comma, semicolon, tab — auto-detected for common cases).
- Choose whether the first row is a header (almost always yes).
- Toggle
infer typesif you want numbers and booleans converted, or leave it off to keep everything as strings. - Click Convert. Copy the JSON or download as a file.
Done. For a typical 100–10,000 row CSV this is a five-second operation. The browser does not upload your data — it parses locally — which matters if the file contains customer details, financial data, or anything else you would rather not have sitting on someone else's server.
Method 2: Excel or Google Sheets, manually
In Google Sheets, open Extensions > Apps Script, paste a small JavaScript snippet that reads the active range and JSON.stringify it, run, copy the output. In Excel, use Power Query (Data > From Table/Range) and convert with the M formula language. Both work for one-off conversions and break down when the source has nested data or hundreds of thousands of rows. If you find yourself doing this twice, switch to method 1 or 3.
Method 3: one line of code
For developers who already have Node or Python open: this is a one-liner. Node.js with the standard library:
const fs = require('fs');
const csv = fs.readFileSync('input.csv', 'utf8');
const [headers, ...rows] = csv.trim().split('\n').map(r => r.split(','));
const json = rows.map(r => Object.fromEntries(headers.map((h, i) => [h, r[i]])));
fs.writeFileSync('out.json', JSON.stringify(json, null, 2));Python is just as short:
import csv, json
with open('input.csv') as f:
rows = list(csv.DictReader(f))
with open('out.json', 'w') as f:
json.dump(rows, f, indent=2)These work for clean, simple CSV. For real-world files with quoted commas or embedded newlines, switch to a CSV-aware library (papaparse for Node, the csv module for Python). Or paste into CSV to JSON and skip the parser implementation entirely.
The CSV parsing gotchas (where naive scripts fail)
CSV looks simple. It is not. RFC 4180 defines the format and every line of it exists because some tool emitted CSV that broke a parser somewhere. A quick tour of the five gotchas that account for 90% of broken conversions:
Quoted fields with commas inside
Smith, Jane, "Engineer, Senior", 95000 looks ambiguous. The CSV spec says the quoted comma is a literal value, not a delimiter — so this is 4 fields, not 5. A naive split-on-comma parser gets it wrong every time.
Escaped quotes
How do you encode a literal quote inside a quoted field? Double it. "He said ""hello""" parses as He said "hello". Most spreadsheets emit this when a value contains quotes; naive parsers ignore it and mangle the output one row in twenty.
Embedded newlines
A quoted field can span multiple lines: "Line 1\nLine 2". This is legal CSV, common in product descriptions. Splitting by line first and parsing fields second breaks here, because the row count goes wrong as soon as one field has a newline.
UTF-8 BOM
Excel's CSV export starts with a 3-byte sequence (EF BB BF) called a BOM, invisible in most text editors. Naive parsers include it as part of the first column header — so name becomes \ufeffname. Every JSON consumer downstream then looks for name and gets nothing.
Different delimiters
German and French Excel use ; as the delimiter because , is their decimal separator. TSV files use tabs. A converter that hardcodes commas fails for half the world. Auto-detection is a must.
""" — try the same input through the browser tool to confirm the input is parseable at all. It almost always is, and the bug is in your parser, not your data.JSON output shapes
Once the CSV is parsed, you have to choose what shape the JSON takes. Three common options, each with a clear use case:
Array of objects (default)
One object per row, keyed by header names. This is the default and what 90% of consumers expect:
[
{ "id": 1, "name": "Acme", "active": true },
{ "id": 2, "name": "Globex", "active": false }
]Object keyed by primary key
Useful when downstream code does lookups by ID. The reading code becomes data[42] instead of data.find(r => r.id === 42):
{
"1": { "name": "Acme", "active": true },
"2": { "name": "Globex", "active": false }
}Array of arrays
Header-less, just rows. Useful for streaming and large datasets where you do not want repeated key strings on every row. Rare in practice, but supported because some chart libraries and data viz tools expect this shape.
The CSV to JSON converter offers all three. Pick based on what the downstream tool expects — if you are not sure, default to the array of objects, which is what every API and every modern config consumer accepts.
Type inference: when to enable it, when not to
CSV stores everything as text. JSON has real types — numbers, booleans, null. Most converters offer type inference: 42 becomes the number 42, true becomes the boolean true, an empty cell becomes null. This is what you usually want, because the alternative is "42" everywhere and downstream code coercing strings.
What you do not want: type inference that mangles data. Common cases that break:
- Product codes that start with
0(0123) lose the leading zero when parsed as numbers. - Phone numbers with
+get converted to negative numbers (+1becomes1) or stay as strings depending on the parser. - Dates in
MM/DD/YYYYformat get parsed and reformatted in some converters and preserved as strings in others, with no consistency. - Long IDs like
1234567890123456789get truncated to JavaScript number precision (about 15–16 digits). - US ZIP codes (
01234) and credit-card-like numbers lose leading zeros silently.
For those cases, turn off type inference and treat everything as strings. The downstream code can cast what it needs. The leading-zero case is the one that bites you a week later when someone notices a SKU is wrong.
code-like — product SKUs, ZIP codes, country phone codes, scientific identifiers — turn off type inference, or specifically opt in to string mode for that column. Once a number loses its leading zero, the value is gone and reparsing does not recover it. This is the single most common cause of the migration looked fine but production broke.Going the other way: JSON to CSV
JSON is more expressive than CSV — it has nesting, arrays, and types. CSV has flat rows of strings. So JSON-to-CSV always loses something, and the lossy parts are the parts you have to think about before converting.
Flat JSON (works cleanly)
[{ name, age, email }, ...] converts to CSV directly. Use JSON to CSV and the headers come straight from the object keys. The output is identical to what a sane backend would emit if you asked for a CSV export of the same data.
Nested JSON (needs flattening)
{ user: { name, address: { city } } } has no native CSV equivalent. The standard answer is dot-notation: user.name, user.address.city. The JSON to CSV tool does this automatically.
[{ "user": { "name": "Jane", "address": { "city": "Berlin" } } }]user.name,user.address.city
Jane,BerlinFor arrays inside JSON ({ user, tags: ["a", "b"] }), there are two strategies. Flatten with index suffix (tags.0, tags.1) preserves order with ugly headers. Or join as a string (tags: "a;b") — readable, but loses the array nature.
Debugging when the output looks wrong
If your converted JSON looks weird — wrong row count, missing fields, garbage in the first column — start here:
- Run the JSON through JSON Validator to confirm the shape is at least valid JSON.
- If valid but ugly, run it through JSON Formatter for an indented view that exposes the structure.
- If still wrong, the issue is upstream. Open the original CSV in a plain text editor (not Excel) and look for: stray BOM at the start, unbalanced quotes, mixed-mode line endings (
\r\nvs\n). - Re-paste into CSV to JSON with
infer typestoggled off. See if the raw string output makes sense first, then add typing on top. - If the output JSON is enormous, run it through JSON Minifier to shave whitespace before piping to a downstream tool with payload limits.
For very large files (100MB+) the in-browser converter can hit memory limits. At that scale, switch to a streaming converter — papaparse in Node, pandas.read_csv with chunksize in Python — which processes row-by-row and never loads the whole file into memory.
Real-world example: Shopify product export to JSON
Common scenario: 5,000-row Shopify product export. The CSV has quoted HTML in the body field, decimal prices, and integer inventory counts:
Handle,Title,Body (HTML),Vendor,Price,Inventory
hat-001,"Classic Hat","<p>A hat. With <em>flair</em>.</p>",Acme,29.99,42
mug-002,"Coffee Mug","<p>Holds coffee.</p>",Acme,12.50,150Pasted through the CSV to JSON converter with type inference on, output:
[
{ "Handle": "hat-001", "Title": "Classic Hat", "Body (HTML)": "<p>A hat. With <em>flair</em>.</p>", "Vendor": "Acme", "Price": 29.99, "Inventory": 42 },
{ "Handle": "mug-002", "Title": "Coffee Mug", "Body (HTML)": "<p>Holds coffee.</p>", "Vendor": "Acme", "Price": 12.50, "Inventory": 150 }
]The HTML survives intact because it was quoted. Prices and inventory are numbers; the rest are strings. This is exactly the shape a Node.js seed script needs:
const products = require('./products.json');
for (const p of products) {
await db.products.insert({
handle: p.Handle,
title: p.Title,
body: p['Body (HTML)'],
price_cents: Math.round(p.Price * 100),
inventory: p.Inventory
});
}Total time from download CSV to running seed: about two minutes. The browser converter is faster than rolling your own for any file you will only convert once or twice. Bookmark CSV to JSON and JSON to CSV together; you will reach for them more often than you expect.
Workflow summary
- Drop your CSV into CSV to JSON.
- Verify delimiter and header row are detected correctly.
- Toggle
infer typesbased on whether your data has code-like columns. - Pick output shape: array of objects (default), keyed object (for lookups), or array of arrays.
- Copy the JSON or download the file.
- If the result looks off, run it through JSON Validator to confirm shape, then back to the parser.
- For the reverse direction, paste your JSON into JSON to CSV and pick a flattening strategy.
JSON, CSV, and XML tools used in this guide
For XML-shaped sources (SOAP responses, RSS feeds, config files), the same flow works through XML to JSON — convert to JSON first, then to CSV if you need a flat shape.
Frequently Asked Questions
Is converting CSV to JSON in the browser safe for sensitive data?
Yes. The conversion runs entirely in your browser using JavaScript that loads once with the page. Nothing is uploaded, and you can verify by opening browser devtools, switching to the Network tab, and watching while you convert — there are no outbound requests. This makes it safe for customer data, financial exports, and other content you would not paste into a server-side tool.
Why does my CSV parse with weird first-column names?
Almost always a UTF-8 BOM. Excel exports CSV with a 3-byte invisible prefix (`EF BB BF`) at the start, and naive parsers treat it as part of the first header. So `name` becomes `\ufeffname`. The [CSV to JSON](/csv-to-json) converter strips the BOM automatically; if you wrote your own parser, prepend a `text.replace(/^\uFEFF/, "")` step.
Should I use type inference on my CSV?
Yes for numeric and boolean data. No for code-like columns — product SKUs, ZIP codes, phone numbers with leading zeros, long IDs that exceed JavaScript number precision (15+ digits). When in doubt, do one conversion with inference on and one with it off, and compare. The string-only output is always recoverable; the typed output sometimes is not.
How do I convert nested JSON to CSV without losing data?
You cannot fully — CSV is flat. The standard workaround is dot-notation flattening: `user.address.city` becomes a column. The [JSON to CSV](/json-to-csv) tool does this by default, and it round-trips cleanly back to the same nested shape if you re-import. For arrays inside objects, you have to choose between index-suffix columns (`tags.0`, `tags.1`) or joined strings (`tags: "a;b"`).
What is the largest CSV the browser converter can handle?
Roughly 50MB on a typical laptop, sometimes up to 100MB on a desktop with plenty of RAM. Past that, the browser tab can run out of memory because it loads the whole file in at once. For larger files, switch to a streaming command-line tool — `papaparse` in Node or `pandas.read_csv` with chunked reading in Python.
Why does my converted JSON have wrong row counts?
Almost certainly because of embedded newlines inside quoted fields. A product description like `"Line 1\nLine 2"` is legal CSV but a single field, not two rows. Naive line-by-line parsers split on the newline first and get confused. Use a CSV-aware parser (which [CSV to JSON](/csv-to-json) is) or open the source in a plain text editor and look for un-balanced quote marks.
Can I convert XML or YAML data the same way?
Yes for XML — use [XML to JSON](/xml-to-json) and then [JSON to CSV](/json-to-csv) if you need a flat shape. YAML is not directly supported in the browser tools but converts cleanly via Python (`yaml.safe_load` plus `json.dump`) or any small CLI conversion script. The chain `XML → JSON → CSV` covers most legacy data sources.