raw Software

Parse CSV with JavaScript

Robert Eisele

CSV looks simple until fields contain delimiters, line breaks, or escaped quotation marks. Splitting rows on newlines and fields on commas is therefore not a correct parser. A maintained parser such as Papa Parse handles these cases and also supports browser files, headers, delimiter detection, and streaming.

Install Papa Parse

npm install papaparse

The former @raw/parsecsv package is no longer available from the npm registry.

Parse a CSV String

import Papa from "papaparse";

const csv = `name,notes
Ada,"line one
line two"
Grace,"uses ""quoted"" text"`;

const result = Papa.parse(csv, {
  header: true,
  skipEmptyLines: "greedy"
});

if (result.errors.length !== 0) {
  console.error(result.errors);
}

console.log(result.data);

The resulting records are:

[
  { name: "Ada", notes: "line one\nline two" },
  { name: "Grace", notes: "uses \"quoted\" text" }
]

With header: true, the first row supplies object keys. Without it, result.data is an array of row arrays. Papa Parse detects common delimiters automatically; set delimiter explicitly when the input contract requires one.

Parse Numbers and Booleans

CSV contains text by default. Enable conversion only when inferred JavaScript values are appropriate:

const result = Papa.parse(csv, {
  header: true,
  dynamicTyping: true,
  skipEmptyLines: "greedy"
});

With dynamicTyping, values such as 42, true, and ISO-like numeric fields may no longer remain strings. Leave it disabled for identifiers with leading zeros, account numbers, or any schema where textual representation matters.

Parse a Browser File

const input = document.querySelector("input[type=file]");

input.addEventListener("change", () => {
  const [file] = input.files;
  if (!file) return;

  Papa.parse(file, {
    header: true,
    worker: true,
    skipEmptyLines: "greedy",
    complete({ data, errors, meta }) {
      if (errors.length !== 0) {
        console.error(errors);
        return;
      }

      console.log(data);
      console.log("delimiter:", meta.delimiter);
    },
    error(error) {
      console.error("Unable to read file:", error);
    }
  });
});

worker: true parses outside the main browser thread. For very large files, use the step or chunk callback instead of retaining every row in memory.

Why the State Machine Matters

A CSV parser must distinguish separators and line endings inside quoted fields from those between fields. A quotation mark inside a quoted field is represented by two quotation marks. The parser also needs to handle CRLF line endings, an optional final newline, empty fields, and malformed rows. Trimming every field is unsafe because spaces inside a quoted value are data, not formatting.

CSV has several dialects rather than one universal format. Agree on delimiter, encoding, headers, and value conversion at the data boundary, and inspect result.errors rather than silently accepting malformed input.