Exercise: Parse HTML Table and Save CSV
Bartosz Zaczyński RP Team on Aug. 20, 2026
@Gerhard Mehler thanks for reporting this, and your fix is right.
Passing HTML content straight to pd.read_html() was deprecated in pandas 2.1. On pandas 2.x it still worked, but with a warning:
FutureWarning: Passing literal html to 'read_html' is deprecated and will be removed
in a future version. To read from a literal string, wrap it in a 'StringIO' object.
In pandas 3.0 it was removed, so the argument now gets treated as a file path or URL. That’s where your OSError comes from, a FileNotFoundError with the entire page of HTML echoed back as the “filename,” which is why the message is so enormous.
Your io.StringIO version is the documented replacement. One shortcut: since response.read() already gives you bytes, you can skip the decode step and hand pandas an io.BytesIO instead.
import io
with urllib.request.urlopen(request) as response:
tables = pd.read_html(io.BytesIO(response.read()))
Both get you to the same place. The StringIO route is the one to remember for when you already have HTML sitting in a string.
I’ll get Grabbing Your Data updated, since it still shows the old call. Thanks for flagging it and for posting a working solution 🙂
Become a Member to join the conversation.
Gerhard Mehler on Aug. 14, 2026
In the tutorial “Grabbing your data,” the command presented is as follows:
This, however, creates a huge
OSError message. This is due to a new version of pandas. The solution is: