argparse type=bool Always True Except Empty String (tested)
Passing type=bool to argparse.add_argument() looks like it should let a user type --flag False to turn something off. We measured exactly what it does instead — and it almost never returns False.
1. --flag False parses as True
import argparse
p = argparse.ArgumentParser()
p.add_argument("--flag", type=bool)
args = p.parse_args(["--flag", "False"])
print(args.flag)
True
Measured: args.flag is True after passing --flag False on the command line. argparse calls type(value) on the raw string it received, so this is exactly bool("False") — and in Python, any non-empty string is truthy. The word "False" has no special meaning to bool(); it's just a 5-character string, and 5-character strings are truthy.
2. '0', 'no', and '' all behave differently than you'd expect
for v in ["True", "False", "0", "1", "no", "yes", ""]:
args = p.parse_args(["--flag", v])
print(repr(v), "->", args.flag)
'True' -> True
'False' -> True
'0' -> True
'1' -> True
'no' -> True
'yes' -> True
'' -> False
Measured: every value we tried came back True except the empty string --flag "", which is the one case bool() treats as falsy. '0' and 'no' — the two forms a user is most likely to type when they mean "off" — both parse as True. There's no error, no warning; the flag is simply on regardless of what the user typed, unless they typed nothing at all.
3. Fix: store_true/store_false, or BooleanOptionalAction for an explicit --no- flag
p2 = argparse.ArgumentParser()
p2.add_argument("--flag", action=argparse.BooleanOptionalAction)
print(p2.parse_args(["--flag"]).flag)
print(p2.parse_args(["--no-flag"]).flag)
print(p2.parse_args([]).flag)
True
False
None
Measured: argparse.BooleanOptionalAction (added in Python 3.9) confirmed giving a real on/off pair: --flag sets True, the auto-generated --no-flag sets False, and omitting both leaves the default. For a simple on/off switch with no explicit value on the command line, the older action="store_true" works the same way without the --no- variant. Either way, the value comes from which flag was typed, not from running an untrusted string through bool().
Frequently asked questions
Why does argparse type=bool always return True?
We measured argparse calling bool() on the raw command-line string. Since any non-empty Python string is truthy, type=bool returns True for 'False', '0', 'no', and virtually every value except an empty string.
What does --flag False actually do with type=bool in argparse?
We confirmed it sets args.flag to True. argparse never interprets the word 'False' specially — it only runs bool('False'), which is True because the string has characters in it.
Is there any value that makes argparse type=bool return False?
In our measurement, only an empty string (--flag '') returned False, since bool('') is the one falsy string value in Python. Every other string we tried, including '0' and 'no', returned True.
What should I use instead of type=bool in argparse?
We verified action="store_true" (or "store_false") for a simple on/off switch, or argparse.BooleanOptionalAction (Python 3.9+) when you also want an explicit --no-flag form that sets False.
Does argparse.BooleanOptionalAction support a --no- prefix automatically?
Yes — we measured add_argument("--flag", action=argparse.BooleanOptionalAction) automatically creating a working --no-flag option that sets False, alongside --flag setting True.
Written with AI assistance. Measured on 2026-10-04 with Python 3.13.5's built-in argparse module: passed type=bool to add_argument() and ran the parser against 'True', 'False', '0', '1', 'no', 'yes', and an empty string on the command line, printing the resulting Python value each time. PlainHeaders is our extension; Python's argparse module is built in.