Convert TSV (Tab-Separated) Files to Markdown Tables
tsv to md tables straight from a file or from your clipboard — a range copied out of Excel, Google Sheets or Numbers is already tab-delimited, so pasting it needs no export step. PapaParse reads the delimited text in a Web Worker, escapes pipes inside cells, and emits a GitHub Flavored Markdown pipe table with the column alignment you choose.Processing happens 100% in your browser — nothing is uploaded.
How to convert TSV to Markdown
- Provide the data: drop a .tsv file onto the dropzone, or copy a range from your spreadsheet and paste it straight into the editor.
- Local processing: PapaParse detects the delimiter (or uses the tab you set explicitly) in a Web Worker, then builds a GFM pipe table with your header and alignment settings.
- Copy or download: copy the Markdown table to your clipboard or save it as a .md file for a README, a wiki page or a pull request.
Why Convert TSV to Markdown with MD Convert?
Paste a spreadsheet range directly
The clipboard format for Excel, Sheets, Calc and Numbers is tab-delimited text, so a copied selection is exactly what the parser expects. That skips the export dance — save as CSV, pick an encoding, find the file — and the delimiter ambiguity export introduces, since a CSV export of European data often uses semicolons.
Alignment written into the delimiter row
GFM encodes alignment through colon placement: :--- left, :---: centre, ---: right. You set it per column here instead of hand-editing dashes afterwards, and three dashes — the GFM minimum — is what gets emitted, since padding the delimiter row adds bytes with no rendering effect.
Pipes escaped, rows kept in sync
Every | inside a cell is escaped as \| before output. Without it, one pipe in a URL, a regex or a log line splits a cell in two and shifts every later value out from under its header — the quiet way a generated table starts reporting the wrong numbers. Newlines inside quoted fields collapse to spaces for the same structural reason.
Ragged rows warn instead of failing
The column count comes from the widest row and short rows are padded with empty cells, so a copied range with a trailing blank column still yields a well-formed table. PapaParse's recoverable issues surface as a warning naming the first few, which is usually enough to find a stray tab.
TSV to Markdown: Before and After
Tabs separate the fields, the first row becomes the header, and the delimiter row carries the per-column alignment you choose — `:---` left, `:---:` centre, `---:` right. Numeric columns read far better right-aligned.
region units revenue
EMEA 1204 48160
APAC 980 39200
LATAM 415 16600| region | units | revenue |
| :--- | ---: | ---: |
| EMEA | 1204 | 48160 |
| APAC | 980 | 39200 |
| LATAM | 415 | 16600 |Understanding the TSV Format: IANA text/tab-separated-values
- Format
- Tab-Separated Values
- Specification
- IANA text/tab-separated-values
- Media type
text/tab-separated-values- Parser used
- PapaParse
TSV is the simpler half of the delimited-text family. Fields are separated by a single horizontal tab (U+0009) and records by a line break, and the IANA registration says nothing about quoting — because it does not need to. A tab is a character almost nobody types inside a data value, so the ambiguity that forces CSV to define quoting, escaped quotes and embedded newlines largely does not arise.
That simplicity is why TSV is the clipboard format for spreadsheets. Copy a range in Excel, Google Sheets, LibreOffice Calc or Numbers and what lands on the clipboard is tab-delimited text — which is why pasting a spreadsheet selection straight into this converter works with no export step, no file and no intermediate save.
Parsing is PapaParse, run on demand in the browser. It handles the cases the bare format leaves open — quoted fields that do contain a tab or a newline, CRLF line endings from Windows, a trailing newline at end of file — and reports ragged rows as recoverable issues rather than refusing the input.
Pasting straight from Excel, Sheets or Numbers
The paste path is the fast one and it needs no file at all. Select a range in your spreadsheet, copy it, and paste into the text input: the clipboard already holds tab-delimited text, so what arrives is exactly what the parser expects. This avoids the usual export dance — save as CSV, pick an encoding, find the file in Downloads — and it avoids the delimiter problem that export introduces, since a CSV export of European data often uses semicolons.
Delimiter handling is explicit or automatic, your choice. Set the delimiter to tab and it is used literally; leave it on auto and PapaParse scores the candidate delimiters against the input and picks the one that yields a consistent column count. Auto is right for pasted content of unknown origin, and an explicit tab is right when a data value contains a comma that would otherwise skew detection.
Header handling is a toggle rather than a guess. It defaults to treating row one as the header, because that is what a copied spreadsheet range almost always contains. Turn it off for headerless data and the converter emits `Column 1`, `Column 2`, … instead — GFM requires a header row, so there is no valid pipe table without one.
Column alignment in the delimiter row
GFM encodes alignment in the delimiter row, using colon placement: `:---` for left, `:---:` for centre, `---:` for right, and a bare `---` to leave it to the renderer's default. The converter exposes this per column, so you set alignment once here instead of hand-editing dashes in your editor afterwards.
Three dashes is the minimum GFM accepts and what is emitted. Padding the delimiter row to match column width makes the raw Markdown prettier but adds bytes with no rendering effect — and it desynchronises the moment anyone edits a cell, so the compact form is the maintainable one.
For tabular numbers, right alignment is the one that actually changes readability: it lines up the digits so magnitude is visible down the column. Left is the sensible default for text keys and identifiers, and centre is best kept for short status or flag columns.
Pipes, newlines and ragged rows
The pipe character is structural in a Markdown table and ordinary in a data value, so every `|` inside a cell is escaped as `\|` before output. Without that escape, a single pipe in a URL, a regex or a log line splits one cell into two and shifts every subsequent value in that row out from under its header — the most common way a generated table silently reports wrong data.
A newline inside a quoted field is collapsed to a space for the same structural reason: a GFM table row is one line, and a literal line break inside a cell terminates the row. If preserving the break matters more than staying in a table, convert that column's content separately.
Ragged rows do not abort the conversion. The column count is taken from the widest row and short rows are padded with empty cells, so a copied range with a trailing blank column still produces a well-formed table. PapaParse's recoverable issues surface as a warning naming the first few, which is usually enough to spot a stray tab in the source.
Large extracts, parsed locally
Tab-delimited files are often the biggest thing a person pastes into a converter — a query export or a log extract can run to tens of thousands of rows. Parsing runs in a Web Worker rather than on the main thread, so a large paste does not freeze the tab while the table is built, and the editor stays responsive throughout.
None of it is uploaded. The file is read locally with the FileReader API, or the pasted text is used directly, and PapaParse runs in your browser — so a customer list, an internal revenue extract or an unreleased benchmark never leaves the machine. There is no account and no server-side history of what you converted, which you can verify in the Network panel of DevTools while converting.
The practical ceiling is browser memory rather than a server limit. Very large inputs are better filtered before conversion anyway: a hundred-thousand-row Markdown table is valid GFM but unreadable in every renderer that will display it.
Known limitations of TSV to Markdown conversion
Being explicit about what a converter cannot do saves you a wasted upload. These are the boundaries of what is recoverable from TSV programmatically:
- A GFM table needs a header row. With the header toggle off, generated `Column N` labels are emitted rather than no header at all.
- Newlines inside quoted fields collapse to spaces, because a table row must occupy a single line.
- Merged cells have no Markdown equivalent. A copied spreadsheet range with merges arrives already flattened by the clipboard, with the value in the first cell.
- Formulas are not evaluated — the clipboard carries the computed values, so what you paste is what you get.
- Cell formatting (colour, font, number formats, currency symbols) is not part of TSV and is not recoverable.
- Auto-detection can pick the wrong delimiter on very narrow input, such as a single row containing both tabs and commas. Set the delimiter explicitly for that case.
Who Converts TSV to Markdown?
Data Analysts
Pasting a Sheets or Excel selection into a pull request, a ticket or a wiki page as a table that renders without an image.
Developers
Turning a tab-delimited query result or a `\t`-separated log extract into a GFM table for a README or an incident write-up.
Technical Writers
Maintaining parameter and compatibility tables in Markdown, with alignment set per column rather than by hand-editing dashes.
Researchers
Publishing tab-delimited experiment output as a readable table in documentation or a static-site build.
How You Can Verify the Privacy Claim
Zero server upload
Conversion runs inside your browser tab. Open DevTools, switch to the Network panel, and convert a file: for every format except URL to Markdown you will see no request carrying your document — because there is no endpoint to send it to.
Off the main thread
Heavy parsing is dispatched to a Web Worker, so a 500-page PDF or a large spreadsheet never freezes the interface. Everything is plain JavaScript — no native plugin, no WebAssembly toolchain, nothing to install.
Nothing to sign up for
No login, no quota, no paywall, and no tracking tied to your files. Analytics are cookieless and aggregate only. Read the privacy policy for the full data-flow breakdown, including the one proxied exception.
The parsers doing the work
No proprietary black box: each format is handled by a widely audited open-source library, running client-side at the version pinned in our lockfile.
TSV to Markdown — FAQ
Can I paste directly from Excel or Google Sheets?
Yes, and it is the fastest route. Both put tab-delimited text on the clipboard when you copy a range, so pasting into the editor gives the parser exactly what it expects with no file and no export. The same is true of LibreOffice Calc and Numbers.
How do I control column alignment in the output?
Alignment is set per column and written into the delimiter row: :--- for left, :---: for centre, ---: for right, and a bare --- to leave it to the renderer. Right alignment is the one that genuinely improves numeric columns, because it lines the digits up so magnitude is readable down the column.
What if a cell contains a pipe or a line break?
Pipes are escaped as \| so they cannot split the row, and a newline inside a quoted field is collapsed to a space because a GFM table row must occupy a single line. If keeping the line break matters more than staying in a table, convert that column's text separately.
Does my data need a header row?
GFM tables require one, so if your data is headerless turn the header toggle off and the converter emits Column 1, Column 2, … as labels rather than producing an invalid table. The toggle defaults to treating row one as the header, which is what a copied spreadsheet range almost always contains.
Is there a row limit, and is my data uploaded?
There is no server limit because there is no server: PapaParse runs in a Web Worker in your browser, so an internal revenue extract or a customer list never leaves the machine. The practical ceiling is browser memory. Very large inputs are worth filtering first anyway — a hundred-thousand-row Markdown table is valid GFM but unreadable in every renderer that will display it.