In Python, a new line is the \n character. Put it anywhere inside a string and everything after it starts on the next line when you print it:
print("Hello\nWorld")
# Hello
# World
Below I cover the /n mix-up, a Windows path that breaks by itself, joining lists, triple quotes and writing files. The screenshots are real runs on Python 3.14.7.

\n is one character in the string, but Windows text mode writes it as two bytes.What the newline character \n is in Python
Here’s what’s actually inside a string that contains \n:
message = "Hello\nWorld"
print(message)
print()
print('len("\\n") ->', len("\n"))
print('ord("\\n") ->', ord("\n"))
print("stored as ->", repr(message))
print()
print("the same character, written other ways:")
print(' chr(10) == "\\n" ->', chr(10) == "\n")
print(' "\\x0a" == "\\n" ->', "\x0a" == "\n")
print(' "\\N{LINE FEED}" == "\\n" ->', "\N{LINE FEED}" == "\n")
Output:
Hello
World
len("\n") -> 1
ord("\n") -> 10
stored as -> 'Hello\nWorld'
the same character, written other ways:
chr(10) == "\n" -> True
"\x0a" == "\n" -> True
"\N{LINE FEED}" == "\n" -> True

\n prints as a line break, but it’s stored as a single character with code 10.The backslash and the n are just how you type it. Python turns them into one character, the line feed, which is character code 10.
That’s why len("\n") is 1. When you want to see the newlines instead of their effect, print repr() of the string and they show up as \n again.
chr(10), \x0a and \N{LINE FEED} are the same character written other ways. You’ll rarely need them, but you’ll meet them in other people’s code.
Don’t confuse it with \r, the carriage return, which is code 13. Windows ends lines in files with \r\n, and that pair turns up again in the file and split sections below.
Is it \n or /n in Python?
It’s \n, with a backslash. A forward slash does nothing special, which is easy to miss:
print("Hello/nWorld") # forward slash: two ordinary characters
print("Hello\nWorld") # backslash: a real new line
print("Hello\\nWorld") # doubled backslash: a literal \n
print(r"Hello\nWorld") # raw string: also a literal \n
print()
print('len("/n") ->', len("/n"))
print('len("\\n") ->', len("\n"))
print('len(r"\\n") ->', len(r"\n"))
Output:
Hello/nWorld
Hello
World
Hello\nWorld
Hello\nWorld
len("/n") -> 2
len("\n") -> 1
len(r"\n") -> 2

/n prints as two plain characters. Only the backslash version starts a new line."Hello/nWorld" prints exactly as typed, because / is an ordinary character. No error, no warning, just the wrong output.
I see this mostly from people who type URLs and web paths all day, where the forward slash is the habit. If your line break isn’t appearing, check the slash first.
Sometimes you want the opposite: a literal backslash and n, say for a regex or a help message. Double the backslash (\\n) or use a raw string (r"\n"). Both give you two characters.
\n is one of several escape sequences; the full set of Python escape sequences covers tabs, quotes and the rest.
Why a Windows file path breaks onto a new line
This one catches people constantly. The path below looks fine, but it’s hiding two escape sequences:
path = "C:\reports\new_sales.csv"
print("what Python stored:", repr(path))
print("contains a new line? ", "\n" in path)
print("contains a carriage return?", "\r" in path)
print("split on new lines:", path.split("\n"))
print()
fixed = r"C:\reports\new_sales.csv"
print("raw string:", fixed)
print("contains a new line? ", "\n" in fixed)
print("forward slashes work too: ", "C:/reports/new_sales.csv")
Output:
what Python stored: 'C:\reports\new_sales.csv'
contains a new line? True
contains a carriage return? True
split on new lines: ['C:\reports', 'ew_sales.csv']
raw string: C:\reports\new_sales.csv
contains a new line? False
forward slashes work too: C:/reports/new_sales.csv

\r and \n in the path became real control characters. The raw string keeps the backslashes.\r in \reports became a carriage return and \n in \new_sales.csv became a new line. Python didn’t complain, because both are valid escapes.
Opening that path fails with a confusing error, or worse, it prints across two lines in a log. Put an r in front of the string, or use forward slashes, which Windows accepts too.
If you’re on a Mac or Linux, your own paths use forward slashes, so you won’t hit this there. You’ll still meet it the day you paste in a Windows path from a colleague or a config file.
Unknown escapes are at least noisy. "\d" raises SyntaxWarning: "\d" is an invalid escape sequence, and a future version will make it an error. Raw strings avoid both problems.
Add a new line to a string in Python
Strings don’t have an append method, so you build a new string instead:
line = "Order #1042 shipped"
before = id(line)
line += "\n"
print(repr(line))
print("same string object as before?", id(line) == before)
print()
name, total = "Ava", 42.5
receipt = f"Customer: {name}\nTotal: ${total:.2f}\nDate: 2026-09-29"
print(receipt)
print()
try:
"Hello".append("\n")
except AttributeError as err:
print("AttributeError:", err)
Output:
'Order #1042 shipped\n'
same string object as before? False
Customer: Ava
Total: $42.50
Date: 2026-09-29
AttributeError: 'str' object has no attribute 'append'
+= looks like it changes the string, but the id check shows you get a brand new object. Strings can’t be changed in place, so there’s no append(), and calling it raises AttributeError.
For anything with values in it, an f-string with \n between the parts reads best. It’s also how I’d build a small receipt or address block.
Gluing many pieces together is a different job. For that, see the ways to concatenate strings in Python.
Join a list of strings with newlines
When the lines are already in a list, "\n".join() is the tool:
items = ["apples", "bread", "milk"]
shopping = "\n".join(items)
print(shopping)
print(repr(shopping))
print()
numbers = [3, 14, 15]
try:
"\n".join(numbers)
except TypeError as err:
print("TypeError:", err)
print("\n".join(str(n) for n in numbers))
print()
print("an empty list gives an empty string:", repr("\n".join([])))
print("add the last newline yourself:", repr("\n".join(items) + "\n"))
Output:
apples
bread
milk
'apples\nbread\nmilk'
TypeError: sequence item 0: expected str instance, int found
3
14
15
an empty list gives an empty string: ''
add the last newline yourself: 'apples\nbread\nmilk\n'

join() puts \n between items only, and it refuses anything that isn’t a string.I use join() far more than += in a loop. It builds the result in one go, and it can’t leave a stray newline hanging off the end.
The separator goes between items, so there’s no newline after the last one. Add it yourself when you’re writing lines to a file and want the file to end cleanly.
join() only accepts strings. A list of numbers raises TypeError: sequence item 0: expected str instance, int found, so convert them on the way in with str(n) for n in numbers.
There’s more on this pattern in turning a list of strings into one string, including other separators.
Multiline strings and docstrings with triple quotes
Triple quotes let you type real line breaks instead of \n. Watch the first line, though:
address = """
Ava Johnson
1200 Market Street
San Francisco, CA
"""
print(repr(address))
address = """\
Ava Johnson
1200 Market Street
San Francisco, CA"""
print(repr(address))
print(address)
print()
def order_total(price, qty):
"""Return the order total.
price and qty are plain numbers.
"""
return price * qty
print(repr(order_total.__doc__))
Output:
'\nAva Johnson\n1200 Market Street\nSan Francisco, CA\n'
'Ava Johnson\n1200 Market Street\nSan Francisco, CA'
Ava Johnson
1200 Market Street
San Francisco, CA
'Return the order total.\n\nprice and qty are plain numbers.\n'
A newline right after the opening quotes is part of the string, so the first version starts with \n. A backslash straight after the quotes swallows it.
Docstrings are triple-quoted strings too. Since Python 3.13, the compiler strips their common indentation, which is why __doc__ above has no leading spaces. I checked: 3.12 keeps them.
Ordinary triple-quoted strings inside a function still keep their indentation. textwrap.dedent() removes it.
Line breaks in your code versus in the string
Splitting a long line of code isn’t the same thing. Adjacent strings inside parentheses join with no newline at all. Continuing a long string on the next line covers that side.
New line inside a Python f-string
Putting \n in the text part of an f-string always worked. Putting it inside the braces used to be a problem:
import sys
items = ["apples", "bread", "milk"]
print(f"Shopping list:\n{'\n'.join(items)}")
print()
nl = "\n"
print(f"Same list, older-Python style:{nl}{nl.join(items)}")
print()
print("ran on", sys.version.split()[0])
Output:
Shopping list:
apples
bread
milk
Same list, older-Python style:
apples
bread
milk
ran on 3.14.7
On Python 3.11, that first f-string is a SyntaxError: f-string expression part cannot include a backslash. I ran it on 3.11.9 to be sure. Python 3.12 lifted the rule.
If your code still has to run on older versions, put "\n" in a variable first, like the nl version. It works everywhere.
Print a new line with print()
print() adds a newline for you, which is why each call lands on its own line:
print("first line")
print() # an empty print() is a blank line
print("second", "third", sep="\n") # one argument per line
print("no newline here", end="")
print(" <- still the same line")
print("top\n\nbottom") # two \n in a row leave a blank line
Output:
first line
second
third
no newline here <- still the same line
top
bottom
print() ends with end="\n" by default. Pass end="" to stay on the same line, or sep="\n" to put each argument on its own line.
There’s a whole article on the printing side: printing a new line after a variable, with the end and sep tricks in detail.
Write a new line to a file (and why os.linesep doubles it)
Files are where newlines get genuinely confusing, especially on Windows:
import os
with open("orders.txt", "w") as f:
f.write("order 1") # write() adds nothing
f.write("order 2\n")
print("order 3", file=f) # print() adds the newline for you
with open("orders.txt", "rb") as f:
print("orders.txt bytes:", f.read())
print()
print("os.linesep here:", repr(os.linesep))
with open("a.txt", "w") as f:
f.write("order 1" + os.linesep)
with open("b.txt", "w") as f:
f.write("order 1\n")
with open("a.txt", "rb") as f:
print("text mode + os.linesep ->", f.read())
with open("b.txt", "rb") as f:
print("text mode + \\n ->", f.read())
Output:
orders.txt bytes: b'order 1order 2\r\norder 3\r\n'
os.linesep here: '\r\n'
text mode + os.linesep -> b'order 1\r\r\n'
text mode + \n -> b'order 1\r\n'

os.linesep in text mode writes \r\r\n. Plain \n gives the correct \r\n.write() adds nothing, so order 1 and order 2 ran together. print(..., file=f) adds the newline like it does on screen.
Now the surprise. You’ll often read that os.linesep makes line endings portable. In text mode it does the opposite: Python already turns each \n into \r\n on Windows, so os.linesep ends up as \r\r\n.
On macOS and Linux, os.linesep is just \n and text mode writes it unchanged, so the same code produces a clean file there. That’s exactly why this bug hides until a Windows teammate runs it.
Just write \n and let text mode translate it. Open with newline="" only when you need exact control, as the csv module does.
When you want the opposite, writing to a file without a newline shows how. Reading files back is covered in reading a file line by line.
Split a string on newlines: split() vs splitlines()
Going the other way, from one string to a list of lines, there are two options, and they disagree:
text = "apples\nbread\nmilk\n"
print(text.split("\n"))
print(text.splitlines())
print()
windows = "apples\r\nbread\r\n"
print(windows.split("\n"))
print(windows.splitlines())
print(windows.splitlines(keepends=True))
print()
print('"".split("\\n") ->', "".split("\n"))
print('"".splitlines() ->', "".splitlines())
Output:
['apples', 'bread', 'milk', '']
['apples', 'bread', 'milk']
['apples\r', 'bread\r', '']
['apples', 'bread']
['apples\r\n', 'bread\r\n']
"".split("\n") -> ['']
"".splitlines() -> []
split("\n") leaves an empty string at the end when the text ends with a newline, and it leaves \r stuck to every line of a Windows file.
splitlines() handles \n, \r\n and \r, and drops the trailing empty item. It’s almost always the one you want for text.
To get rid of the newlines entirely instead of splitting on them, see removing newlines from a string.
Does input() keep the newline?
No, and that’s a common source of confusion when you switch to reading stdin directly:
import sys
name = input() # reads "Ava" and drops the newline
print(repr(name))
city = sys.stdin.readline() # reads "San Francisco" and keeps it
print(repr(city))
print(repr(city.rstrip("\n")))
Output:
'Ava'
'San Francisco\n'
'San Francisco'
input() strips the newline from the end of what you typed. sys.stdin.readline() keeps it, so compare its result to "San Francisco" and you’ll get False until you rstrip("\n") it.
Python new line quick reference
"\n"starts a new line. It’s one character, code 10./nis not a newline. Use a backslash.- Write Windows paths as raw strings:
r"C:\reports\new.csv". "\n".join(lines)joins a list, with no newline after the last item.- Triple quotes keep a leading newline unless you add
\after them. print()adds\n;f.write()doesn’t.- Write
\nin text mode, notos.linesep. splitlines()beatssplit("\n")for real text.
Newline handling touches a lot of other string work, so these pair well with it:
- Print on the same line in Python
- Write a list to a file
- Split a long string into multiple lines
- Split a string by space
- Print a new line after a variable
Frequently asked questions
How do I make a new line in Python?
Put \n inside the string: print("Hello\nWorld") prints two lines. print() also ends every call with a newline, so separate print() calls land on separate lines.
Is it \n or /n in Python?
\n, with a backslash. /n is just a forward slash and the letter n, so it prints exactly as typed and doesn’t start a new line.
How do I add a newline to the end of a string?
Build a new string with text + "\n", text += "\n" or an f-string. Strings have no append() method because they can’t be changed in place.
Why does my Windows file path contain a line break?
Because \n in a path like "C:\new" is read as a newline escape. Use a raw string, r"C:\new", or forward slashes.
What’s the difference between split(‘\n’) and splitlines()?
split("\n") leaves an empty item after a trailing newline and keeps \r from Windows line endings. splitlines() handles every line ending and drops the empty item.
Should I use os.linesep when writing a file?
Not in text mode. Python already translates \n to the platform ending, so on Windows os.linesep is written as \r\r\n. Write \n and let Python translate it.
What other escape sequences does Python have besides \n?
\t is a tab, \r a carriage return, \\ a backslash, and \' and \" are quotes. The complete list is in the Python escape sequences reference.

Bijay Kumar is a 13-time Microsoft MVP with more than 18 years in software development, and the founder of Python Guides and TSinfo Technologies. He started out building .NET and SharePoint solutions at HP, TCS and KPIT before moving into Python, machine learning and AI, and he also builds web apps with TypeScript and React. He writes the tutorials here himself, and every example is run before publishing so you see the real output. More about Bijay · Microsoft MVP profile · LinkedIn