Duplicate Line Remover
Remove duplicate lines, or find out what repeated
Duplicate Line Remover tool
0 lines in · 0 out · 0 removed
What to keep
Written as the count, a tab, then the line — two columns if you paste it into a spreadsheet.
Strips leading and trailing whitespace from the text that is written out, not just the comparison.
What counts as the same
Off, Apple and apple are one value.
A stray trailing space stops hiding a match.
"New York" and "New York" become one value.
O’Brien matches OBrien, AT&T matches ATT.
café matches cafe. Wrong for languages where the accent changes the word.
Matches characters that look identical but are stored differently — a precomposed é and an e with a combining accent.
How the list is separated
Line mode reads all three line endings and writes back the one your text arrived with, so a file saved on Windows stays a Windows file.
Ready-made settings (8)
Duplicate Line Remover: key facts
- What it does
- Remove duplicate lines, or find out what repeated
- Category
- Text Tools
- Cost
- Free, with no account, sign-up, or install.
- Your data
- Runs entirely in your browser — the files and text you enter are never uploaded to a server.
- Last reviewed
- . Report an incorrect result.
About the Duplicate Line Remover
Lists pulled from logs, exports, or a copy-pasted spreadsheet column are full of repeats, and deleting them by hand is slow and easy to get wrong. This tool cleans the list and — just as usefully — tells you what was repeated and how often, so the removal is something you can check rather than something you have to trust.
Which copy survives is your choice. Keeping the first of each is the familiar behaviour and the right one for anything chronological. Keeping the last is what you want when a corrected row was appended below the one it replaces, where deduplicating from the top would throw the correction away. Two more options turn the tool around entirely: show only the entries that appear exactly once, or show only the ones that repeat, each with its count. A fifth collapses just the runs of identical lines sitting next to each other, the way the uniq command does, leaving separated repeats alone.
The harder question is what counts as the same. Exact comparison is the only unambiguous rule, but it is rarely what messy data needs, so the comparison is adjustable in six ways: fold case, ignore surrounding whitespace, ignore doubled spaces inside the line, drop punctuation and symbols, drop accents, and normalise Unicode so characters that look identical on screen but are stored differently still match. Every one of those changes only the comparison — the line that survives is written out exactly as you pasted it.
You can also narrow what is compared rather than loosening how. Compare a single column of a CSV and the whole row is still kept, so a contact list deduplicates on the email address while the name and phone number ride along. Compare only the part matching a regular expression and a log file deduplicates on the message with the timestamp ignored. Lists separated by commas, semicolons, tabs, or anything else work as well as one item per line, and the result can come back separated however suits the next step.
Comparing part of a line instead of all of it
A CSV row is rarely duplicated in full. The same customer appears twice with a different phone number, or the same URL twice with a different tracking parameter — whole-line comparison sees two distinct rows and keeps both. Comparing a single column solves it: choose the separator and the column number, and the tool groups rows by that field alone while writing out the entire row it belongs to.
The pattern mode generalises the same idea to anything a regular expression can pick out. Give it a pattern with a capture group and the group becomes the comparison key; give it one without and the whole match is used. For log lines, a pattern that skips the first field compares the messages and ignores the timestamps, so a hundred repetitions of the same error collapse to one.
Both modes have to answer what happens to a line that has no key at all — a row with fewer columns than you asked for, or a line the pattern does not match. Treating those as sharing an empty key would silently merge unrelated lines, so they are kept exactly as they are, excluded from the grouping, and counted in a note beneath the controls. Note also that the column split is a plain separator split, not a full CSV parse: a quoted field containing the separator will be split at it.
How to use it
- Paste your list into the top box, or drop a .txt or .csv file onto it.
- Pick what to keep: the first copy of each, the last, only the lines that appear once, only the ones that repeat, or just neighbouring runs.
- Adjust what counts as the same — ignore case, spacing, punctuation or accents, or compare only one column or one pattern.
- Read the result as it updates, and check the table of repeated values underneath to see exactly what was found and how often.
- Copy or download the cleaned list, or press "Use as input" to run a second pass over it.
Choosing which copy survives
Keeping the first occurrence preserves the original order and the earliest entry, which is correct for a log, an append-only export, or any list where position carries meaning. It is the default for that reason.
It is the wrong default when later entries carry corrections. If someone appended an updated address below the stale one, taking the first copy silently keeps the version that is out of date — the failure is invisible, because the output looks perfectly clean. Switching to the last occurrence keeps each value where its final copy appeared, which is what an append-corrections workflow actually means.
The two filtering modes answer different questions again. "Only lines that appear once" strips out every copy of anything repeated, which is how you find the entries that exist in one source but not the other after concatenating two lists. "Only the repeated lines" does the opposite and gives you the overlap. Neither is a cleanup; both are queries, and the counts beside them are the answer.
- A three-line list where the same value appears twice collapses to two lines, positioned where the first copy was.
- Switching to last-wins moves that surviving line down to where the final copy appeared.
- Concatenate two exports, filter to the repeated lines, and you have the entries common to both.
Why use this version
- Everything runs in your browser. A list of customer emails or internal records never leaves your machine, and nothing is uploaded.
- The result updates as you type and as you change options, so what you are reading always describes the list currently in the box.
- A table of every repeated value with its count turns the removal into something you can verify instead of a number you have to believe.
- Six comparison switches plus column and pattern modes cover the real messiness — mixed case, stray and doubled spaces, punctuation, accents, and rows that differ only in a field you do not care about.
- Kept lines are written out exactly as you pasted them, and line endings survive the round trip, so a file saved on Windows comes back as a Windows file.
- Load a file, undo, chain a second pass, download the result, and keep your list and settings between visits if you want them.
Loosening the comparison without losing the data
Every definition of duplicate looser than "byte-for-byte identical" is a judgement call, and the useful thing a tool can do is make that judgement explicit rather than bury it. Two email addresses differing only in capitals are almost certainly one inbox — the domain is case-insensitive by specification, and in practice providers treat the local part that way too. Two names differing only by an apostrophe are usually one person. Two words differing by an accent may or may not be the same word, depending entirely on the language.
So each of those is a separate switch you turn on knowingly, and none of them rewrite your data. The comparison runs against a normalised copy of the line; the line that reaches the output is untouched. The one exception is the trim option in the result panel, which does edit the kept text, and is labelled where it sits.
Unicode normalisation deserves a note because it is on by default and invisible when it works. The same accented character can be stored either as one code point or as a plain letter followed by a combining mark. The two render identically and compare as different strings, which is why a list assembled from more than one source sometimes appears to contain duplicates the tool refuses to remove. Normalising to a canonical form before comparing fixes that without discarding the accent.
Frequently Asked Questions
Does it keep the original order of my list?
Yes. Nothing is sorted. Lines are emitted in the order they occur, so keeping the first copy of each leaves the surviving lines exactly where their first appearance was, and keeping the last leaves them where the final copy was. If you want the result alphabetised, run it through the Text Sorter afterwards.
How do I keep the newest entry instead of the oldest?
Choose "Keep the last of each" under What to keep. Each value then survives at the position of its final copy rather than its first, which is what you want when a corrected row was appended below the entry it replaces.
Can I see which lines were duplicated, not just how many?
Yes. Below the result, a table lists every value that appeared more than once alongside its count, most frequent first, and copies out as two tab-separated columns. If you would rather have the counts inside the result itself, tick "Number each result with how many times it occurred".
What happens to blank lines?
You choose one of three behaviours. "Remove them" deletes every blank line, which compacts a sparse list; "Keep them all" leaves the spacing untouched and exempts blanks from the comparison; "Treat as normal lines" makes them ordinary values, so a run of four blanks collapses to one. Removals are reported in a note so a deleted blank line is never a surprise.
Why did it not remove lines that look identical to me?
Something invisible differs — a trailing space, a doubled space in the middle, a curly apostrophe against a straight one, an accent stored as a separate combining mark, or a difference in capitals. Loosen the comparison under "What counts as the same" until the table shows the value as repeated. If the difference is in a field you do not care about, compare only the column or the pattern that matters instead.
Can it deduplicate a comma-separated list rather than one item per line?
Yes. Under "How the list is separated", set the input separator to commas, semicolons, tabs, spaces, or any custom string. The output separator is chosen independently, so you can feed in a comma list and get back one item per line, or the reverse.
Is my list uploaded anywhere?
No. The deduplication runs entirely in your browser and nothing is sent over the network. If you leave "Keep my list in this browser" ticked, the text and your settings are saved to this device's local storage so they survive a reload — untick it to clear that, and lists over 200,000 characters are never stored at all.