Concepts / Building a Simple Web Client

Building a Simple Web Client

A web client often begins with text: a message, a request target, or another piece of application data.

  • Programming

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.

Python stringtext to sendencode()UTF-8 transformationBytesdata for transmissionNetwork connectiontransmitted bytesReceived bytesdata from connectiondecode()UTF-8 interpretationPython stringreadable texttextUTF-8sendreceiveUTF-8text
How does text move from a Python string into transmitted bytes and back into readable text?
Key point

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.

Astring character1 byteUTF-8 result€string character3 bytesUTF-8 resultencode()encode()
How does the string A become one byte while the Euro symbol becomes three bytes?
python
Output
1
3

The 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.

Code walkthrough
message = "Hello"
message_bytes = message.encode()

fixed_bytes = b"Hello"

received_text = message_bytes.decode()
  1. 1
    The program starts with the string Hello.
  2. 2
    Calling encode() prepares that text as bytes for transmission.
  3. 3
    The bytes literal creates byte data directly for the same simple text.
  4. 4
    Calling 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.
Received bytesnetwork resultdecode()UTF-8 interpretationReadable stringapplication textbytestext
What happens to transmitted bytes when decode() converts them 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.

Python stringapplication dataEncode before sendingbytes ready?Sending errorstring crossed the boundaryNetwork transmissionbytesDecode with UTF-8encoding matches?Decoding errorgarbled text or errorReadable stringapplication textpreparenoyesreceivenoyes
Where in the data flow does an error occur when code sends a string directly or decodes with the wrong encoding?
  • Common mistake

    Trying to send a string directly instead of converting it to bytes.

    What it looks like
    request_text = "€"
    connection.send(request_text)
    Why it fails

    Text must be encoded into bytes before it can leave the computer and travel across the network.

    Do this instead
    request_bytes = request_text.encode()
    connection.send(request_bytes)
  • Common mistake

    Trying to call decode() on text that is already a string.

    What it looks like
    message = "Hello"
    message.decode()
    Why it fails

    decode() is used to convert received bytes into a string, not to process a string that is already readable text.

    Do this instead

    Use decode() on the received bytes value.

  • Common mistake

    Decoding received bytes with the wrong encoding.

    What it looks like
    received_bytes.decode("some-other-encoding")
    Why it fails

    When the decoding choice does not match the encoding used for the data, international text can become garbled or an error can occur.

    Do this instead

    Use UTF-8 consistently when the data was encoded as UTF-8.

  • Common mistake

    Assuming every character becomes one byte.

    What it looks like
    text = "A€"
    text.encode()
    Why it fails

    UTF-8 uses a character-dependent transformation. A takes one byte, while € takes three bytes.

    Do this instead

    Expect 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?

  • A

  • €

  • They require the same number of bytes

Reveal answer
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.

EASY

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.
Worked example

Tracing One Message

Trace the value of the message "€" as it moves through a simple client.

  1. 1
    Start with text

    The application begins with the string "€".

  2. 2
    Encode

    Calling encode() applies UTF-8 and transforms the character into three bytes.

  3. 3
    Transmit

    The resulting bytes are the form that travels across the network connection.

  4. 4
    Receive

    The other side receives those bytes.

  5. 5
    Decode

    Calling decode() with the matching UTF-8 interpretation turns the bytes back into the readable string "€".

Result

The message follows the cycle string → encode → bytes → network → bytes → decode → string.

What to Remember

  1. 1
    Network communication carries bytes, so encode application text before transmission.
  2. 2
    UTF-8 can represent one character with different numbers of bytes; A takes one byte, while € takes three.
  3. 3
    Use b'' notation when writing bytes literals directly.
  4. 4
    Use decode() to turn received bytes back into a readable string.
  5. 5
    When 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, and decode() 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.

Related concepts

More concepts starting with B