Logo

MonoCalc

/

Tabs to Spaces Converter

Text
Paste code or text, or drop a plain-text file onto the box. Up to 20,00,000 characters.

Samples:

0 characters0 lines0 tabs0 spaces0 B

Replaces tab characters with spaces. In tab-stop mode each tab advances to the next multiple of the tab size, which is how terminals and editors actually render it.

Columns per tab stop.
Editors and terminals agree on 2, 4 and 8; other widths render differently elsewhere.
Only the indentation at the start of each line is converted. Tabs used as data separators further along a line survive untouched.
A tab advances to the next column that is a multiple of the tab size, so it may expand to anywhere between one space and a full tab size.
Normalise terminators along with the whitespace, or keep whatever the input used.
Only applies in align-columns mode.

Language presets:

What these settings do

ab→cd
ab··cd

"ab" fills columns 0–1, so the tab expands to 2 spaces to reach column 4 — not 4.

Nothing converted yet.

Paste code or text to convert

The converted text, the indentation report and the per-line breakdown all appear here.

About This Tool

Tabs to Spaces Converter – Normalise Indentation Without Breaking It

Mixed indentation is one of those problems that stays invisible right up to the moment something fails. Python raises TabError: inconsistent use of tabs and spaces, a YAML parser rejects a file outright because the spec forbids tabs in indentation, a Git diff reports every line as changed, and the same snippet lines up differently in three different editors. This tabs to spaces converter rewrites the whitespace in one consistent direction and shows you exactly what it changed.

Why one tab is not four spaces

A tab does not have a width. It is a movement: it pushes the cursor to the next tab stop, which is the next column that is a multiple of the tab size. At a tab size of four, the string ab\tcd renders as ab  cd — the tab is worth two spaces, because ab already occupies columns 0 and 1 and the cursor only has to travel to column 4. A plain find-and-replace of \t with four spaces gets this wrong on every line where the tab is not already sitting on a stop, which is why converted files so often come out misaligned.

The default tab stops (elastic) mode reproduces the real behaviour using nextStop = floor(col / N) × N + N. If you actually want the naive substitution — and sometimes you do, for example when a downstream tool expects a fixed indent unit — switch to fixed count and every tab becomes exactly N spaces wherever it sits.

Choosing a direction and a scope

Tabs → Spaces is what you want for Python, YAML and any codebase that enforces spaces. Spaces → Tabs is the inverse: the leading whitespace of each line is measured in columns and rewritten as whole tabs plus any remainder, which is what Go, Makefiles and tab-separated data need. On the entire-line scope the reverse pass only collapses runs of two or more spaces that actually reach a tab stop, so word gaps and intra-line alignment survive — the same rule GNU unexpand -a follows.

The scope setting is the safety catch. With leading whitespace only, just the indentation is touched, so a tab used as a data separator halfway along a line is left exactly where it was. Widen the scope to entire line only when you really do want every tab converted.

Never convert a Makefile's tabs to spaces
make requires a real tab at the start of every recipe line and fails with a missing separator error if it finds spaces instead. The tool detects the Makefile shape — a target line followed by a tab-indented line — and warns you before you convert. YAML is the mirror image: tabs are illegal in its indentation, so converting them to spaces is mandatory rather than optional.

Finding the lines that will bite

Analyse onlymode changes nothing and just reports. It counts tab-indented, space-indented and mixed lines, names the dominant style, lists the exact line numbers where tabs and spaces are mixed inside the same indent, and infers a likely tab size from the greatest common divisor of the space-indent widths. The per-line table shows each line’s indent before and after in visible glyphs, its width in columns, and whether the pass changed it.

Alignment, cleanup and export

Align columns mode reads tabs as separators instead of indentation and pads each column to the widest cell plus a gutter, turning tab-separated data into a fixed-width plain-text table. Alongside the conversion you can trim trailing whitespace, enforce a final newline, and normalise line endings between LF, CRLF and CR. Turn on show whitespace to render tabs as and spaces as · in the preview panes — copying and downloading always use the raw text. Results export as TXT, the per-line report exports as CSV, and everything runs in your browser, so proprietary source never leaves your machine.

Frequently Asked Questions

Is the Tabs to Spaces Converter free?

Yes, Tabs to Spaces Converter is totally free :)

Can I use the Tabs to Spaces Converter offline?

Yes, you can install the webapp as PWA.

Is it safe to use Tabs to Spaces Converter?

Yes, any data related to Tabs to Spaces Converter only stored in your browser (if storage required). You can simply clear browser cache to clear all the stored data. We do not store any data on server.

How does the Tabs to Spaces Converter work?

Each line is walked one character at a time while the tool keeps track of the visual column. When it meets a tab it works out how many spaces are needed to reach the next tab stop — the next column that is a multiple of your tab size — and writes exactly that many. The reverse direction measures the width of a line's leading whitespace and rewrites it as whole tabs plus any leftover spaces. Every count in the results panel is then derived by comparing each line before and after, so the statistics can never disagree with the text you actually get.

Why does one tab not always become the same number of spaces?

Because a tab is a movement, not a width. It advances the cursor to the next tab stop, so at a tab size of 4 a tab in column 2 is worth 2 spaces while a tab in column 4 is worth 4. That is what the default "tab stops (elastic)" mode reproduces, and it is why text converted with a plain find-and-replace often comes out misaligned. If you genuinely want one tab to become a fixed number of spaces, switch the expansion mode to "fixed count".

What does "leading whitespace only" protect?

It restricts the conversion to the indentation at the start of each line, so tabs used further along a line survive untouched. That matters for tab-separated data, for aligned trailing comments, and for tabs inside string literals. Switch the scope to "entire line" only when you want every tab on the line converted.

Will this break my Makefile?

It would, which is why the tool warns you first. make requires a real tab at the start of every recipe line and fails with a "missing separator" error if it finds spaces instead. When the input looks like a Makefile — a target line followed by a tab-indented line — a warning appears before you convert. Use the Spaces → Tabs direction for Makefiles rather than the other way round.

How accurate is the mixed-indentation report?

The per-line classification is exact: a line is counted as mixed when its leading whitespace contains both a tab and a space, and those are the lines that raise TabError in Python or produce whole-file diffs. The inferred tab size is a genuine guess — it is the greatest common divisor of the space-indent widths, falling back to the most common width when the file is not consistently indented — so treat it as a suggestion, not a fact.

Is my code uploaded anywhere?

No. The conversion runs entirely in your browser and nothing is transmitted, so it is safe for proprietary source. Your last input and settings are kept in your own browser's local storage, and the share link carries your settings plus the text only while the text is small enough to fit in a URL.