LineBreaks

Remove line breaks — and see what was really in there.

Paste text that a PDF, an email client or a word processor broke into short lines. Pick a mode, take the result. The part that makes this different is the Show invisible characters toggle: it draws a labelled badge wherever a CRLF, a lone carriage return, a U+2028, a no-break space or a tab is sitting, so you can see why a break you already "removed" is still there.

Blank lines survive as paragraph breaks; the wrapping inside each paragraph is undone.

8 lines · 312 characters · 54 wordsLF ×7NBSP ×1
3 lines · 310 characters-2 characters

Eight lines — seven of text, one blank as a paragraph break — with one no-break space and one word broken across a line by a hyphen.

Hyphen rejoining can be wrong. Guarded mode keeps the hyphen when the fragment before it is a known compound head, which saves well-known but also leaves inter-national unjoined. The measured score for both settings is on the PDF page.

The six modes, and which one you want

People arrive here wanting one of six different things, and picking the wrong one is an easy way to make a mess you cannot undo. They differ in what they treat as structure worth keeping.

  • Remove all line breaks — every break goes and the document becomes one continuous paragraph. Right for a quotation, a search box, or a field that must be one line. Wrong for anything with more than one paragraph, because you will not get them back.
  • Keep paragraphs, unwrap lines — the mode above with one exception: a blank line means "new paragraph" and survives. This is what almost everyone actually wants after copying out of a PDF, and it is what this page opens in.
  • Remove blank lines — the opposite job. Line structure is untouched; the empty lines between the lines go. Useful for lists that arrived double-spaced.
  • Join lines with a separator — turns a column of lines into a delimited list. The separator is yours, and each line can be wrapped in SQL or JSON quoting on the way out.
  • Tidy extra spaces — leaves every break where it is and normalises the horizontal whitespace instead: runs of spaces, tabs, and the no-break spaces a word processor scatters through justified text.
  • Convert line endings — changes nothing but the bytes between lines. Converts a file to LF, CRLF or CR without touching a character of content.

Switching mode resets the options to that mode's defaults, deliberately. Carrying a "collapse the spaces" setting into a mode whose entire purpose is not to alter the lines would be a good way to lose data quietly.

What each mode does to each invisible character

This is the table that took the longest to get right, and it is not written by hand. Every cell below was produced by running the tool on the input in the second column while this page was being built, which means the table cannot describe behaviour the tool does not have. The probe is deliberately minimal: the letter A, the character, the letter B.

Generated at build time by calling the tool with each mode's shipped defaults. ␊ is LF, ␍ is CR, → is a tab, · is a space, and bracketed names mark characters with no picture of their own.
Character Input Remove all line breaksKeep paragraphs, unwrap linesRemove blank linesJoin lines with a separatorTidy extra spacesConvert line endings
LF
U+000A
A␊B A·B A·B A␊B unchanged A,·B A␊B unchanged A␊B unchanged
CRLF
U+000D U+000A
A␍␊B A·B A·B A␍␊B unchanged A,·B A␍␊B unchanged A␊B
CR
U+000D
A␍B A·B A·B A␍B unchanged A,·B A␍B unchanged A␊B
NEL
U+0085
A⟦NEL⟧B A·B A·B A⟦NEL⟧B unchanged A,·B A⟦NEL⟧B unchanged A␊B
LS
U+2028
A⟦LS⟧B A·B A·B A⟦LS⟧B unchanged A,·B A⟦LS⟧B unchanged A␊B
PS
U+2029
A⟦PS⟧B A·B A·B A⟦PS⟧B unchanged A,·B A⟦PS⟧B unchanged A␊B
NBSP
U+00A0
A⟦NBSP⟧B A⟦NBSP⟧B unchanged A⟦NBSP⟧B unchanged A⟦NBSP⟧B unchanged A⟦NBSP⟧B unchanged A·B A⟦NBSP⟧B unchanged
TAB
U+0009
A→B A→B unchanged A→B unchanged A→B unchanged A→B unchanged A·B A→B unchanged

Three things fall straight out of it. Of the 8 characters, none is left alone by all six modes, and none is rewritten by all six — so "does this tool remove X" has no answer that is not also a question about which mode. 5 of them (CRLF, CR, NEL, LS, PS) are altered by 4 of the 6 modes, which is as high as the table goes. And the two that are not line breaks at all — NBSP and TAB — are touched by exactly one mode, Tidy extra spaces. That is the design, not an oversight: a no-break space is a space, and a mode that promised to leave your lines alone has no business rewriting the characters inside them.

Where each of these characters comes from

Knowing which byte you have is most of the diagnosis, because each one implicates a different application.

Names are quoted from Unicode Consortium files opened directly — see the sourcing note. Control characters have no Unicode name; the names below are the formal aliases Unicode publishes for them, and the column says which is which.
CharacterNameKindWhere it comes from
LF
U+000A
LINE FEED
control alias
Line break The line ending of Unix, macOS, the web, JSON, and every string literal written "like\nthis". Text copied out of a code editor or a terminal is almost always LF.
CRLF
U+000D U+000A
CARRIAGE RETURN + LINE FEED
sequence
Line break The Windows line ending, and the one the internet protocols specify: HTTP/1.1 header lines and CSV records under RFC 4180 both end with CRLF, and both specifications were read for this site. Anything saved by a Windows editor, or produced by PowerShell or a .bat file, arrives this way.
CR
U+000D
CARRIAGE RETURN
control alias
Line break On its own, the line ending of the classic Mac OS (through Mac OS 9) and of some lab and point-of-sale equipment. Far more often it is the leftover half of a CRLF that a regex removed the LF from — damage a browser hides completely, and that terminals, editors and string comparisons do not.
NEL
U+0085
NEXT LINE
control alias
Line break A C1 control from ISO 6429, and the line ending of IBM mainframe EBCDIC text. It shows up in data exported from mainframe systems and in files transcoded from EBCDIC without newline mapping. Almost nothing on a PC displays it as a break, so the text looks like one long line in some programs and two lines in others.
LS
U+2028
LINE SEPARATOR
name
Line break Unicode’s own unambiguous "break the line here, same paragraph" character. Page-layout applications emit it for a soft line break, and it survives copy-paste out of them. Browsers render it as a line break; many plain-text editors do not.
PS
U+2029
PARAGRAPH SEPARATOR
name
Line break The paragraph-level partner of LINE SEPARATOR. Text pasted out of layout and DTP software can carry it in place of a blank line, which is why a "remove blank lines" pass sometimes has nothing to remove even though the text plainly has paragraphs.
NBSP
U+00A0
NO-BREAK SPACE
name
Looks like a space Not a line break at all — a space that forbids one. Word processors insert it between a number and its unit, HTML authors write it as  , and PDF text extraction produces runs of it where the original was justified. It looks exactly like a space and is matched by almost no "collapse the spaces" regex.
TAB
U+0009
CHARACTER TABULATION
control alias
Looks like a space The column separator of TSV data and the indentation of most source code. Copying a table out of a spreadsheet or a PDF gives you tabs between the cells, and turning them into spaces destroys the column structure you were trying to keep.

Nine one-line fixes that do not work

Everything on this page exists because the obvious solution — one regex, ten seconds — is wrong in ways that do not announce themselves. Below are 9 patterns taken from the shape of answers that circulate on forums, each run against an input that exposes what it misses. The output column is not an illustration. It is the string the pattern in the first column returned when this page was built.

Sorted by how they fail: 3 leave an orphan carriage return behind, 5 change nothing whatsoever, and 1 destroys structure it should have kept. The classification is computed from each pattern's own output, not assigned by an author.

Every input and output rendered twice: once with visible marks, once as the UTF-8 bytes.
PatternInOutHow it failsWhat works
text.replace(/\n/g, ' ')
The answer at the top of every "remove line breaks in JavaScript" thread.
first␍␊second
66 69 72 73 74 0D 0A 73 65 63 6F 6E 64
first␍·second
66 69 72 73 74 0D 20 73 65 63 6F 6E 64
orphan CR. The file came from Windows, so each break was CR + LF. Only the LF matched. Every line now ends with a carriage return that nothing displays — the text looks joined in a browser and still breaks in a terminal, an editor, or a database column. text.replace(/\r\n|[\r\n]/g, ' ')
first·second
text.replace(/\n/g, '')
The same mistake with an empty replacement, which hides it better.
first␍␊second
66 69 72 73 74 0D 0A 73 65 63 6F 6E 64
first␍second
66 69 72 73 74 0D 73 65 63 6F 6E 64
orphan CR. Now the two words are welded together *and* an orphan CR sits between them. Byte count went down, so the operation looks like it worked. Paste this into a CSV and the row silently splits in some readers. text.replace(/\r\n|[\r\n]/g, '')
firstsecond
text.split('\n')
Splitting a Windows file into lines.
alpha␍␊beta␍␊gamma
61 6C 70 68 61 0D 0A 62 65 74 61 0D 0A 67 61 6D 6D 61
[alpha␍][beta␍][gamma]
5B 61 6C 70 68 61 0D 5D 5B 62 65 74 61 0D 5D 5B 67 61 6D 6D 61 5D
orphan CR. Shown here with brackets around each piece. Every line except the last carries a trailing CR inside the brackets, so "alpha" never equals "alpha", lookups miss, and trimmed comparisons pass while untrimmed ones fail. text.split(/\r\n|[\r\n]/)
[alpha][beta][gamma]
text.replace(/\s+/g, ' ')
The "just normalise all whitespace" one-liner.
one⟦PS⟧two
6F 6E 65 E2 80 A9 74 77 6F
one·two
6F 6E 65 20 74 77 6F
structure destroyed. JavaScript's \s includes U+2029 PARAGRAPH SEPARATOR, so a paragraph boundary is quietly demoted to a space. This pattern is too greedy, not too narrow: it flattens structure you meant to keep, and it does the same to tabs inside TSV data. text.replace(/[^\S\r\n\u0085\u2028\u2029]{2,}/g, ' ')
one⟦PS⟧two
text.replace(/\r\n|[\r\n]/g, ' ')
A correct CRLF-aware pattern, meeting text pasted from a layout program.
one⟦LS⟧two
6F 6E 65 E2 80 A8 74 77 6F
one⟦LS⟧two
6F 6E 65 E2 80 A8 74 77 6F
no change at all. Nothing matched, and nothing changed. The break is U+2028 LINE SEPARATOR, which browsers render as a line break and this pattern does not mention. The user sees a line break, presses the button again, and concludes the tool is broken. text.replace(/\r\n|[\r\n\u0085\u2028\u2029]/g, ' ')
one·two
text.replace(/\s+/g, ' ')
The greedy whitespace pattern, meeting mainframe-exported text.
one⟦NEL⟧two
6F 6E 65 C2 85 74 77 6F
one⟦NEL⟧two
6F 6E 65 C2 85 74 77 6F
no change at all. The opposite failure to the row above: \s does not include U+0085 NEXT LINE. A pattern broad enough to eat paragraph separators is still too narrow for EBCDIC exports, which is a good reason to name the characters you mean instead of reaching for \s. text.replace(/[\u0085\u2028\u2029]|\r\n|[\r\n]/g, ' ')
one·two
text.replace(/ +/g, ' ')
Collapsing runs of spaces after a PDF paste.
total:⟦NBSP⟧⟦NBSP⟧⟦NBSP⟧42
74 6F 74 61 6C 3A C2 A0 C2 A0 C2 A0 34 32
total:⟦NBSP⟧⟦NBSP⟧⟦NBSP⟧42
74 6F 74 61 6C 3A C2 A0 C2 A0 C2 A0 34 32
no change at all. Three no-break spaces are not spaces. The literal " " in the pattern is U+0020 and matches none of them, so the gap stays exactly as wide as it was and the text still will not wrap where you want it to. text.replace(/[\u00A0\u202F]/g, ' ').replace(/ {2,}/g, ' ')
total:·42
text.replace(/\n\n/g, '\n')
Removing blank lines from a Windows file.
alpha␍␊␍␊beta
61 6C 70 68 61 0D 0A 0D 0A 62 65 74 61
alpha␍␊␍␊beta
61 6C 70 68 61 0D 0A 0D 0A 62 65 74 61
no change at all. The two LFs are not adjacent — a CR sits between them — so the pattern never matches and the blank line stays. This one is easy to miss because it fails silently on exactly the files it was written for. text.replace(/(\r\n|[\r\n]){2,}/g, '$1')
alpha␍␊beta
text.replace(/\R/g, ' ')
A pattern copied from a PCRE or Perl answer, where \R means "any line break".
one␊two
6F 6E 65 0A 74 77 6F
one␊two
6F 6E 65 0A 74 77 6F
no change at all. JavaScript has no \R. In a non-unicode regex the escape simply degrades to the letter R, so the pattern matches a capital R and nothing else — no error, no match, no line breaks removed. Add the u flag and the same pattern throws a SyntaxError instead. text.replace(/\r\n|[\r\n\u0085\u2028\u2029]/g, ' ')
one·two

The last row deserves a note, because its pattern does not mean in JavaScript what it means where it was copied from. \R means "any line break" in PCRE and Perl, and it is copied into JavaScript constantly. JavaScript has no such escape. In an ordinary regex it degrades silently to the letter R — tested here, and /\R/ does match the string "R": true. Add the u flag and the same pattern is a SyntaxError. So the pattern either does nothing or throws, and neither outcome looks like "your line breaks were not the ones you thought".

The carriage returns left behind when you strip the newlines

Take three lines saved by a Windows editor: first, second, third. On disk that is 66 69 72 73 74 0D 0A 73 65 63 6F 6E 64 0D 0A 74 68 69 72 64 — note the 0D 0A pairs. Now run the pattern from the first row of the table above, text.replace(/\n/g, ' '). Each 0A becomes 20 and each 0D stays: … 74 0D 20 73 …. One byte swapped for another, so the file is exactly the size it was — and it still contains a carriage return per line.

In a browser that renders as first second third and looks finished. Paste it into a terminal and the cursor jumps to column zero mid-sentence. Store it in a database and WHERE name = 'first' misses every row. Diff it against a clean copy and every line shows as changed with no visible difference. Four symptoms, one cause, and nothing on screen that connects them — which is why the defence has to be reading the bytes, and what the reveal toggle is for.

How to use the reveal view

Both panels switch at once, and a line-ending badge still breaks the line, so the shape of the text survives while the cause of every break is named. Runs of ordinary spaces at the end of a line get a faint dot each — the thing that makes a diff noisy and a trim() comparison pass while an untrimmed one fails.

The counters under the input do the same job in summary form: a badge appears for each character class actually present, with its count. A document whose badge strip shows CRLF alongside NBSP has already told you two things about where it came from before you have read a word of it — it was saved on Windows, and something in its history justified the text. The sample loaded above reports its own counts the same way, and they are the real ones for that text rather than an illustration.

What this tool will not do

  • It cannot know which hyphen you meant. The rejoin option is a heuristic with a published score; no dictionary is consulted. Details and the measurement on the PDF page.
  • It does not reflow to a column width. Removing breaks and inserting new ones at 72 characters is a different job with different rules for hyphens and quotes.
  • It does not repair encoding damage. If your text arrived as ’ where an apostrophe belongs, that happened before the line breaks did, and a break remover cannot undo it.
  • It does not preserve formatting. Everything here is plain text. Bold, italics and headings are gone by the time the text reaches the box.

Every job, and the page that covers it

  • Remove line breaks from PDF text — the hard-wrap problem in its worst form, with a measured account of what the hyphen-rejoin option gets right and wrong.
  • Remove line breaks in Excel and CSV — why a CSV has two kinds of line break that look identical, and how to strip one without destroying the other.
  • Remove line breaks in Word documents — soft breaks, paragraph separators and the no-break spaces a word processor leaves in your clipboard.
  • Remove blank lines — eleven candidate lines and three definitions of "blank" that disagree about nine of them.
  • Join lines with a separator — turning a column of lines into a comma list, a SQL IN clause or a JSON array.
  • CRLF vs LF — where the two-character line ending came from, and what git actually does to your files under each core.autocrlf setting.
  • Convert line endings — the byte-level conversion table for LF, CRLF and CR, with the round-trip check.
  • Remove extra spaces — all twenty invisible horizontal characters, and the one that an ordinary space-collapsing regex can see.

What people ask after the first paste

I removed the line breaks but the text still breaks. What is going on?

Something in the text is a line break that your tool did not recognise. The three usual culprits are U+2028 LINE SEPARATOR and U+2029 PARAGRAPH SEPARATOR — which browsers render as breaks and most patterns never mention — and U+0085 NEXT LINE, which is not even matched by JavaScript's \s. Switch on Show invisible characters above and the badge will tell you which one you have. All three are handled by every mode here.

Why does my text look joined here but broken when I paste it into Word?

Almost always a lone carriage return. A file written on Windows ends each line with two characters, CR + LF; a pattern that only removes \n leaves the CR behind. Browsers ignore a bare CR, so the text looks fixed, while editors and terminals still treat it as a break. The reveal view marks orphan CRs with their own badge, and the comparison table below shows exactly which modes remove them.

Will this keep my paragraphs?

Use Keep paragraphs, unwrap lines, which is the mode this page opens in. A run of blank lines is treated as a paragraph boundary and survives; the single breaks inside a paragraph are the ones that get replaced. Leading and trailing blank lines are dropped and a run of three blank lines becomes one, so the spacing comes out even.

Is anything I paste sent to a server?

No. The only thing that ever leaves this tab is a file you save yourself with the .txt button. The conversion, the counters and the badge on every invisible character are computed by JavaScript that is already in the page, against text that stays in the tab's memory until you close it. There is no account and no address to send anything to — the site is a folder of static files. If you would rather check than believe, leave the browser's network panel open while you paste a document: it stays empty.

What is a no-break space and why will it not go away?

U+00A0 NO-BREAK SPACE looks exactly like a space but forbids a line break at that point. Word processors insert it, and PDF text extraction produces runs of it. It is not U+0020, so / +/g — the pattern in every "remove extra spaces" snippet — matches none of it. Switch on Turn no-break spaces into ordinary spaces, or use the Tidy extra spaces mode, which has it on by default.

Can it rejoin words that a PDF split across two lines?

Yes, with a caveat. Set Words split by a hyphen to Guarded and informa- / tion becomes information. But nothing in the text distinguishes that from well- / known, where the hyphen belongs to the word — so the option is a heuristic, not a solution. We ran both settings over 48 declared words and published the score.

Does it handle very large files?

The whole document is held in memory and re-transformed on every keystroke, so a book-length paste will feel sluggish on a modest machine. There is no hard limit and nothing is truncated. If you are working with a multi-megabyte file, load it with the Open .txt button rather than pasting, and expect the reveal view — which builds a DOM node per invisible character — to be the slowest part.

Put this tool on your own page

The embed is the same converter with the article stripped out. It is marked noindex so it will never compete with this page in search results.

<iframe src="https://linebreaks.pages.dev/embed/" width="100%" height="620" style="border:1px solid #f0dbd0;border-radius:12px" title="LineBreaks — remove line breaks" loading="lazy"></iframe>

Where each job has its own page

  • Remove line breaks from PDF text — the hard-wrap problem in its worst form, with a measured account of what the hyphen-rejoin option gets right and wrong.
  • CRLF vs LF — where the two-character line ending came from, and what git actually does to your files under each core.autocrlf setting.
  • Remove blank lines — eleven candidate lines and three definitions of "blank" that disagree about nine of them.
  • Word Counter — the other half of the tidy-up job: word, character and reading-time counts once the text is one paragraph again.
  • Case Converter — text pasted out of a PDF often arrives SHOUTING as well as broken — this fixes the capitalisation under four style guides.