CSV to JSON Converter
Convert CSV or TSV into JSON in your browser — RFC 4180 parser with auto-delimiter detection and type coercion.
Runs online in your browserNo installNo accountFree
How to use CSV to JSON Converter
- Paste your CSV, TSV, or any delimited text into the input panel on the left. The Load sample button fills in a worked example if you want to see the output shape first.
- Leave "Delimiter" on Auto-detect for most inputs, or pick a specific character (comma, semicolon, tab, pipe) if you know the format. Use "Custom…" for a single-character delimiter not in the preset list.
- Toggle "Header row" off if the first row is data rather than column names — the output switches from an array of objects to an array of arrays.
- Flip on "Coerce numbers" or "Coerce booleans" to get typed JSON values; leave them off to keep every cell as a string, which is the safe default for unknown data.
- Use "Trim values" to strip whitespace on unquoted cells, and "Empty → null" to turn blank cells into JSON `null` instead of empty strings.
- Toggle "Pretty-print" off to get minified single-line JSON — handy when you're pasting into a shell script or an HTTP request body.
- Press ⌘/Ctrl + Enter to copy the JSON output, or use the Copy JSON button in the action bar.
- Click Share to generate a URL that restores your input and settings in any browser. Share links live entirely in the URL fragment and never hit a server.
CSV to JSON Converter
A zero-dependency, browser-local CSV (and TSV) to JSON converter with a real RFC 4180 parser at its core. Paste a spreadsheet export, a database dump, an API CSV response, or anything with delimiters — get back clean, typed JSON without the round-trip to a server. Auto-delimiter detection, header-row resolution, type coercion, and error reporting all run locally, and the output updates on every keystroke.
Why a dedicated CSV→JSON converter
Almost every online "CSV to JSON" tool is built on input.split("\n").map(l => l.split(",")). That breaks on the first quoted field containing a comma, the first embedded newline, the first escaped quote, the first CRLF line ending. Failures are usually silent — you get JSON that looks plausible but has cells shifted across columns and quotes leaked into values.
The second problem is privacy. CSV is one of the most common ways to move sensitive tabular data: customer exports, billing rows, invoice lines, HR spreadsheets. Server-side converters log every paste, often through a CDN and an error tracker too. A browser-local parser eliminates that exposure.
The third problem is type handling. Naïve coercion (parseFloat(cell)) is how databases end up with 7 in a column that used to hold "007". CSV is a string-only format, so the safe default is strings; anything else has to be opt-in with rules that recognise identifier patterns.
This tool runs a character-by-character state-machine parser locally. The tokeniser is ~200 lines of TypeScript, zero runtime dependencies, and handles the full RFC 4180 surface. Type coercion runs as a separate pass, so the parse itself can never lie about the input. Errors carry line and column so you can fix the source.
What it does
- Parse CSV, TSV, or any delimited text — comma, semicolon, tab, pipe, or a custom single-character delimiter.
- Auto-detect the delimiter by scoring the first ten logical lines for column consistency, with the pick shown as a badge on the input panel.
- Handle real-world edge cases: quoted fields with commas, escaped quotes (
""), embedded newlines, CR / LF / CRLF endings, leading UTF-8 BOM, ragged rows, trailing blank lines. - Optional type coercion: numeric-looking cells to numbers (preserving leading-zero identifiers),
"true"/"false"to booleans, empty cells to JSONnull. - Header-row toggle: emit an array of objects keyed by the first row, or an array of arrays when the data has no column names. Empty header cells get
column_Nplaceholders. - Trim whitespace on unquoted cells without touching quoted content, and promote empty strings to
nullwith one click. - Output control: pretty-print with 2-space indent or minify to a single line. A row-count badge shows exactly how many records you got.
- Typed parse errors: unclosed quotes return an explicit "line X, column Y" message instead of silently emitting a shifted matrix.
- URL-hash share: input and every option encoded into
#s=…for private, peer-to-peer sharing.
Under the hood
The parser is a single-pass state machine with two states — inside quotes and outside — handling one character per iteration. That structure makes RFC 4180 tractable: every edge case is a small transition rule rather than a regex with backtracking.
Outside quotes, a leading double-quote flips the state to "inside" and marks the field as quoted. A delimiter ends the field; LF, CR, or CRLF ends the row. A stray mid-field quote like ab"cd stays literal, matching csv-parse with relax_quotes on.
Inside quotes, every character is literal including commas and newlines. A double-quote closes the field, or when paired as "" is an escaped literal quote. Embedded CRLF pairs are normalised to \n.
Delimiter auto-detection runs before the main parse. It samples the first ten non-blank logical lines — honouring quoted newlines so a quoted \n doesn't split a row — and scores each candidate by average column count and variance. Ties fall back to , ; \t |.
Type coercion is conservative. The number check requires optional sign, integer, optional fraction, optional exponent, with no leading zeros on multi-digit integers, so 007, 01234, and 00.5 stay strings. Boolean coercion only matches exact "true" or "false" (case-insensitive); it won't misread "True story". Empty strings become null only when you opt in.
Header mode fills missing column names with column_N placeholders. Ragged rows shorter than the header pad with empty strings; longer rows drop extras, keeping the output matrix rectangular.
RFC 4180 compliance
RFC 4180 is a 2005 informational memo that codified CSV as the industry had settled on it. It is the de-facto reference every CSV tool targets. This parser implements the parts that matter:
- Fields separated by the delimiter; rows separated by CRLF, bare LF, bare CR, or any mix.
- Double-quoted fields that may contain the delimiter, CR, LF, and CRLF.
- Double-quote escaping via doubling (
""represents a literal"inside a quoted field). - Optional header row, toggleable in the UI.
- Leading UTF-8 BOM tolerated and stripped silently — Excel on Windows emits it.
Behaviours outside the memo that this tool handles anyway:
- Delimiters other than comma — semicolon (European Excel), tab (TSV), pipe (legacy ETL).
- Mixed line endings inside a single document.
- Trailing blank rows, dropped automatically.
- Ragged rows, padded or truncated to match the header.
- Stray unmatched quotes mid-field, kept as literal characters rather than raising an error.
Privacy
No analytics on input content, no server round-trip, no third-party script in the transform path. The parser is a pure function of your CSV and your options — no network calls, no logging, no server round-trip. We do load Google Analytics 4 for aggregate page-view counts (cookieless by default, honours DNT/GPC — details), but it never receives textarea content, file contents, or URL-hash state. The Share button encodes a base64url snapshot into the URL fragment (#s=…), which HTTP spec guarantees is never transmitted to any server. Sharing a link is a peer-to-peer transfer of state, not an upload.
For CSV specifically, on-device parsing is the difference between "I debugged my customer export" and "I uploaded my customer export." Spreadsheets carry more PII per kilobyte than almost any other format, and a parser that only runs locally removes the question.
What's not supported (yet)
- JSON to CSV (the reverse direction): planned as a separate tool. In the meantime, JSON to YAML covers the common "serialise JSON into a human-readable row format" case.
- Multi-character delimiters: the parser operates on single characters by design, covering CSV, TSV, SSV, and pipe-delimited formats. For
||or|~|delimited exports, pre-process with find-and-replace down to a single character. - Streaming for very large files: documents that fit in browser memory parse fine (tens of megabytes are comfortable). Larger files should go through a CLI tool like
csvkitorpapaparsein a Node script — partial output in the UI would be worse than a clean "too big" signal. - Custom column types: the coercion layer has three knobs applied uniformly across every cell. Per-column schema control is on the v1.1 roadmap.
- Dialect auto-detect beyond delimiter: quote character is fixed at
"and escape convention is doubled-quote. Single-quoted CSVs and backslash-escape dialects are rare enough we have not hit them in user traces.
Related tools
- JSON Formatter and Validator — the natural next step after conversion. Pretty-print the JSON at a custom indent, minify it, or validate the structure against a live error banner.
- JSON to YAML Converter — if the final destination is a config file or Kubernetes manifest, convert the CSV here then pipe the JSON through YAML.
- JSONPath Evaluator — filter, project, or extract specific fields from the array of records.
$[?(@.active==true)].emailis a one-liner on the converter's output. - JSON Diff — convert two CSV snapshots to JSON and diff them structurally, which is almost always more useful than diffing the raw CSV text.
- Sort Lines — pre-process a messy CSV (dedupe, sort alphabetically) before feeding it to the converter when you want canonical ordering.
Frequently asked questions
Does the CSV I paste ever leave my browser?
No. The parser runs entirely on your device — there is no CSV-handling endpoint on dev101.io. We wrote the RFC 4180 tokeniser from scratch in a few hundred lines of TypeScript so the tool has zero network dependencies. That matters for CSV specifically because spreadsheets are a favourite way to move customer lists, invoice rows, transaction logs, and user exports around; pasting one into a server-side converter effectively hands that data to a third party. The optional Share button encodes state into the URL hash (the part after `#`), which by HTTP design is never transmitted to any server.
How does auto-delimiter detection work?
When "Auto-detect" is selected, the parser samples the first ten non-blank logical lines of your input (honouring quoted embedded newlines) and scores each candidate delimiter — comma, semicolon, tab, pipe — by average column count and variance. The delimiter that produces the most columns with the most consistent row width wins. Ties break in favour of comma, then semicolon, tab, and pipe in that order. If your input has exactly one column, detection falls back to comma and you still get a valid result.
What does "RFC 4180 compatible" mean in practice?
RFC 4180 is the informal CSV spec most tools target. In concrete terms, this parser handles quoted fields that contain the delimiter (`"hello, world"`), doubled-up escaped quotes (`"she said ""hi"""`), embedded CR / LF / CRLF inside quoted fields, and mixed line endings across the document. It also strips a leading UTF-8 BOM — Excel exports on Windows often carry one — and drops trailing blank lines. Unclosed quotes return a typed error with the line and column of the starting quote, instead of silently producing garbage output.
Why does "007" stay a string even when "Coerce numbers" is on?
Leading-zero sequences are almost always identifiers — account numbers, phone numbers, ZIP codes, SKUs. `Number("007")` would silently turn them into `7`, losing the zeros forever, and that's exactly the kind of data corruption CSV-to-JSON tools are infamous for. Our number-coercion rule rejects any multi-digit integer that starts with zero; decimals, negatives, and scientific notation (`1e3` → `1000`) are all converted normally. If you genuinely want numeric conversion on zero-padded values, pre-process the column with your editor's find-and-replace before pasting.
What's the difference between header mode and no-header mode?
With "Header row" on (the default), the first row is treated as column names and every subsequent row becomes a JSON object keyed by those names — the most common shape when you're loading a CSV into a database or an API request body. With it off, each row becomes a JSON array of cell values; useful when the CSV has no meaningful column names or you're doing positional transforms. You can switch modes at any time; the output updates live.
Can this tool also convert TSV (tab-separated values)?
Yes. Pick "Tab (\t)" from the delimiter dropdown, or leave it on "Auto-detect" — the detector will spot the tab character without any configuration. TSV is the usual output format when you copy a range from Excel, Google Sheets, or Numbers, so "paste from spreadsheet → get JSON" works in two clicks. Semicolon-separated exports from European locales of Excel and pipe-delimited dumps from legacy ETL pipelines work the same way.
What happens to ragged rows where a cell is missing at the end?
Missing trailing cells are treated as empty strings, so a header row of four columns paired with a data row of three cells gives you an object with four keys where the fourth value is `""` (or `null`, if "Empty → null" is on). Extra cells past the header are silently dropped — we assume a misaligned row is a data problem worth flagging in your own pipeline, not a parser bug to paper over. Rows shorter than the header never raise an error, so you can still load a messy export and see exactly where the gaps are in the output.