The quickest way to pad a string with zeros in Python is str.zfill(width): it adds zeros on the left until the string is width characters long and keeps a leading + or - in front. For zeros on the right, use ljust(width, "0"):
"42".zfill(5) # '00042'
"1.5".ljust(5, "0") # '1.500'
I checked every result with Python 3.12.5 and pandas 3.0.6, using order IDs and ZIP codes as the example strings.
You’ll see zfill, the rjust and ljust alternatives, the f-string rule that catches people out with strings, ZIP codes that lose their zeros in pandas, and how to remove leading zeros again.
Pad a string with zeros using zfill()
zfill() is built for exactly this job. Strings already at or over the width come back unchanged, so it never truncates:
order_ids = ["7", "42", "305", "12345", "1234567"]
for oid in order_ids:
print(f"{oid:>8} -> {oid.zfill(5)}")
print("-42".zfill(6), "+7".zfill(4), "3.5".zfill(6)) # sign stays in front
Output:
7 -> 00007
42 -> 00042
305 -> 00305
12345 -> 12345
1234567 -> 1234567
-00042 +007 0003.5

If you’re starting from an integer rather than a string, format it directly instead; my guide on padding numbers with leading zeros in Python covers that side.
Pad with zeros on the left or right using rjust() and ljust()
rjust(), ljust() and center() take any fill character. The difference from zfill() shows up with signs:
code = "-42"
print("zfill: ", code.zfill(6))
print("rjust '0': ", code.rjust(6, "0")) # zeros go before the minus sign
print("ljust '0': ", "1.5".ljust(6, "0")) # pad on the right
print("center '0':", "TX".center(6, "0"))
Output:
zfill: -00042
rjust '0': 000-42
ljust '0': 1.5000
center '0': 00TX00

rjust() puts zeros in front of the minus sign, giving 000-42; zfill() gives -00042.Use ljust(width, "0") for trailing zeros, like fixed-width decimal fields. For general text, building fixed-width strings is covered in creating a string of N characters in Python.
Why does an f-string pad my string with zeros on the right?
For numbers, {n:05} pads on the left. For strings, the same spec pads on the right, because strings align left by default. Add > to fix it:
s = "42"
n = 42
print(f"{n:05}") # int: zero-padded on the left -> 00042
print(f"{s:05}") # str: '0' is just the fill, and strings align LEFT -> 42000
print(f"{s:0>5}") # say > to right-align a string -> 00042
print(f"{s:0<5}") # right padding on purpose -> 42000
width = 8
print(f"{'A-17':0>{width}}") # width from a variable
print("{:0>6}".format("731")) # same rules in str.format
Output:
00042
42000
00042
42000
0000A-17
000731

:05 gives 00042 for the int and 42000 for the string.So for strings I always write the alignment explicitly: :0>5 for leading zeros. Formatting rules in general are in creating a string with variables in Python.
Keep leading zeros in ZIP codes and IDs with pandas
Leading zeros usually vanish before you ever pad anything: a CSV reader sees 02134 and stores the number 2134. Here’s that happening in pandas, and two fixes:
import io
import pandas as pd
csv = "customer,zip\nEmily,02134\nJames,07030\nOlivia,73301\n"
wrong = pd.read_csv(io.StringIO(csv))
print(wrong["zip"].tolist(), wrong["zip"].dtype) # leading zeros gone
fixed = wrong["zip"].astype(str).str.zfill(5)
print(fixed.tolist())
right = pd.read_csv(io.StringIO(csv), dtype={"zip": str}) # best: never lose them
print(right["zip"].tolist(), right["zip"].dtype)
Output:
[2134, 7030, 73301] int64
['02134', '07030', '73301']
['02134', '07030', '73301'] str

str.zfill(5) restores it, but reading the column as text is the real fix.The same thing happens with phone extensions, product codes and account numbers. If the data comes from a text file first, see reading a file as a string in Python.
Remove leading zeros from a string
Going the other way, lstrip("0") removes leading zeros, but it has two traps: an all-zero string becomes empty, and it doesn’t understand signs. Converting to a number avoids both:
values = ["000042", "0000", "0.50", "-0042"]
for v in values:
print(f"{v!r:>9} lstrip -> {v.lstrip('0')!r:>7} int/float -> {float(v) if '.' in v else int(v)}")
Output:
'000042' lstrip -> '42' int/float -> 42
'0000' lstrip -> '' int/float -> 0
'0.50' lstrip -> '.50' int/float -> 0.5
'-0042' lstrip -> '-0042' int/float -> -42
Use int() when the value is really a number, and lstrip() only for codes. Turning text into numbers safely is covered in converting a string to an integer in Python.
Zero-padding methods compared
| Method | Pads | Handles + / – | Example |
|---|---|---|---|
s.zfill(5) | Left | Yes | '-42' → '-0042' |
s.rjust(5, "0") | Left | No | '-42' → '00-42' |
s.ljust(5, "0") | Right | No | '1.5' → '1.500' |
f"{s:0>5}" | Left | No | '42' → '00042' |
Series.str.zfill(5) | Left | Yes | pandas columns |
These string guides are worth a look next:
- Format a number with commas in Python
- Print 2 decimal places in Python
- Append to a string in Python
- Escape curly braces in Python format strings
Frequently asked questions
How do I pad a string with zeros in Python?
Use s.zfill(width), for example "42".zfill(5) gives '00042'.
How do I add zeros to the right of a string?
Use s.ljust(width, "0") or f"{s:0<width}".
Why does f”{s:05}” add zeros at the end?
Strings are left-aligned by default. Use f"{s:0>5}" to put the zeros in front.
Does zfill work with negative numbers?
Yes. "-42".zfill(5) gives '-0042', keeping the sign first. rjust() doesn’t.
How do I keep leading zeros when reading a CSV?
Read the column as text, for example pd.read_csv(path, dtype={"zip": str}).
Where is str.zfill documented?
See str.zfill() in the Python docs.

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