CSV looks like the simplest format in the world — values separated by commas. Then a value contains a comma, or a quote, or a line break, and a naive split() quietly corrupts your data. Here's what the format actually requires.
CSV feels like the format you don't need to think about. Values separated by commas, rows separated by line breaks — you could parse it with a one-liner. And you can, right up until a customer's name is "Smith, Jr.", or an address field contains a line break, or someone pastes a quote character into a comment. At that point a naive parser doesn't throw an error; it silently shifts every column after the break and hands you plausible-looking, wrong data. That silence is what makes CSV bugs so dangerous. Let's look at exactly where they come from.
Why "split on commas" is a trap
The comma is doing double duty. It separates fields, but it's also a perfectly ordinary character that appears inside real data all the time — in names, in prices written the European way, in free-text notes. The moment a field's own content contains the delimiter, splitting on that delimiter cuts the field in half and every subsequent column is off by one. Nothing in the row looks malformed afterwards; you just have a value in the wrong place and a total that no longer adds up three reports downstream. This is the core problem CSV has to solve, and it solves it with quoting.
The actual specification
There is a real spec — RFC 4180 — and it's short enough to read in one sitting. The rule that matters most is how fields containing awkward characters get protected:
"Fields containing line breaks (CRLF), double quotes, and commas should be enclosed in double-quotes. [...] If double-quotes are used to enclose fields, then a double-quote appearing inside a field must be escaped by preceding it with another double quote."
— RFC 4180, "Common Format and MIME Type for Comma-Separated Values (CSV) Files"
Read that twice, because it resolves all three edge cases at once. A comma inside a field is fine — as long as the field is wrapped in double quotes. A line break inside a field is fine — same rule. And a double quote inside a field is represented by doubling it: "" means one literal quote. So the name She said "hi" becomes the field "She said ""hi""". Ugly, unambiguous, correct.
Edge case one: commas inside a field
The classic. The value Smith, Jr. must be written as "Smith, Jr.". A compliant parser sees the opening quote, reads until the matching closing quote, and treats every comma in between as data rather than a delimiter. A naive line.split(",") sees three commas where there are two fields and produces a phantom extra column. The fix isn't to ban commas in your data — it's to use a parser that honors quoting, and to make sure whatever writes your CSV quotes fields correctly in the first place.
Edge case two: quotes inside a field
This is the one people get wrong even after they've handled commas. Once you're using double quotes to wrap fields, a literal double quote inside the data is ambiguous — is it closing the field or is it content? RFC 4180's answer is escaping by doubling: two double quotes in a row inside a quoted field mean one literal quote character. Miss this rule and a single review comment like 5" screen can terminate a field early and desync the whole row. Encoders that don't double their quotes produce files that look fine in a spreadsheet and explode in a stricter parser.
Edge case three: newlines inside a field
The most surprising one, because it violates the mental model that "one line equals one row." A quoted field is explicitly allowed to contain line breaks. So a multi-line address stored as a single field spans several physical lines in the file, and the row isn't finished until the closing quote appears. This is precisely why you cannot parse CSV by reading it line by line and splitting each line — a single logical record may occupy five lines of text. Any parser that iterates over physical lines is broken by design the moment a field contains a newline; you have to track whether you're currently inside a quoted field.
The CRLF and encoding footnotes
Two smaller traps worth knowing. RFC 4180 specifies CRLF (\r\n) as the line ending between records, but real-world files arrive with plain \n too, so a robust reader accepts both. And CSV carries no encoding declaration of its own — a file is just bytes — so a UTF-8 file opened as Latin-1 (or the reverse) turns accented characters into mojibake. When a CSV mangles names with accents, the format isn't the culprit; a mismatched character encoding is. Decide on UTF-8 and be explicit about it on both ends.
Round-trip it, don't hand-roll it
The reliable way to know your CSV survives these edge cases is to round-trip it and check nothing shifted. Convert your CSV to JSON and eyeball the structure: if a field that should contain a comma or a line break came through whole, your quoting is being honored; if columns are misaligned, the source file wasn't quoted properly. Going the other way, a JSON to CSV converter that follows RFC 4180 will quote and escape fields for you, so the awkward values are protected without hand-editing. And when the JSON in the middle looks tangled, a JSON formatter makes the structure readable so you can confirm the data is intact before you convert back. CSV isn't hard — it's just unforgiving of the assumption that a comma is always a separator. Honor the quotes and it round-trips perfectly.
← All articles