What this tool does

CSV Viewer opens a CSV or TSV file (up to 25 MB) in a fast, sortable, searchable table, entirely in your browser. No upload, no server, no row limit besides what your browser can fit in memory. A 100,000-row file scrolls smoothly because the table is virtualized: only the rows currently in view are rendered to the DOM.

This is the tool you reach for when Excel chokes, Google Sheets refuses to open it, or you just want to glance at a file without spinning up a notebook. Drop the file, get a table, sort/filter, move on.

How to use it

1. Drop a file onto the page, click the empty-state card to pick one, or hit Sample to load a small example. 2. Click any column header to sort. First click sorts ascending, second click descending, third click clears the sort. Sort is type-aware, numbers compare numerically, dates by ISO order, text by locale-aware natural order. 3. Type into the search box to filter across every cell. The row count updates ("85 of 12,400 rows") so you can see how aggressive your filter is. 4. Drag the right edge of any header to resize that column. Widths persist for the current session.

What the parser handles

Under the hood it's the same RFC 4180-compliant parser as the CSV-to-JSON tool, quoted fields with embedded commas or newlines, escaped quotes (""), Excel-style BOMs, and CRLF line endings all work without configuration.

The delimiter is auto-detected from the first non-empty line by scoring comma / tab / semicolon / pipe. If your file uses something unusual the parser may pick the wrong character; in that case rename the file to .tsv (forces tab) or paste into the CSV-to-JSON tool which has a manual delimiter dropdown.

Type inference

Columns get one of three inferred types based on the first 100 rows:

  • number, every non-empty value parses as a finite number. Right-aligned, sorted numerically.
  • date, every non-empty value matches an ISO-style date prefix. Sorted lexicographically (which is also chronological for ISO dates).
  • string, anything else. Sorted with the browser's localeCompare in numeric: true mode, so "item2" comes before "item10" instead of after.

The badge in the column header (#, ◷, A) tells you which one was picked. If you see A on a column you expected to be a number, look for stray non-numeric values or leading zeros that prevented numeric inference.

Performance

The table uses windowed rendering, at any moment only the ~30 rows visible in the scrollable area exist as DOM nodes. Scrolling produces and discards rows on the fly, so a 200,000-row file feels exactly like a 200-row file. Sorting and filtering happen in plain JavaScript over the in-memory array; expect single-digit milliseconds for 100k rows.

The browser's hard ceiling is memory, not row count. A 25 MB CSV typically holds 200k–500k rows of moderate width. Anything bigger, and the file picker rejects the load before the parser sees it.

Common gotchas

  • Sort doesn't sort numbers correctly? Check the type badge in the header. If it shows A instead of #, the column has at least one non-numeric value (maybe a stray header repeated, or N/A instead of empty). Numbers fall back to string sort in that case.
  • Search only filters, doesn't highlight. The match logic is cell.toLowerCase().includes(query). Quotation marks in your query are treated literally, not as exact-match.
  • Resized columns reset on reload. Widths are session-state, they don't persist to localStorage. Reloading the page restores the auto-fit defaults.
  • File too large. The 25 MB cap is enforced at upload time. To view larger files, run head -n 100000 big.csv > sample.csv and view the sample.

Privacy

The file you load, the parsed rows, and any column widths you set stay entirely in your browser. The "recent" list stores only file names (not contents) in localStorage. Nothing about the data leaves the page.

Frequently asked

Does the file leave my browser?

No. The file is read with the browser's FileReader API and parsed locally in JavaScript. Nothing is uploaded. The recent-inputs list saves filenames only (no contents), and only to localStorage.

What's the file size limit and why?

25 MB. The cap exists because the parser holds the entire dataset in memory plus a virtualized table on top. Most browsers handle 25 MB CSVs fluidly; bigger files risk freezing the tab. For larger data, slice the file (head -n 100000 big.csv > sample.csv) and view the sample.

How does the auto-detected delimiter work?

The sniffer counts candidate characters (comma, tab, semicolon, pipe) on the first non-empty line and picks the most consistent one. If your file uses an unusual delimiter, the parser may guess wrong — rename to .tsv to force tab, or use the CSV-to-JSON tool which has a manual delimiter dropdown.

Why is my number column sorting alphabetically?

Check the type badge in the column header. # means number, ◷ means date, A means string. If a numeric column inferred as A, it has at least one non-numeric value in the first 100 rows — usually a placeholder like 'N/A' or a stray header. Clean those values and reload.

What does the third click on a header do?

Tri-state sort. First click ascending, second click descending, third click clears the sort and returns to file order. The aria-sort attribute and the arrow indicator update to match.

Can I edit cells in the table?

No — this tool is read-only. It's designed for fast inspection, not editing. If you need to modify values, export to JSON with the CSV-to-JSON tool and use a JSON editor, or open in Excel/Sheets for spreadsheet-style editing.

How does search interact with sort?

Search filters first, then sort applies to the filtered subset. The row count display reflects this ('85 of 12,400 rows'). Clearing the search restores all rows and keeps your active sort.

Why don't column widths persist between sessions?

Resized widths are session-state only. They reset on reload to type-aware defaults (numbers 110px, dates 120px, strings sized to the header text). Persisting widths per-file is possible but would require keying by file content hash, which is more complexity than the use case warrants.