Building a Simple Web Client
A web client often begins with text: a message, a request target, or another piece of application data.
From Text to the Network
A web client often begins with text: a message, a request target, or another piece of application data. Text is useful to your Python program, but data sent across a network connection must travel as bytes. The complete journey is string → encode → bytes → network → bytes → decode → string. Encoding prepares text to leave the application, and decoding makes received bytes usable as text again.
Think of encode() and decode() as the two boundaries of network text handling. encode() changes a string into bytes before transmission. decode() changes received bytes back into a string after transmission.
Watching UTF-8 Expand Characters
Encoding is not a simple one-to-one replacement in which every character becomes exactly one byte. With UTF-8, Python examines each character and converts it to one or more bytes. The number of bytes depends on the character.
1
3The first result reflects the fact that A is a simple ASCII character and takes one byte in UTF-8. The second reflects the fact that € is a more complex Unicode character and takes three bytes. This difference matters when network data contains international text, special symbols, or emoji rather than only ordinary ASCII letters, numbers, and punctuation.
Writing and Reading Bytes
The usual way to convert a string into UTF-8 bytes is to call encode() on the string. Python also provides bytes literals using the b'' notation for text that is already written as a byte value. After bytes arrive from a connection, call decode() to turn them back into a string that the application can read.
message = "Hello"
message_bytes = message.encode()
fixed_bytes = b"Hello"
received_text = message_bytes.decode()- 1The program starts with the string Hello.
- 2Calling
encode()prepares that text as bytes for transmission. - 3The bytes literal creates byte data directly for the same simple text.
- 4Calling
decode()on the bytes reconstructs a Python string.
- message is text represented as a Python string.
encode()converts the string into UTF-8 bytes.- b"Hello" is a bytes literal.
decode()converts the bytes back into readable text.
Debugging the Boundary
Encoding problems become easier to locate when you ask which boundary failed. A sending problem occurs before the network receives the data: application text was not converted into bytes. A receiving problem occurs after bytes arrive: the program tried to interpret them with an unsuitable decoding choice. Inspect whether the value at each boundary is a string or bytes, then check the encoding used for the conversion.
Common mistake Trying to send a string directly instead of converting it to bytes.
What it looks likerequest_text = "€" connection.send(request_text)Why it failsText must be encoded into bytes before it can leave the computer and travel across the network.
Do this insteadrequest_bytes = request_text.encode() connection.send(request_bytes)Common mistake Trying to call decode() on text that is already a string.
What it looks likemessage = "Hello" message.decode()Why it failsdecode()is used to convert received bytes into a string, not to process a string that is already readable text.Do this insteadUse decode() on the received bytes value.
Common mistake Decoding received bytes with the wrong encoding.
What it looks likereceived_bytes.decode("some-other-encoding")Why it failsWhen the decoding choice does not match the encoding used for the data, international text can become garbled or an error can occur.
Do this insteadUse UTF-8 consistently when the data was encoded as UTF-8.
Common mistake Assuming every character becomes one byte.
What it looks liketext = "A€" text.encode()Why it failsUTF-8 uses a character-dependent transformation. A takes one byte, while € takes three bytes.
Do this insteadExpect the byte count to vary with the characters in the string.
Practice the Conversion
What do you think happens?
A program encodes A and € with UTF-8. Which character requires more bytes?
Reveal answer
€
A is a simple ASCII character and requires one byte in UTF-8. The Euro symbol is a more complex Unicode character and requires three bytes.
Write a short sequence that starts with the string "€", encodes it into UTF-8 bytes, and then decodes those bytes back into a string. Identify the value at each stage.
Hints
- Start with a normal quoted Python string.
- Call
encode()before the data is treated as network data. - Call
decode()on the resulting bytes.
Tracing One Message
Trace the value of the message "€" as it moves through a simple client.
- 1Start with text
The application begins with the string "€".
- 2Encode
Calling
encode()applies UTF-8 and transforms the character into three bytes. - 3Transmit
The resulting bytes are the form that travels across the network connection.
- 4Receive
The other side receives those bytes.
- 5Decode
Calling
decode()with the matching UTF-8 interpretation turns the bytes back into the readable string "€".
The message follows the cycle string → encode → bytes → network → bytes → decode → string.
What to Remember
- 1Network communication carries bytes, so encode application text before transmission.
- 2UTF-8 can represent one character with different numbers of bytes; A takes one byte, while € takes three.
- 3Use b'' notation when writing bytes literals directly.
- 4Use
decode()to turn received bytes back into a readable string. - 5When debugging, check both conversion boundaries: encoding before sending and decoding after receiving.
At a glance
- A Python string must be encoded into bytes before the data travels across a network connection.
- UTF-8 is character-dependent: A uses one byte, while € uses three bytes.
encode()converts strings to bytes, anddecode()converts received bytes back to strings.- Use matching UTF-8 encoding and decoding, especially when handling international text.
- Debug the point of failure by checking whether the program is sending text instead of bytes or decoding with the wrong encoding.