Add line numbers to any text
Paste a list, get it back with a row number prepended to every line. Default separator is tab so it pastes into Excel column A. Configurable start number and zero / space padding for tidy column alignment.
Or press Ctrl+Enter
When to use this tool
guideReviewing a long log or feedback list? Number rows first so you can say "look at row 47" instead of describing the line content.
Tab-separated output drops straight into a spreadsheet — numbers in column A, original text in column B. No formulas, no drag-fill.
LLMs follow "for each numbered item…" instructions more reliably when items are pre-numbered in the prompt.
The last line's number is the total. Faster than counting manually, no `wc -l` required.
How it works
three steps-
01
Paste text or drop a .txt file
Live preview up to 100K lines on desktop / 5K on mobile. Bigger inputs auto-switch to download mode — numbering moves into a Web Worker, the page stays interactive, and the output drops straight as .txt.
-
02
Pick separator, start, padding
Separator: tab (default, splits into Excel columns), space, ": " or ". ". Start at any integer. Padding: none, zero ("007"), or spaces (" 7") so all numbers line up.
-
03
Hit Run
Numbers are prepended deterministically. With the empty toggle off (default) every line gets a number, blanks included — `cat -n` behaviour. Toggle on follows `cat -b`: skip blanks but keep numbering consecutive on non-blank rows.
Under the hood
engine notes- Algorithm
- Single linear pass · O(n)
- Pad width
- String(start + count − 1).length
- Throughput
- 100K lines numbered in ≈90 ms on a 2024 M3 MacBook Air
For each line, format the cursor as a string, optionally pad to max-number width, prepend the separator. Cursor only increments on lines that actually get numbered.
Width computed once based on the largest number that will be produced. A 1000-line file always pads to 4 digits, never partial. With empty=on, count is non-blank lines.
Same engine as the other tools. Web Worker takes over for files ≥ 2 MB or ≥ 100K lines so the main thread stays interactive.
Privacy & limits
what stays whereEverything runs in your browser. Numbers are computed locally; the row count and the input itself never leave the tab, not even for an analytics ping. 80 MB hard cap per run.
Frequently asked
answeredWhy is tab the default separator?
Tab-separated text pastes into Excel, Google Sheets and Numbers as two columns automatically. Single space, colon-space (": ") and dot-space (". ") are also one click away for plain-text use.
Can I start numbering from 0 or 100?
Yes — type any integer in the Start at field. Negative values and 0 are accepted. Padding width auto-adjusts to the largest absolute number that will be produced.
What happens to blank lines?
Two modes, controlled by the "Remove blank lines" toggle. Off (default) numbers every line including blanks — `cat -n` behaviour. On numbers only non-blank lines but keeps the count consecutive ("1, 2, 3" on non-blank rows even if there were blanks in between) — `cat -b` behaviour.
How is this different from Excel's ROW() formula?
ROW() requires data to already be in cells, gives numbers in a separate column, and breaks when you delete rows. This tool gives plain-text output you can paste anywhere — email, chat, PDF, Markdown — with no formula dependency.
Is my text uploaded?
No. The numbering runs entirely in your browser. The input and the row count both stay local — the analytics layer never sees them. Disconnect from the network after loading and the tool still works.