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:
- BitTorrent v1 (SHA-1): 20 raw bytes.
- BitTorrent v2 (SHA-256): 32 raw bytes.
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:
- 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. - Reserved and Non-Printable Bytes: Any byte value
that falls outside the unreserved character set—including control
characters, whitespace, high-ASCII bytes (
0x80through0xFF), and URL-reserved delimiters (such as&,=,?,/)—must be encoded as%followed by two hexadecimal digits (e.g.,0x1Fbecomes%1F).
Step-by-Step Encoding Process
To illustrate the encoding process:
- Obtain the 20-byte hash: Suppose the first four
bytes of a SHA-1 hash in hexadecimal are
0x41,0x0A,0x2E, and0xFF. - Evaluate byte by byte:
0x41corresponds to ASCII characterA(unreserved) \(\rightarrow\) encoded asA(or%41).0x0Acorresponds to a non-printable Line Feed \(\rightarrow\) encoded as%0A.0x2Ecorresponds to ASCII character.(unreserved) \(\rightarrow\) encoded as..0xFFis outside standard ASCII \(\rightarrow\) encoded as%FF.
- 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
- Literal
%20vs.+: Space bytes (0x20) must always be encoded as%20. Unlike standard HTML form data (application/x-www-form-urlencoded), using+to represent0x20can cause trackers to decode the character as a literal plus sign (0x2B), corrupting the hash. - Hex Case Sensitivity: While hexadecimal digits in
percent-encoding (e.g.,
%0avs%0A) are technically case-insensitive per RFC 3986, uppercase hexadecimal letters are standard and expected by most BitTorrent tracker implementations. - Double Encoding Pitfalls: Standard high-level HTTP client libraries often assume query parameters are UTF-8 text and may attempt to encode or re-encode strings automatically. To avoid corrupted hashes, developers must ensure the HTTP client treats the query parameters as raw binary data or pass the pre-encoded ASCII string directly without secondary transformation.