For simplicity's sake, let's consider writing instead of reading for now.

So when you use open() like say:

with open("test.dat", "wb") as f:
    f.write(b"Hello World")
    f.write(b"Hello World")
    f.write(b"Hello World")

After executing that a file called test.dat will be created, containing 3x Hello World. The data wont be kept in memory after it's written to the file (unless being kept by a name).

Now when you consider io.BytesIO() instead:

with io.BytesIO() as f:
    f.write(b"Hello World")
    f.write(b"Hello World")
    f.write(b"Hello World")

Which instead of writing the contents to a file, it's written to an in memory buffer. In other words a chunk of RAM. Essentially writing the following would be the equivalent:

buffer = b""
buffer += b"Hello World"
buffer += b"Hello World"
buffer += b"Hello World"

In relation to the example with the with statement, then at the end there would also be a del buffer.

The key difference here is optimization and performance. io.BytesIO is able to do some optimizations that makes it faster than simply concatenating all the b"Hello World" one by one.

Just to prove it here's a small benchmark:

  • Concat: 1.3529 seconds
  • BytesIO: 0.0090 seconds

import io
import time

begin = time.time()
buffer = b""
for i in range(0, 50000):
    buffer += b"Hello World"
end = time.time()
seconds = end - begin
print("Concat:", seconds)

begin = time.time()
buffer = io.BytesIO()
for i in range(0, 50000):
    buffer.write(b"Hello World")
end = time.time()
seconds = end - begin
print("BytesIO:", seconds)

Besides the performance gain, using BytesIO instead of concatenating has the advantage that BytesIO can be used in place of a file object. So say you have a function that expects a file object to write to. Then you can give it that in-memory buffer instead of a file.

The difference is that open("myfile.jpg", "rb") simply loads and returns the contents of myfile.jpg; whereas, BytesIO again is just a buffer containing some data.

Since BytesIO is just a buffer - if you wanted to write the contents to a file later - you'd have to do:

buffer = io.BytesIO()
# ...
with open("test.dat", "wb") as f:
    f.write(buffer.getvalue())

Also, you didn't mention a version; I'm using Python 3. Related to the examples: I'm using the with statement instead of calling f.close()

Answer from vallentin on Stack Overflow
🌐
Beautiful Soup
tedboy.github.io › python_stdlib › generated › generated › io.BytesIO.html
io.BytesIO — Python Standard Library
class io.BytesIO¶ · Create a buffered I/O implementation using an in-memory bytes buffer, ready for reading and writing.
🌐
Python Assets
pythonassets.com › posts › what-is-io-bytesio-useful-for
What Is `io.BytesIO` Useful For? | Python Assets
July 19, 2024 - io.BytesIO is a standard class that creates an in-memory binary stream, that is, it behaves like a file but exists only in our program's memory. This means you can read from and write to it just like a file, but without creating any actual files ...
Discussions

python - Difference between `open` and `io.BytesIO` in binary streams - Stack Overflow
I'm learning about working with streams in Python and I noticed that the IO docs say the following: The easiest way to create a binary stream is with open() with 'b' in the mode string: f = open(&... More on stackoverflow.com
🌐 stackoverflow.com
<class 'bytes'> vs <class '_io.BytesIO'>
These are completely different things. BytesIO is, as the name implies, an input/output object. It doesn't represent the bytes themselves, it represents a stream such as you might read from disk or receive over a network. bytes is the bytes themselves, ie the data that is received via a BytesIO. More on reddit.com
🌐 r/learnpython
4
1
December 1, 2022
Does BytesIO need to be closed.
From my understanding, probably not, but it can't hurt. The information below is based on this Google Groups chat from 2015, so it could be outdated. StringIO at the very least only use RAM, so at worst not closing them could cause a memory leak, but CPython takes care of it for you. Of course if you use PyPy or some other implementation, things are different. BytesIO is a bit different in that it uses file descriptors, which are in limited supply for each process, but I wouldn't expect you to need too many of these. Personally I'm something of a robustness enthusiast and prefer code that doesn't rely on implementation details over fast code, so I would recommend you to use context managers always, but this is subjective. More on reddit.com
🌐 r/learnpython
8
5
January 17, 2023
The need of closing io.StringIO/BytesIO?
Better for code generalisation. A function that gets a file like object, should act like it's any file, and then it can work well with both. More on reddit.com
🌐 r/learnpython
2
1
October 17, 2020
🌐
DigitalOcean
digitalocean.com › community › tutorials › python-io-bytesio-stringio
Python io.BytesIO and io.StringIO: Memory File Guide | DigitalOcean
August 3, 2022 - There are many ways in which we can use the io module to perform stream and buffer operations in Python. We will demonstrate a lot of examples here to prove the point. Let’s get started. Just like what we do with variables, data can be kept as bytes in an in-memory buffer when we use the io module’s Byte IO operations. Here is a sample program to demonstrate this: import io stream_str = io.BytesIO(b"JournalDev Python: \x00\x01") print(stream_str.getvalue())
Top answer
1 of 2
208

For simplicity's sake, let's consider writing instead of reading for now.

So when you use open() like say:

with open("test.dat", "wb") as f:
    f.write(b"Hello World")
    f.write(b"Hello World")
    f.write(b"Hello World")

After executing that a file called test.dat will be created, containing 3x Hello World. The data wont be kept in memory after it's written to the file (unless being kept by a name).

Now when you consider io.BytesIO() instead:

with io.BytesIO() as f:
    f.write(b"Hello World")
    f.write(b"Hello World")
    f.write(b"Hello World")

Which instead of writing the contents to a file, it's written to an in memory buffer. In other words a chunk of RAM. Essentially writing the following would be the equivalent:

buffer = b""
buffer += b"Hello World"
buffer += b"Hello World"
buffer += b"Hello World"

In relation to the example with the with statement, then at the end there would also be a del buffer.

The key difference here is optimization and performance. io.BytesIO is able to do some optimizations that makes it faster than simply concatenating all the b"Hello World" one by one.

Just to prove it here's a small benchmark:

  • Concat: 1.3529 seconds
  • BytesIO: 0.0090 seconds

import io
import time

begin = time.time()
buffer = b""
for i in range(0, 50000):
    buffer += b"Hello World"
end = time.time()
seconds = end - begin
print("Concat:", seconds)

begin = time.time()
buffer = io.BytesIO()
for i in range(0, 50000):
    buffer.write(b"Hello World")
end = time.time()
seconds = end - begin
print("BytesIO:", seconds)

Besides the performance gain, using BytesIO instead of concatenating has the advantage that BytesIO can be used in place of a file object. So say you have a function that expects a file object to write to. Then you can give it that in-memory buffer instead of a file.

The difference is that open("myfile.jpg", "rb") simply loads and returns the contents of myfile.jpg; whereas, BytesIO again is just a buffer containing some data.

Since BytesIO is just a buffer - if you wanted to write the contents to a file later - you'd have to do:

buffer = io.BytesIO()
# ...
with open("test.dat", "wb") as f:
    f.write(buffer.getvalue())

Also, you didn't mention a version; I'm using Python 3. Related to the examples: I'm using the with statement instead of calling f.close()

2 of 2
42

Using open opens a file on your hard drive. Depending on what mode you use, you can read or write (or both) from the disk.

A BytesIO object isn't associated with any real file on the disk. It's just a chunk of memory that behaves like a file does. It has the same API as a file object returned from open (with mode r+b, allowing reading and writing of binary data).

BytesIO (and it's close sibling StringIO which is always in text mode) can be useful when you need to pass data to or from an API that expect to be given a file object, but where you'd prefer to pass the data directly. You can load your input data you have into the BytesIO before giving it to the library. After it returns, you can get any data the library wrote to the file from the BytesIO using the getvalue() method. (Usually you'd only need to do one of those, of course.)

🌐
Python
docs.python.org › 3 › library › io.html
io — Core tools for working with streams
BytesIO provides or overrides these methods in addition to those from BufferedIOBase and IOBase:
🌐
ProgramCreek
programcreek.com › python › example › 1734 › io.BytesIO
Python Examples of io.BytesIO
def _deserialize(self, data, type_): if self.compress: # decompress the data if needed data = lz4.frame.decompress(data) if type_ == _NUMPY: # deserialize numpy arrays buf = io.BytesIO(data) data = np.load(buf) elif type_ == _PICKLE: # deserialize other python objects data = pickle.loads(data) else: # Otherwise we just return data as it is (bytes) pass return data ·
🌐
GeeksforGeeks
geeksforgeeks.org › python › stringio-and-bytesio-for-managing-data-as-file-object
Stringio And Bytesio For Managing Data As File Object - GeeksforGeeks
July 24, 2025 - In this example, a new BytesIO object named binary_buffer is created to emulate an in-memory file for binary data. The hexadecimal representation of the string "Hello" is written to the buffer using write. The content of the buffer is then retrieved as bytes with getvalue() and printed as the result. ... from io import BytesIO # Create a new BytesIO object binary_buffer = BytesIO() # Hexadecimal representation of "Hello" binary_buffer.write(b'\x48\x65\x6C\x6C\x6F') # Get the contents of the buffer as bytes result_bytes = binary_buffer.getvalue() # Print the result print(result_bytes)
Find elsewhere
🌐
Reddit
reddit.com › r/learnpython › vs
r/learnpython on Reddit: <class 'bytes'> vs <class '_io.BytesIO'>
December 1, 2022 -

Hello all,

I'm trying to wrap my head around the practical differences between:

<class 'bytes'> and <class '_io.BytesIO'>.

I read through the documentation:

https://docs.python.org/3/library/io.html?highlight=bytesio#binary-i-o

Binary I/O (also called buffered I/O) expects bytes-like objects and produces bytes objects. No encoding, decoding, or newline translation is performed. This category of streams can be used for all kinds of non-text data, and also when manual control over the handling of text data is desired.

It provides some examples:

The easiest way to create a binary stream is with open() with 'b' in the mode string:

and

f = io.BytesIO(b"some initial binary data: \x00\x01")

So I read all this, but so what? Why would you use the io.BytesIO data type over a standard bytes data type?

EDIT: Let me provide some additional context that I just discovered after reading the documentation on lxml.

https://lxml.de/parsing.html#parsing-html

I'm using the requests object and parsing the results with lxml. Here is the example code:

from io import BytesIO
from lxml import etree
#* etree - https://lxml.de/parsing.html
#? etree stands for element tree

import requests

#? Need to know concepts
#?  What are bytes
#?  HTTP status codes
#?  HTTP methods (GET. POST, PUT, DELETE)
#?  bytes - https://docs.python.org/3/library/stdtypes.html?highlight=bytes#bytes-objects

url = 'http://localhost'
#! The URL https://nostarch.com/ doesn't seem to work

resp = requests.get(url=url)
html_bytes = resp.content
parser = etree.HTMLParser()
content = etree.parse(BytesIO(html_bytes), parser=parser)

print(type(html_bytes))
print(type(BytesIO(html_bytes)))

for link in content.findall('//a'):
    print(f"{link.get('href')} -> {link.text}")

Kind regards

🌐
Pynerds
pynerds.com › io-bytesio-in-python
io.BytesIO in Python
Disclaimer: References to any specific company, product or services on this Site are not controlled by GoDaddy.com LLC and do not constitute or imply its association with or endorsement of third party advertisers
🌐
Python⇒Speed
pythonspeed.com › articles › bytesio-reduce-memory-usage
The surprising way to save memory with BytesIO
February 27, 2025 - If you need a file-like object that stores bytes in memory in Python, chances are you you’re using Pytho’s built-in io.BytesIO(). And since you’re already using an in-memory object, if your data is big enough you probably should try to save memory when reading that data back out.
🌐
AskPython
askpython.com › home › python io module: the complete practical reference
Python IO Module: The Complete Practical Reference - AskPython
February 16, 2023 - In this article, we learned about using the Python IO module, and it’s two main classes – io.BytesIO and io.StringIO for reading and writing byte and string data onto a buffer.
🌐
Medium
medium.com › @abhishekshaw020 › understanding-bytesio-handling-in-memory-files-like-a-pro-e1b767339468
Understanding BytesIO: Handling In-Memory Files Like a Pro | by Abhishek Shaw | Medium
March 31, 2025 - Let’s dive into some examples to see BytesIO in action! First, let’s create a simple in-memory file and write some text to it: from io import BytesIO # Create a new BytesIO object memory_file = BytesIO() # Write data (must be in bytes, so we encode it) memory_file.write(b"Hello, this is an in-memory file!") # Move back to the beginning of the file memory_file.seek(0) # Read the contents print(memory_file.read().decode()) # Output: Hello, this is an in-memory file!
🌐
GeeksforGeeks
geeksforgeeks.org › python › convert-from-_io-bytesio-to-a-bytes-like-object-in-python
Convert from '_Io.Bytesio' to a Bytes-Like Object in Python - GeeksforGeeks
July 23, 2025 - To convert from _io.BytesIO to a bytes-like object using the getvalue() method, we can directly obtain the byte data stored in the BytesIO buffer.
🌐
Python
wiki.python.org › moin › BytesIO
BytesIO - Python Wiki
April 28, 2011 - In Python 2.6, 2.7 and 3.x, the io module provides a standard BytesIO class.
🌐
Mellowd
mellowd.dev › python › using-io-bytesio
Using io.BytesIO() with Python - mellowd.dev
May 15, 2019 - In this example I’ll create a graph in matplotlib and just save to a virtual file. #!/usr/bin/env python3 import io import matplotlib import matplotlib.pyplot as plt import numpy as np t = np.arange(0.0, 2.0, 0.01) s = 1 + np.sin(2 * np.pi * t) fig, ax = plt.subplots() ax.plot(t, s) ax.set(xlabel='time (s)', ylabel='voltage (mV)', title='About as simple as it gets, folks') ax.grid() b = io.BytesIO() plt.savefig(b, format='png') plt.close()
🌐
Learning Machine
gallon.me › using-the-bytesio-class-in-python
Using the BytesIO Class in Python - Learning Machine
February 14, 2025 - February 14, 2025 by Corey, Cyrano in TIL tags: python · The io.BytesIO class in Python is an in-memory stream for binary data. It provides a file-like interface that lets you read and write bytes just like you would with a file, but all the ...
🌐
GitHub
github.com › python › cpython › blob › main › Modules › _io › bytesio.c
cpython/Modules/_io/bytesio.c at main · python/cpython
Returns True if the IO object can be seeked. ... Does nothing. ... Get a read-write view over the contents of the BytesIO object. ... Retrieve the entire contents of the BytesIO object. ... Always returns False. ... BytesIO objects are not connected to a TTY-like device. ... Current file position, an integer...
Author   python
🌐
YouTube
youtube.com › watch
How to use io.StringIO and io.BytesIO in Python? (Memory | IO | File | String | Bytes) - YouTube
How to use io.StringIO and io.BytesIO in Python? Learn an easy way to deal with file-like objects in memory.Medium: https://lynn-kwong.medium.com/how-to-use-...
Published   October 25, 2024
🌐
Andrew Wheeler
andrewpwheeler.com › 2022 › 11 › 02 › using-io-objects-in-python-to-read-data
Using IO objects in python to read data | Andrew Wheeler
November 2, 2022 - # Example 2, grabbing zipped contents import zipfile from io import BytesIO census_url = 'https://www2.census.gov/programs-surveys/acs/summary_file/2019/data/2019_5yr_Summary_FileTemplates.zip' req = requests.get(census_url) # Can use BytesIO for this content zf = zipfile.ZipFile(BytesIO(req.content))
🌐
CodeRivers
coderivers.org › blog › io-bytesio-python
Python's `io.BytesIO`: A Comprehensive Guide - CodeRivers
February 22, 2026 - In the world of Python programming, handling data streams is a common task. The io module provides a flexible framework for working with various types of I/O operations. Among its many classes, io.BytesIO stands out as a powerful tool for working with in-memory byte streams.