CSV to Markdown Table
Turn CSV or TSV into a GitHub-ready Markdown pipe table — or paste a Markdown table and get CSV back — entirely on this device.
Pretty pads every column to one width — readable as plain text, larger diffs. Backslash-escapes *, _, ` and [ in cells so they render literally. Pipes in cells are always escaped as \| so the table cannot break. GFM renders header cells bold natively — there is nothing to add.
BOM prefixes a byte-order mark so Excel opens the CSV as UTF-8.
A live preview of the table renders here.
Press ? for shortcuts
Do it offline:$ pandoc table.csv -f csv -t gfm
How to use it
- Paste CSV, TSV or a Markdown table, or drop a file — the detected direction shows on a badge one click overrides.
- Pick each column's alignment in the strip above the preview: Left, Center and Right write the :---, :---: and ---: forms.
- Choose Pretty for padded source or Compact for diffs, and decide whether cell line breaks become <br> tags or stop the run.
- Copy the result, download it as .md or .csv, or share the state as a link — credential-shaped input is never stored.
A Markdown pipe table is tedious to type and worse to realign. Paste CSV or TSV and get a GitHub-ready GFM table with per-column alignment, padded for reading or compact for clean diffs — or paste an existing table and get RFC 4180 CSV back. Direction and delimiter are auto-detected, and nothing you paste leaves this device.
How it works
A GFM table is a header row, a delimiter row whose :---, :---: and ---: cells set column alignment, and data rows — each split on its unescaped pipes. This page writes that grammar directly and re-reads it with the same splitting rule, so escaped pipes and <br> line breaks survive the return trip.
Cell text is not rewritten. A pipe leaves as \| because a bare pipe would end the cell early; a backslash against a cell boundary is doubled so the escape survives the return trip. Everything else — asterisks, backticks, brackets — passes through and renders as Markdown unless Escape all is on.
Examples
item,qty,price
Apple,3,1.50
Plum,10,0.75| item | qty | price |
| :---- | --: | ----: |
| Apple | 3 | 1.50 |
| Plum | 10 | 0.75 |Left, right and right become :---- and ----: in the separator row; padding grids the pipes. GitHub reads padded and unpadded source identically.
flag,meaning
a|b,either a or b| flag | meaning |
| ---- | ------------- |
| a\|b | either a or b |A bare pipe would end the cell after the a, so it leaves as a\|b — never optional. The reverse direction restores the plain pipe.
| Package | Downloads | License |
| :------ | --------: | :-----: |
| left-pad | 12,904 | MIT |
| is-odd | 5,510 | MIT |Package,Downloads,License
left-pad,"12,904",MIT
is-odd,"5,510",MITThe colons return as data — the note reads: column alignment from the separator row — Package: left, Downloads: right, License: center — and 12,904 gains quotes: it contains the delimiter.
Every example on this page is executed against the same engine that powers the tool, on every build.
Gotchas worth knowing
Markdown inside cells stays live
Asterisks, backticks and brackets pass through and will render on GitHub; a chip counts the cells. Escape all makes them literal.
Pretty for reading, compact for diffs
Both modes parse to the identical table; compact keeps one edit to one changed line, so review diffs stay honest as the table evolves.
Past 15 columns GFM stops cooperating
GitHub scrolls a wide table rather than wrapping it. Conversion still runs, with a warning — transpose the data or use an HTML table instead.
CJK padding is an approximation
Pretty mode counts East Asian wide characters as double width — true in most monospace fonts, not all. The table stays valid either way.
A missing separator row is tolerated
Reading a table back, no dash row means row one becomes the header with default alignment — a warning says so, nothing invented.
Pipe-delimited CSV can look like Markdown
id|name|qty reads plausibly as either format, so detection never silently guesses: a banner offers both directions and the wrong reading costs one click.
Backticks do not protect pipes
GFM splits rows on unescaped pipes before inline code is read, so a pipe inside backticks still ends the cell. Only \| stays literal.
One column still needs outer pipes
Compact drops outer pipes where GFM allows, but a single-column row without them is plain text — so they stay, with a note.
Cells are strings, never numbers
007 keeps its zeros and 1e3 stays text in both directions — nothing is typed or re-formatted. Inference is the CSV to JSON converter's job.
The header is already bold
GitHub renders header cells bold natively, so that option sits checked and disabled — wrapping cells in asterisks would only add literal characters.
Common errors
a quoted cell never closes at line 2, column 5 — double any " inside the cell as "" and close the quote.- A quote opened a cell that never ended, so everything after reads as one cell. The position marks the opening quote; double inner quotes and close the cell.
row 5 has 4 cells; header has 5 — check for an unescaped |- A row split into a different cell count than the header — usually an unescaped pipe. GitHub would silently pad or drop cells; that moves data, so this tool refuses instead.
no pipe found at line 1, column 1 — a GFM table row separates cells with |, like | name | qty |- The first non-blank line has no pipe, so no header row exists. Paste one table at a time without surrounding prose — a blank line ends a GFM table.
1 cell contains line breaks (rows 2) — switch multiline to <br> to keep them, or remove the breaks- Reject mode stops on a line break inside a quoted cell and lists the rows. Switch multiline to <br> to keep the breaks, or flatten the cells first.
FAQ
Which Markdown table dialect does this produce?
GitHub Flavored Markdown pipe tables — the grammar GitHub, GitLab and most renderers share. MultiMarkdown grids and reStructuredText tables are different syntaxes this page does not write; GFM is the dialect that travels.
Do pipes or line breaks inside a cell survive?
Yes, both ways. Pipes leave escaped as \| with a counting chip; line breaks become <br> tags and return as real breaks. GFM trims cell-edge spaces, and a literal <br> already in a cell reads back as a break unless Escape all is on.
Should I commit the pretty or the compact table?
Compact for tables that keep changing — re-padding rewrites every row and buries the real edit in diff noise. Pretty for files people read as source, where aligned pipes are the point.
Keyboard shortcuts
- ⌘/Ctrl + Enter
- Run the conversion now; above 2 MB this replaces auto-run.
- ⌘/Ctrl + S
- Download the output — .md or .csv, matching the direction.
- ⌘/Ctrl + C
- Copy the whole output when nothing is selected.
- ⌘/Ctrl + Shift + C
- Copy the whole output even while text is selected.
- s
- Swap direction, carrying the output back; one undo restores.
- t
- Switch the theme.
- ? or ⌘/Ctrl + /
- Open the shortcut help overlay.
- Esc
- Dismiss the topmost overlay.