isdigit() is a Python string method that returns True when every character in the string is a digit, and False otherwise.
"123".isdigit() # True
"12a".isdigit() # False
"-5".isdigit() # False <- catches people out
"3.14".isdigit() # False <- so does this
Those last two are why you’re probably here. A minus sign isn’t a digit and neither is a full stop, so isdigit rejects most real-world numbers.
Everything on this page ran on Python 3.12.5, and the screenshots are those runs.
What isdigit() does
It checks every character and returns a single boolean. One non-digit anywhere makes the whole thing False:
print("123".isdigit()) # True
print("abc".isdigit()) # False
print("12a".isdigit()) # False, every character must be a digit
print("".isdigit()) # False, an empty string has nothing to check
# it is a string method, so numbers have to be strings first
print(str(2026).isdigit())
Output:
True
False
False
False
True
An empty string returns False too, which is convenient: you don’t need a separate length check before calling it.
What isdigit() returns False for
This is the table worth remembering, because the surprises are all practical:
values = ["42", "-5", "3.14", "1_000", " 7 ", "٧", "²", "½", ""]
print(f"{'value':<8} {'isdigit':>8}")
for value in values:
print(f"{value!r:<8} {value.isdigit()!s:>8}")
Output:
value isdigit
'42' True
'-5' False
'3.14' False
'1_000' False
' 7 ' False
'٧' True
'²' True
'½' False
'' False
'42' and the two Unicode digits pass."-5"— the minus sign is not a digit."3.14"— neither is the decimal point."1_000"— underscores are legal in Python literals, not in strings." 7 "— spaces count as characters, so strip first.
If you’re validating user input, strip the whitespace before the check and handle the sign yourself. That’s the same care any input check needs.
isdigit vs isdecimal vs isnumeric
Python has three of these and they disagree on exactly the characters you’d never think to test:
samples = ["42", "²", "½", "٧", "3.14", "-5"]
print(f"{'value':<8} {'isdigit':>8} {'isdecimal':>10} {'isnumeric':>10}")
for s in samples:
print(f"{s!r:<8} {s.isdigit()!s:>8} {s.isdecimal()!s:>10} {s.isnumeric()!s:>10}")
print()
print("superscript two -> isdigit True, isdecimal False")
print("one half -> isnumeric True only")
print("arabic-indic 7 -> all three True")
Output:
value isdigit isdecimal isnumeric
'42' True True True
'²' True False True
'½' False False True
'٧' True True True
'3.14' False False False
'-5' False False False
superscript two -> isdigit True, isdecimal False
one half -> isnumeric True only
arabic-indic 7 -> all three True
| Method | Accepts | Example that differs |
|---|---|---|
isdecimal() | Characters usable in a base-10 number | "²".isdecimal() is False |
isdigit() | Decimals plus superscripts and subscripts | "²".isdigit() is True |
isnumeric() | Everything above plus fractions and numerals | "½".isnumeric() is True |
isdecimal() is the strictest and usually the one you want, because it accepts exactly the characters int() can parse.
isnumeric() is the loosest. It says yes to "½" and to Roman numerals, neither of which int() will take.
Checking whether a string is really a number
Since isdigit refuses negatives and decimals, here are the two checks that actually work:
def is_whole_number(text):
"""True for '42' and '-5', False for '3.14' and 'abc'."""
return text.lstrip("-").isdigit() and text not in ("", "-")
def is_any_number(text):
"""True for anything float() accepts, including decimals and negatives."""
try:
float(text)
return True
except ValueError:
return False
for value in ["42", "-5", "3.14", "-3.14", "abc", "", "1e5"]:
print(f"{value!r:<8} whole={is_whole_number(value)!s:<6} number={is_any_number(value)}")
Output:
'42' whole=True number=True
'-5' whole=True number=True
'3.14' whole=False number=True
'-3.14' whole=False number=True
'abc' whole=False number=False
'' whole=False number=False
'1e5' whole=False number=True
float() version accepts decimals, negatives and scientific notation.Stripping a leading minus before isdigit handles whole numbers including negatives. For anything else, try: float(text) is the honest test.
Note that the float() version accepts "1e5". If that’s not wanted, use the isdecimal check instead.
Validating input with isdigit
The most common real use is a prompt that keeps asking until it gets digits:
def read_age(prompt):
while True:
text = input(prompt).strip()
if text.isdigit(): # digits only: no minus, no decimal point
return int(text)
print(" please type a whole number")
age = read_age("Age: ")
print("you entered:", age)
Typing ‘twelve’, then ‘-3’, then a valid age:
Age: please type a whole number
Age: please type a whole number
Age: you entered: 34
isdigit suits this precisely because it’s strict. An age can’t be negative or fractional, so the method’s limitations become the validation rule. For measurements that can be decimal, use float() in a try block.
More Python string and input guides:
- Check if a number is between two values
- Area of a rectangle in Python
- Remove characters from a string
- Round numbers to 2 decimal places
- List comprehension with if else
Frequently asked questions
What does isdigit() do in Python?
It returns True when every character in the string is a digit and the string is not empty. It is documented with the other string methods in the Python string reference.
Why does isdigit() return False for a negative number?
The minus sign is not a digit, so "-5".isdigit() is False. Strip the sign first, or use a float() check.
Why does isdigit() return False for 3.14?
The decimal point is not a digit either. Use try: float(text) when decimals are allowed.
What is the difference between isdigit and isnumeric?
isnumeric is looser: it accepts fractions such as "½" and other numerals that isdigit rejects.
What is the difference between isdigit and isdecimal?
isdecimal is stricter. Superscripts like "²" pass isdigit but fail isdecimal.
Does isdigit() work on an empty string?
It returns False, so you do not need a separate emptiness check before calling it.
Which should I use to validate a number from input()?
isdecimal() for whole numbers, or float() inside a try block when decimals and negatives are allowed.
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