Skip to content
A work-in-progress BitTorrent client written in Haskell.
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.


made at Recurse Center

HTorrent is a work-in-progress BitTorrent client written in Haskell. This was built as a learning exercise. It is not intended for use in production.


NOTE: HTorrent uses pwrite & pread under the hood to allow for parallel reads of tracker content. For this reason, only POSIX system are supported (sorry windows).

Binary Install (Mac)

  1. Run wget && chmod +x ./htorrent
  2. Run htorrent --help for usage instructions

Binary Install (Linux)

  1. Run wget && chmod +x ./htorrent
  2. Run htorrent --help for usage instructions

Stack install

  1. Install / make sure you have git and Stack and that binaries installed via stack install are reachable in your path.
  2. Run git clone && cd htorrent
  3. Run make test, all tests should pass. If they do not, please open an issue.
  4. Run make install
  5. Run htorrent --help for usage instructions


I built this as an exercise to learn Haskell (which had only minimal exposure to prior to this project) and use it to build a non trivial project from scratch. I also wanted to learn about parsing, bit manipulation, socket programming, property based testing, how to build efficient concurrent / parallel programs in Haskell, and how to profile & optimize Haskell programs.



  • Able to resume partial download with no duplicate work
  • Accepting incoming connections from peers
  • Computes & sends initial bitfield message to peers
  • Hash checking to verify that each piece received is valid
  • Is able to seed & leach from itself
  • Never downloads the same piece twice.
  • Only requests a piece from a peer if it already knows the peer has the piece.
  • Parallel leaching & seeding
  • Property & unit tests for parsing logic
  • Reading single torrent
  • Tracks if peer is choking and does not request pieces if peer is choking
  • Tracks which pieces each peer has by parsing have & bitfield messages.
  • Support for large single files
  • Signal handling for Ctrl-C & clean shutdown
  • Refactor Parser module to use attoparsec as profiling discovered explicit fold / unfold parser to be the current bottleneck

TODO (next to be implemented):

  • Publishing have messages to all peers as pieces complete
  • Provide visualization (presentation mode)
  • Fix issue where if the tracker server doesn't exist, it does not just blow up. Report back HTTP Call 'http call' to tracker server 'tracker server url'
  • Add CI/CD

Not (yet?) Implemented:

  • Asking for rarest blocks first.
  • Close connections with peers when you have everything and they have everything
  • Convert cabal file into an hpack file
  • DHT support
  • Endgame - asking for the same pieces from multiple peers when number of outstanding pieces is lower than number of peers which can serve them.
  • Game theory algorithm for deciding when to choke peers (currently peers are always unchoked)
  • Only sending interested messages when the peer actually has pieces HTorrent needs (currently HTorrent is always interested in all peers)
  • Property / integration tests for bittorrent FSM itself
  • Property tests for RPC parser
  • Provide ability to get debug logging
  • Provide option to exit on completion
  • Requesting tracker for more peers when HTorrent runs low on peers
  • Resolve all compiler warnings
  • Support for WebSeeds
  • Support for multiple torrents
  • Support for multiple trackers
  • Support for specifying the download directory (currently it just downloads the file in the current directory)
  • Torrents which contain more than one file
  • Track download statistics to report back to tracker
  • Tracking & reporting total download & upload rate
  • UDP Tracker Protocol


  • PRs welcome! If you would like to add/suggest a feature, please feel free to submit a PR/issue.
You can’t perform that action at this time.