Skip to content

Bytes

You can declare bytes for CLI arguments and options.

By default, bytes are created by encoding the input string with UTF-8 (the same as Python's default for str.encode()), but you can configure the encoding and error handling.

Default UTF-8 encoding

This example declares a bytes argument using the default UTF-8 encoding:

import typer


def main(data: bytes):
    # Default encoding is UTF-8
    print(f"Bytes: {data!r}")


if __name__ == "__main__":
    typer.run(main)

Try it with non-ASCII characters and you will get UTF-8 encoded bytes.

Custom encoding on Argument

You can set a specific encoding for a bytes argument:

import typer


def main(data: bytes = typer.Argument(..., encoding="latin-1")):
    # Argument configured to use latin-1
    print(f"Bytes (latin-1): {data!r}")


if __name__ == "__main__":
    typer.run(main)

Here the argument is configured with encoding="latin-1", so the command line input will be encoded accordingly.

Custom encoding and errors on Option

You can also configure a bytes option with a specific encoding and error handling mode:

import typer


def main(token: bytes = typer.Option(..., encoding="ascii", errors="replace")):
    # Option configured with ascii encoding and errors=replace
    print(f"Token: {token!r}")


if __name__ == "__main__":
    typer.run(main)

The errors parameter supports the same values as Python's str.encode() (e.g. "strict", "ignore", "replace").

Primary use case

The goal of supporting bytes is to let you write a single function that works both:

  • Inside Typer: when called as a CLI, Typer parses command line input and converts it to bytes using the configured encoding/errors.
  • Outside Typer: when called as regular Python code, you can pass bytes directly, without any CLI parsing involved.

This keeps your function reusable in both contexts while giving you control over how CLI text inputs are converted to bytes.