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'slocaleCompareinnumeric: truemode, 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
Ainstead of#, the column has at least one non-numeric value (maybe a stray header repeated, orN/Ainstead 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.csvand 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.