CSV has a spec. Almost nobody follows the same one.
RFC 4180 says: commas between fields, CRLF between records, double quotes around fields that contain either, and a quote inside a quoted field written twice. Real files use semicolons, tabs, backslashes, stray quotes and whatever encoding the exporting machine liked. This page reads a file character by character with a state machine, guesses its dialect, profiles every column, flags what a spreadsheet will silently change, and shows five parsers disagreeing about the same bytes.
Each column below is a real parser written here with one behaviour switched: splitting lines on commas (what a quick script does), strict RFC 4180, skipping spaces after a delimiter (Python’s skipinitialspace), backslash escapes (MySQL’s default ESCAPED BY), and dropping blank lines (what pandas does). Edit the text or pick a trap.
Choose how fields are quoted, the delimiter, line endings and BOM. The output is parsed again with the strict reader and compared field by field. “Defuse formulas” prefixes cells that start with = + − @ (and tab or CR) with an apostrophe, which OWASP recommends against CSV injection.
order_id,sku,postcode,qty,date,customer,comment␍↵1001,MARCH1,02134,3,03/04/2026,"Smith, J",ok␍↵1002,1E5,90210,1,13/04/2026," ""Lee"," K""",spaces before the quote␍↵1003,SEPT2,00501,2,4-5,"Ana ""the boss"" Ruiz",bare quotes␍↵1004,AB-77,10115,5,2026-04-14,"O\Neil""",backslash escape␍↵␍↵1005,ZX-9,4111111111111111,1,2026-04-15,"'=HYPERLINK(""http://evil.example""",Click),formula␍↵1006,QQ-1,75001,2,2026-04-16,Müller,extra,fields,here␍↵1007,QQ-2,1000,1,2026-04-17,"unterminated,never closed1008,QQ-3,2000,1,2026-04-18,Late,row"␍↵file = [header CRLF] record *(CRLF record) [CRLF]record = field *(COMMA field)field = escaped / non-escapedescaped = DQUOTE *(TEXTDATA / COMMA / CR / LF / 2DQUOTE) DQUOTEnon-escaped = *TEXTDATATEXTDATA = %x20-21 / %x23-2B / %x2D-7ETEXTDATA is printable ASCII only: the RFC itself has no answer for “é”. Every real reader extends it to any non-delimiter character.