Basics Intermediate Advanced
aialgorithmsapibest-practicescareercommunitydatabasesdata-sciencedata-structuresdata-vizdevopsdjangodockereditorsflaskfront-endgamedevguimachine-learningnewsnumpyprojectspythonstdlibtestingtoolsweb-devweb-scraping

How to Convert Bytes to Strings in Python
Table of Contents
Converting bytes into readable strings in Python is an effective way to work with raw bytes fetched from files, databases, or APIs. You can do this in just three steps using thebytes.decode() method. This guide lets you convert byte data into clean text, giving you a result similar to what’s shown in the following example:
>>>binary_data=bytes([100,195,169,106,195,160,32,118,117])>>>binary_data.decode(encoding="utf-8")'déjà vu'By interpreting the bytes according to a specificcharacter encoding, Python transforms numeric byte values into their corresponding characters. This allows you to seamlessly handle data loaded from files, network responses, or other binary sources and work with it as normal text.
Abyte is a fundamental unit of digital storage and processing. Composed of eight bits (binary digits), it’s a basic building block of data in computing. Bytes represent a vast range of data types and are used extensively in data storage and in networking. It’s important to be able to manage and handle bytes where they come up. Sometimes they need to be converted into strings for further use or comprehensibility.
By the end of this guide, you’ll be able to convertPythonbytes to strings so that you can work with byte data in a human-readable format.
Get Your Code:Click here to download the free sample code that you’ll use to convert bytes to strings in Python.
Take the Quiz: Test your knowledge with our interactive “How to Convert Bytes to Strings in Python” quiz. You’ll receive a score upon completion to help you track your learning progress:
Interactive Quiz
How to Convert Bytes to Strings in PythonDecode bytes into readable strings in Python. Test your skills working with data from files, APIs, and databases.
Step 1: Obtain the Byte Data
Before convertingbytes tostrings, you’ll need some actual bytes to work with. In everyday programming, you may not have to deal with bytes directly at all, as Python often handles their encoding and decoding behind the scenes.
Binary data exchanged over the internet can be expressed in different formats, such as raw binary streams,Base64, orhexadecimal strings. When you browse a web page, download a file, or chat with a colleague, the data that emerges travels as numeric bytes before it is interpreted as text that you can read.
In this step, however, you’ll obtain byte data using one of two approaches:
- Using the
bytesliteral (b"") - Using the
urllibpackage
You’ll soon find that using theurllib package requires that you go online. You can, however, createbytes manually without reaching out to the internet at all. You do this by prefixing a string withb, which creates abytes literal containing the text inside:
raw_bytes=b"These are some interesting bytes"You may be wondering why you have to create abytes object at all from strings that you can read. This isn’t just a convenience. Whilebytes and strings share most of their methods, you can’t mix them freely. If you pass string arguments to abytes method, then you’ll get an error:
>>>raw_bytes=b"These are some interesting bytes">>>raw_bytes.replace("y","o")Traceback (most recent call last):...TypeError:a bytes-like object is required, not 'str'Abytes object only accepts otherbytes-like objects as arguments. If you try to use a string like"y" with abytes method, then Python raises aTypeError. To work with raw binary data, you must explicitly usebytes, not strings.
Note that you can represent the same information using alternativenumeral formats, including binary, decimal, or hexadecimal. For instance, in the following code snippet, you convert the samebytes object from the above code example into hexadecimal and decimal formats:
>>>raw_bytes.hex()'54686573652061726520736f6d6520696e746572657374696e67206279746573'>>>list(raw_bytes)[84, 104, 101, 115, 101, 32, 97, 114, 101, 32, 115, 111, …]This seemingly random mix of numbers is a good reminder that even thoughbytes created using theb prefix may look readable, they aren’t actually strings. In some cases,bytes may appear much less readable. Ignoring the differences betweenbytes and strings could cause a bunch of errors in your code that’ll lead you to some frustratingdebugging sessions.
Note: Python restrictsbytes literals to ASCII characters only, meaning that something likeb"é" would result in a syntax error. If you need bytes outside the ASCII range, then write them using escape codes, such asb"\xc3\xa9", or create them by calling thebytes() constructor.
You can also createbytes using Python’s built-inurllib package. It’s part ofPython’s standard library, so you won’t have to install it. It provides tools for working with URLs. One of its submodules,urllib.request, containsurlopen(), which allows you to open a URL and fetch its content. If you’ve never worked with this package before, you can check outPython’s urllib.request for HTTP Requests to learn more.
You can use any website of your choice for this guide. Here,https://example.com/ can be replaced with the site that you’ve chosen. When you use theurlopen() function, Python automatically returns the data asbytes, since data is transmitted in that raw format. The strings you see are simply a human-readable representation of these bytes.
Create a Python file nameddecode_bytes.py and add the following code:
decode_bytes.pyfromurllib.requestimporturlopenurl="https://example.com/"withurlopen(url)asresponse:raw_bytes:bytes=response.read()print("Bytes:",raw_bytes[:100])In the code snippet above, you importurlopen() fromurllib.request and assign a URL from which data will be fetched. You use thewith statement to ensure that once the data is read, the connection to the website is closed automatically.
The.read() method extracts the contents of the web page and returns it as abytes object, which you assign toraw_bytes. The call toprint() displays the first 100 bytes of the web page. When you run the code in yourterminal, you’ll get a result similar to the one below:
$pythondecode_bytes.pyBytes: b'<!doctype html><html lang="en"><head><title>Example Domain</title>⮑ <meta name="viewport" content="wid'Even though the output looks somewhat readable and you can see a familiarHTML structure, notice theb prefix before the quotes. This is used to identify abytes object, so it reminds you that what you’re seeing is still raw byte data.
The next logical step is to decode these bytes into a string so you can process them further or at least read them. Whatever method you choose, you now have raw byte data ready to be decoded into a human-readable string. You’ll learn how to do just that next.
Step 2: Decode the Bytes to a String Using Python’s.decode() Method
Once you’ve obtained abytes object, the next task is to decode it. This process involves converting raw bytes from step one into a readable string. In Python, thebytes.decode() method handles this task. It’s a built-in method that belongs to everybytes object and returns a string representation of the data.
In this practical example, you continue from the previous step by modifyingdecode_bytes.py:
decode_bytes.pyfromurllib.requestimporturlopenurl="https://example.com/"withurlopen(url)asresponse:raw_bytes:bytes=response.read()print("Bytes:",raw_bytes[:100])print("String:",raw_bytes[:100].decode())The.decode() method takes twooptional arguments:
| Argument | Default | Meaning |
|---|---|---|
encoding | "utf-8" | The encoding with which to decode the bytes |
errors | "strict" | The handling scheme to use for decoding errors |
Encodings help in mapping byte sequences to readable characters. Each encoding has a set of rules to determine how bytes represent letters, symbols, and other characters. Think of it like a specialized dictionary similar to a translation site or tool, except it translates the weird bytes of computers into a language humans can understand and use.
In the example above,.decode() usesUTF-8 encoding automatically since no encoding was specified. When the code runs, it converts the raw bytes fetched from the website into a readable HTML string, which can then be displayed or parsed further. Theb prefix seen in the earlier byte representation disappears, and the result becomes a standard string:
$pythondecode_bytes.pyBytes: b'<!doctype html><html lang="en"><head><title>Example Domain</title>…String: <!doctype html><html lang="en"><head><title>Example Domain</title>…If you’d rather decodebytes using another encoding, you can do so by passing it explicitly, such asraw_bytes.decode("latin-1") orraw_bytes.decode("utf-16"). You’ll really need this when you’re working with data whose source uses a specific format. The collapsible below briefly dives into an explanation of some encodings.
Encodings are like specialized dictionaries. There are different kinds available, such as UTF-8. If you choose UTF-8, it becomes the dictionary agreed upon between you and the computer. If you try decoding abytes object with a different encoding from what was used to encode it, then you’ll end up with garbled data. It’s like using a French dictionary to translate Russian. You’re bound to meet some very confused Russians.
If no encoding is specified, Python defaults to UTF-8, which is the standard encoding for almost all modern systems and web data. Each encoding defines its own rules for translating bytes into text. UTF-8, for example, can represent virtually every character used by humans, from English letters to emojis. It does this using one to four bytes per symbol, so it’s known as a variable-length encoding.
Another well-known encoding isASCII, which is short for the American Standard Code for Information Interchange. ASCII is one of the oldest and simplest encodings, representing letters, digits, and punctuation marks using numbers from 0 to 127. Because of its simplicity, it’s still widely recognized today, but it can represent plain English text only, not special characters, emojis, or scripts like Chinese or Arabic.
If you’re working with data that includes European accented characters or special punctuation marks, you might encounter Latin-1, also known as ISO-8859-1. This encoding expands upon ASCII by supporting 256 characters, enough to cover many Western European languages. It’s especially common in legacy systems and older web pages that haven’t transitioned to UTF-8.
There area number of standard encodings out there that you can check out. You can use any of these encodings by specifying them in the.decode() method.
Once thebytes are successfully decoded, you now have a string object that is a human-friendly version of what the machine processed earlier. In the next step, you’ll learn how to confirm that this conversion works as expected. You’ll also find out how to handle situations where decoding may not go as planned.
Step 3: Validate Decoded String and Handle Potential Decoding Errors
When decodingbytes into strings, things don’t always go as smoothly as expected. Not every sequence ofbytes can be neatly translated into readable text using the encoding that you choose. This is where it becomes crucial to validate your data and handle any potential errors. Lucky for you, Python’s.decode() method helps you handle these situations gracefully.
The.decode() method takes a second, optional argument callederrors. This defines what Python should do if it encounters a byte that doesn’t fit in nicely with the rules of the encoding specified. It tells Python what to do when something goes wrong during the decoding process.
By default, theerrors argument is set to"strict", which means Python will immediately let you know something is wrong if it encounters invalid byte data. This is actually a really safe way to handleexceptions, since it alerts you to real issues that might otherwise go unnoticed.
Suppose you have a few bytes that don’t actually represent valid UTF-8 data:
>>>b"d\xe9j\xe0 vu".decode("utf-8")Traceback (most recent call last):...UnicodeDecodeError:'utf-8' codec can't decode byte 0xe9 in position 1:⮑ invalid continuation bytePython raises aUnicodeDecodeError because the byte0xe9 is only allowed as a multi-byte sequence continuation in UTF-8. Sometimes, however, you may want to permit a few malformed bytes to avoid your program crashing. That’s where the other options for theerrors argument come in handy.
If you seterrors to"ignore", then Python will simply skip over any invalid bytes and decode the rest:
>>>b"d\xe9j\xe0 vu".decode("utf-8",errors="ignore")'dj vu'This means that your program will run successfully, but hidden errors may occur and escape your notice. This may be useful when you’re processing large amounts of text where perfect accuracy isn’t particularly crucial.
The"replace" option takes a gentler approach. Instead of ignoring invalid bytes entirely, it substitutes them with a replacement character, typically the Unicode replacement symbol—a question mark in a diamond shape:
>>>b"d\xe9j\xe0 vu".decode("utf-8",errors="replace")'d�j� vu'This makes it easy to spot where decoding failed while keeping the text mostly intact.
The"backslashreplace" option takes a different approach. Instead of dropping or replacing the bytes, it displays them asescape sequences, making debugging easier:
>>>b"d\xe9j\xe0 vu".decode("utf-8",errors="backslashreplace")'d\\xe9j\\xe0 vu'Using this mode, invalid bytes are shown in a form like\\xe9 or\\xe0, showing you exactly which data caused the issue.
The right error-handling strategy depends on your use case. For clean, well-structured data (like an API response or a trusted file),"strict" is best because it catches real problems early. For messy, unpredictable data like old archives,"ignore" or"replace" can help you recover what’s usable without halting your program. For debugging or data inspection,"backslashreplace" is perfect, since it preserves all bytes in a visible form.
Each encoding defines strict rules for how bytes should form characters, and if a sequence doesn’t fit, then you’re alerted to an error. The optionalerrors argument of the.decode() method allows for flexibility. It lets you decide whether to be strict with the rules, bend them a bit, or simply ignore them.
Conclusion
By this stage, you’ve successfully generated raw bytes, decoded them into readable strings, and handled the tricky edge cases that could appear in real-world data. Understanding these steps means you can confidently convert bytes to strings in Python, whether you’re dealing with web content, file I/O, or encoded messages. Furthermore, you can better handle any potential errors that arise as you converse with your computer.
Get Your Code:Click here to download the free sample code that you’ll use to convert bytes to strings in Python.
Frequently Asked Questions
Now that you have some experience with converting bytes to strings in Python, you can use the questions and answers below to check your understanding and recap what you’ve learned.
These FAQs are related to the most important concepts you’ve covered in this tutorial. Click theShow/Hide toggle beside each question to reveal the answer.
Call.decode() on thebytes object. It returns astr, using UTF-8 by default unless you pass a different character encoding.
Use UTF-8 for most modern text because it is the standard on the web and across platforms. If the data source declares a specific character set, pass that name to.decode().
Pass theerrors argument to.decode() to control failures. The default is"strict", but you can also opt for"ignore","replace", or"backslashreplace". Pick the mode that fits your data quality and debugging needs.
bytes holds raw 8-bit values, whilestr holds Unicode text. Convert from bytes to text with.decode() and from text to bytes with.encode().
Take the Quiz: Test your knowledge with our interactive “How to Convert Bytes to Strings in Python” quiz. You’ll receive a score upon completion to help you track your learning progress:
Interactive Quiz
How to Convert Bytes to Strings in PythonDecode bytes into readable strings in Python. Test your skills working with data from files, APIs, and databases.
🐍 Python Tricks 💌
Get a short & sweetPython Trick delivered to your inbox every couple of days. No spam ever. Unsubscribe any time. Curated by the Real Python team.

AboutAmanda Adoyi
Amanda is a Software Developer, writer and all-round nerd who loves to tinker with code and build projects in her free time. She also goes by Lonercode.
» More about AmandaMasterReal-World Python Skills With Unlimited Access to Real Python
Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:
MasterReal-World Python Skills
With Unlimited Access to Real Python
Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:
What Do You Think?
What’s your #1 takeaway or favorite thing you learned? How are you going to put your newfound skills to use? Leave a comment below and let us know.
Commenting Tips: The most useful comments are those written with the goal of learning from or helping out other students.Get tips for asking good questions andget answers to common questions in our support portal.
Looking for a real-time conversation? Visit theReal Python Community Chat or join the next“Office Hours” Live Q&A Session. Happy Pythoning!
Keep Learning
Keep reading Real Python by creating a free account or signing in:
Already have an account?Sign-In





