$ snippet parse-csv-browser

Parse CSV in the browser

A correct CSV parser in 25 lines: quoted fields, embedded commas and newlines, doubled quotes — plus a File input example.

JavaScript
/** Parse CSV text into an array of rows (arrays of strings). RFC 4180 compliant. */
function parseCSV(text, delimiter = ",") {
  const rows = [];
  let row = [], field = "", inQuotes = false;
  for (let i = 0; i < text.length; i++) {
    const c = text[i];
    if (inQuotes) {
      if (c === '"') {
        if (text[i + 1] === '"') { field += '"'; i++; }   // escaped quote
        else inQuotes = false;
      } else field += c;
    } else if (c === '"' && field === "") inQuotes = true;
    else if (c === delimiter) { row.push(field); field = ""; }
    else if (c === "\n" || c === "\r") {
      if (c === "\r" && text[i + 1] === "\n") i++;
      row.push(field); rows.push(row); row = []; field = "";
    } else field += c;
  }
  if (field !== "" || row.length) { row.push(field); rows.push(row); }
  return rows;
}

/** First row as headers → array of objects. */
function csvToObjects(text, delimiter = ",") {
  const [header, ...rows] = parseCSV(text, delimiter);
  return rows.filter(r => r.length > 1 || r[0] !== "")
             .map(r => Object.fromEntries(header.map((h, i) => [h.trim(), r[i] ?? ""])));
}

/** Usage with a file input: <input type="file" accept=".csv"> */
async function readCSVFile(file) {
  return csvToObjects(await file.text());
}

How it works

text.split(",") fails the moment a field contains a comma inside quotes, and split("\n") fails on quoted newlines — both common in real exports from Excel and CRMs. A character-by-character state machine handles the three rules of CSV: fields may be quoted, quoted fields may contain delimiters and line breaks, and a literal quote is written as "".

Gotchas

Try it
Result
Ad slot