Question

Python b String Prefix: Bytes Literals Explained

pythonstringunicodebinary

Question

Python accepts a b prefix before a string literal:

b"The string"

What does the b prefix mean? What effects does it have, and when is it appropriate to use it?

How does it differ from the u prefix for Unicode strings? Are there other prefixes that can be placed before Python string literals?

Short Answer

The b prefix creates a bytes literal rather than a normal Python text string. You will learn the difference between str and bytes, how to convert between them with encoding and decoding, when byte data is necessary, and which literal prefixes Python supports.

Concept

In modern Python, a normal quoted literal creates a str object:

message = "Hello"
print(type(message))  # <class 'str'>

A literal prefixed with b creates a bytes object:

message_bytes = b"Hello"
print(type(message_bytes))  # <class 'bytes'>

str represents text: human-readable characters such as letters, punctuation, and emoji. Python stores text as Unicode characters.

bytes represents raw byte values: integers from 0 through 255. Bytes are the form used by files, network connections, images, compressed data, and many binary protocols.

print("ABC")       # ABC
print(b"ABC")      # b'ABC'
print(list(b"ABC")) # [65, 66, 67]

The b is not part of the value. It is literal syntax that tells Python which type to create.

A bytes literal can directly contain ASCII characters. For byte values that are not easily written as ASCII, use escape sequences such as \x00:

packet_start = b"\x02DATA\x03"

Use str for text and bytes for byte-oriented data. Convert explicitly at a boundary using an encoding, usually UTF-8:

text = "café"
data = text.encode("utf-8")   # str -> bytes
again = data.decode("utf-8")  # bytes -> str

Explicit conversion matters because the same byte sequence can mean different text under different encodings.

Mental Model

Think of str as a written message and bytes as the individual numbered signals used to send or store that message.

  • str: “Hello” as text a person can read.
  • bytes: the numeric byte values a computer sends across a network or writes to a file.

The b prefix says: “Create the raw signals, not a text message.”

Encoding is translating a message into signals. Decoding is translating those signals back into a message.

Take Quiz

Syntax and Examples

A bytes literal uses b or uppercase B immediately before the quote:

data1 = b"hello"
data2 = b'hello'
data3 = B"hello"

Bytes support many familiar escape sequences:

newline = b"first line\nsecond line"
header = b"ID:\x00\xff"

You can inspect byte values by iterating over the object:

word = b"cat"

for value in word:
    print(value)

Output:

99
97
116

Unlike iterating over a str, iterating over bytes produces integers.

Encoding text into bytes

name = "Ada"
wire_data = name.encode("utf-8")

print(wire_data)        # b'Ada'
print(type(wire_data))  # <class 'bytes'>

Decoding bytes into text

wire_data = b"Ada"
name = wire_data.decode("utf-8")

print(name)        # Ada
print(type(name))  # <class 'str'>

Use encode() when text must become bytes, and decode() when bytes contain encoded text.

Step by Step Execution

Consider code that receives UTF-8 data from an external source:

raw_name = b"Marta"
name = raw_name.decode("utf-8")
greeting = "Hello, " + name
print(greeting)

Step by step:

  1. b"Marta" creates a bytes object. Its contents are the byte values for the ASCII/UTF-8 letters in Marta.
  2. raw_name.decode("utf-8") interprets those bytes using UTF-8 and returns the str value "Marta".
  3. "Hello, " and name are both str values, so Python can concatenate them.
  4. print() displays:
Hello, Marta

If you skip decoding, Python rejects the mixed types:

raw_name = b"Marta"
greeting = "Hello, " + raw_name  # TypeError

This is intentional: Python requires you to decide how bytes should be interpreted as text.

Real World Use Cases

Use bytes when an API expects or returns raw data rather than Python text.

  • Reading binary files: Images, PDFs, ZIP archives, and executable data are bytes.

    with open("photo.jpg", "rb") as file:
        image_data = file.read()
    
  • Writing binary files: A program may generate a binary format.

    with open("output.bin", "wb") as file:
        file.write(b"\x00\x01\x02")
    
  • Network communication: Sockets send and receive bytes.

    request = "PING\r\n".encode("utf-8")
    
  • Web requests and API responses: HTTP response bodies are often received as bytes before being decoded as text or parsed as JSON.

  • Cryptography and hashing: Hash functions operate on bytes.

    import hashlib
    
    digest = hashlib.sha256(b"important data").hexdigest()
    
  • Binary protocols: Hardware devices and custom protocols may specify exact byte values, such as b"\xaa\x01\x00".

Take Quiz

Real Codebase Usage

In real projects, developers usually avoid scattering b literals throughout application logic. Instead, they keep text as str and convert only at system boundaries.

Encode before sending or storing

def send_message(socket, message: str) -> None:
    socket.sendall(message.encode("utf-8"))

Decode as soon as received

def read_message(socket) -> str:
    response = socket.recv(4096)
    return response.decode("utf-8")

This approach keeps most business logic working with readable Unicode text.

Use byte literals for fixed protocol markers

PNG_SIGNATURE = b"\x89PNG\r\n\x1a\n"

with open("image.png", "rb") as file:
    if file.read(8) != PNG_SIGNATURE:
        raise ValueError("Not a PNG file")

Validate before decoding untrusted data

External bytes may not be valid in the expected encoding:

try:
    text = incoming_data.decode("utf-8")
except UnicodeDecodeError:
    text = ""

The correct error-handling policy depends on the application. Some programs reject invalid input; others log it or use a documented fallback.

Common Mistakes

Mixing str and bytes

Python does not automatically combine text and bytes:

# Broken
label = "User: " + b"Marta"

Fix it by decoding the bytes or encoding the text:

label = "User: " + b"Marta".decode("utf-8")
# or, when bytes are required:
label_bytes = b"User: " + "Marta".encode("utf-8")

Assuming b means “binary text”

b"hello" is a bytes object, not a special version of text. Use a regular str unless an API specifically needs bytes.

Writing non-ASCII characters directly in a bytes literal

This is invalid:

# Broken: bytes literals may directly contain ASCII characters only
word = b"café"

Encode a text string instead:

word = "café".encode("utf-8")

Decoding with the wrong encoding

data = "café".encode("utf-8")
# data.decode("ascii")  # UnicodeDecodeError

Use the encoding that was used to create the data. If you control both sides, UTF-8 is a common choice.

Forgetting binary file mode

Use "rb" and "wb" for raw files. Text modes ("r" and "w") read or write str and handle encoding for you.

Expecting byte indexing to return a one-character bytes object

value = b"ABC"[0]
print(value)  # 65, not b'A'

To get a one-byte slice, use:

first_byte = b"ABC"[0:1]  # b'A'

Comparisons

Featurestrbytes
Literal example"hello"b"hello"
RepresentsUnicode text charactersRaw values from 0 to 255
Typical useNames, messages, JSON textFiles, sockets, hashes, protocols
Iteration resultOne-character str valuesIntegers
Convert from the other typedata.decode("utf-8")text.encode("utf-8")
Direct non-ASCII literal contentAllowedNot allowed; encode a str instead

String literal prefixes

PrefixMeaningExample
bCreate bytesb"OK"
rTreat backslashes as mostly literal charactersr"C:\\temp\\file.txt"
fFormat expressions inside {}f"Hello, {name}"
uUnicode string prefix; accepted mainly for compatibility in modern Pythonu"hello"
rb or brRaw bytes literalrb"\x41"
rf or frRaw formatted stringrf"{folder}\\file.txt"

Not every prefix combination is valid. In particular, bytes literals cannot be f-strings: bf"..." is invalid. Build text with an f-string and then call .encode() if bytes are needed.

Take Quiz

Cheat Sheet

# Text
text = "hello"                 # str

# Bytes
raw = b"hello"                 # bytes

# Text -> bytes
raw = text.encode("utf-8")

# Bytes -> text
text = raw.decode("utf-8")

# Binary file operations
open("file.dat", "rb")         # read bytes
open("file.dat", "wb")         # write bytes

# Exact byte values
marker = b"\x00\xff"
  • Use str for human-readable text.
  • Use bytes for raw data and APIs that require bytes.
  • Do not concatenate or compare text and bytes as though they are the same type.
  • Specify an encoding when converting; UTF-8 is commonly used.
  • bytes[index] returns an integer; bytes[start:end] returns bytes.
  • A b literal may directly contain ASCII characters. Encode a normal string for non-ASCII text.

FAQ

What does b mean before a string in Python?

It creates a bytes object instead of a normal str object. For example, b"abc" is byte data, while "abc" is Unicode text.

Is b"hello" the same as "hello"?

No. They may look similar when printed, but they have different types and cannot be freely mixed. b"hello" is bytes; "hello" is str.

When should I use a bytes literal in Python?

Use one for fixed raw data, such as file signatures, protocol commands, byte markers, and test fixtures. For ordinary user-facing text, use str.

How do I convert a Python string to bytes?

Call encode() with an encoding:

payload = "Hello".encode("utf-8")

How do I convert bytes to a Python string?

Call decode() with the encoding used for the data:

text = b"Hello".decode("utf-8")

Why does Python show b'...' when printing bytes?

The b in the displayed representation distinguishes byte data from a text string. It is not an extra byte inside the data.

What does the u prefix mean in Python 3?

Python 3 strings are Unicode by default, so u"text" behaves like "text". The prefix remains accepted mainly for compatibility with older code.

Can a bytes literal contain emoji or accented characters?

Not directly. Start with a normal Unicode string and encode it, for example: "🚀".encode("utf-8").

Take Quiz

Mini Project

Description

Build a small packet creator and reader. The packet has a fixed byte marker followed by a UTF-8 encoded message. This mirrors how programs mix raw protocol bytes with human-readable text in files and network messages.

Goal

Create a byte packet from a text message, then validate and decode the packet back into text.

Requirements

  • Define a bytes constant that identifies the start of a packet.
  • Create a function that accepts a str message and returns a bytes packet.
  • Create a function that validates the packet marker.
  • Decode the message portion as UTF-8.
  • Raise ValueError when the packet does not have the expected marker.
Take Quiz

Keep learning

Related questions

View more