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())
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.
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))
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:
b"Marta"creates abytesobject. Its contents are the byte values for the ASCII/UTF-8 letters inMarta.raw_name.decode("utf-8")interprets those bytes using UTF-8 and returns thestrvalue"Marta"."Hello, "andnameare bothstrvalues, so Python can concatenate them.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 .
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
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:
Comparisons
| Feature | str | bytes |
|---|---|---|
| Literal example | "hello" | b"hello" |
| Represents | Unicode text characters | Raw values from 0 to 255 |
| Typical use | Names, messages, JSON text | Files, sockets, hashes, protocols |
| Iteration result | One-character str values | Integers |
| Convert from the other type | data.decode("utf-8") | text.encode("utf-8") |
| Direct non-ASCII literal content | Allowed |
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
strfor human-readable text. - Use
bytesfor 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]returnsbytes.- A
bliteral 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:
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
strmessage and returns abytespacket. - Create a function that validates the packet marker.
- Decode the message portion as UTF-8.
- Raise
ValueErrorwhen the packet does not have the expected marker.
Keep learning
Related questions
@staticmethod vs @classmethod in Python Explained
Learn the difference between @staticmethod and @classmethod in Python with clear examples, use cases, mistakes, and a mini project.
Add Rows to a Pandas DataFrame in Python
Learn how to add rows to a Pandas DataFrame, why repeated row appends are slow, and when to use loc, concat, or record lists.
Call a Function by Name in a Python Module
Learn how to call a function by name in a Python module using strings, getattr, and safe patterns for dynamic function dispatch.