How to URL-Encode Torrent Info Hashes for Trackers

When a BitTorrent client communicates with an HTTP-based tracker via a GET request, it must send the torrent’s unique info hash as a parameter in the query string. Because the info hash is a raw sequence of binary bytes rather than a plain text string, it contains arbitrary byte values that are invalid or reserved in standard URLs. To transmit this data correctly without corruption, clients convert the raw binary hash into an ASCII-compatible format using standard percent-encoding (URL-encoding) rules.

The Raw Binary Hash vs. Hex Strings

A common mistake in BitTorrent development is attempting to URL-encode the 40-character hexadecimal representation of a hash. BitTorrent trackers do not expect a hexadecimal string; they require the raw binary hash:

When communicating with the tracker via the ?info_hash= query parameter, the client must encode the 20 or 32 individual bytes directly, not the human-readable 40 or 64 hex characters.

Standard URL-Encoding Rules

The BitTorrent protocol follows standard RFC 3986 URI encoding rules for the raw bytes:

  1. Unreserved Characters: Bytes that correspond to the ASCII values of alphanumeric characters (a-z, A-Z, 0-9) and the four unreserved symbols (-, _, ., ~) may be transmitted directly as literal characters.
  2. Reserved and Non-Printable Bytes: Any byte value that falls outside the unreserved character set—including control characters, whitespace, high-ASCII bytes (0x80 through 0xFF), and URL-reserved delimiters (such as &, =, ?, /)—must be encoded as % followed by two hexadecimal digits (e.g., 0x1F becomes %1F).

Step-by-Step Encoding Process

To illustrate the encoding process:

  1. Obtain the 20-byte hash: Suppose the first four bytes of a SHA-1 hash in hexadecimal are 0x41, 0x0A, 0x2E, and 0xFF.
  2. Evaluate byte by byte:
    • 0x41 corresponds to ASCII character A (unreserved) \(\rightarrow\) encoded as A (or %41).
    • 0x0A corresponds to a non-printable Line Feed \(\rightarrow\) encoded as %0A.
    • 0x2E corresponds to ASCII character . (unreserved) \(\rightarrow\) encoded as ..
    • 0xFF is outside standard ASCII \(\rightarrow\) encoded as %FF.
  3. Assemble the result: The four-byte segment becomes A%0A.%FF.

The complete URL-encoded info hash string typically ends up between 20 and 60 characters in length, depending on how many bytes map to unreserved ASCII characters versus percent-encoded sequences.

Important Implementation Considerations