webtorrent/bittorrent-protocol is a UI-focused project on GitHub with 357 stars, written primarily in JavaScript. Simple, robust, BitTorrent peer wire protocol implementation
Snapshot summary built from the project's own GitHub metadata — there's no written TopGit review yet. The page will update automatically when a full review is published.
WHY NO REVIEW YET
TopGit writes full reviews for the most-starred, most-requested repositories. This page is a snapshot until then — see the READ ME tab for the original README in full.
Node.js implementation of the BitTorrent peer wire protocol.
The protocol is the main communication layer for BitTorrent file transfer.
Also works in the browser with browserify! This module is used
by WebTorrent.
install
npm install bittorrent-protocol
usage
The protocol is implemented as a duplex stream, so all you have to do is pipe to and
from it.
duplex streams
a.pipe(b).pipe(a)
(Images from the "harnessing streams" talk by substack.)
import Protocol from 'bittorrent-protocol'
import net from 'net'
net.createServer(socket => {
const wire = new Protocol()
// pipe to and from the protocol
socket.pipe(wire).pipe(socket)
wire.on('handshake', (infoHash, peerId) => {
// receive a handshake (infoHash and peerId are hex strings)
// lets emit a handshake of our own as well
wire.handshake('my info hash (hex)', 'my peer id (hex)')
})
wire.on('unchoke', () => {
console.log('peer is no longer choking us: ' + wire.peerChoking)
})
}).listen(6881)
methods
handshaking
Send and receive a handshake from the peer. This is the first message.
// send a handshake to the peer
wire.handshake(infoHash, peerId, { dht: true })
wire.on('handshake', (infoHash, peerId, extensions) => {
// receive a handshake (infoHash and peerId are hex strings)
console.log(extensions.dht) // supports DHT (BEP-0005)
console.log(extensions.extended) // supports extension protocol (BEP-0010)
})
For wire.handshake(), the infoHash and the peerId should be 20 bytes (hex-encoded string or Buffer).
choking
Check if you or the peer is choking.
wire.peerChoking // is the peer choking us?
wire.amChoking // are we choking the peer?
wire.on('choke', () => {
// the peer is now choking us
})
wire.on('unchoke', () => {
// peer is no longer choking us
})
interested
See if you or the peer is interested.
wire.peerInterested // is the peer interested in us?
wire.amInterested // are we interested in the peer?
wire.on('interested', () => {
// peer is now interested
})
wire.on('uninterested', () => {
// peer is no longer interested
})
bitfield
Exchange piece information with the peer.
// send a bitfield to the peer
wire.bitfield(buffer)
wire.on('bitfield', bitfield => {
// bitfield received from the peer
})
// send a have message indicating that you have a piece
wire.have(pieceIndex)
wire.on('have', pieceIndex => {
// peer has sent you a have message
})
You can always see which pieces the peer has
wire.peerPieces.get(i) // returns true if peer has piece i
wire.peerPieces is a BitField, see docs.
requests
Send and respond to requests for pieces.
// request a block from a peer
wire.request(pieceIndex, offset, length, (err, block) => {
if (err) {
// there was an error (peer has started choking us etc)
return
}
// got block
})
// cancel a request to a peer
wire.cancel(pieceIndex, offset, length)
// receive a request from a peer
wire.on('request', (pieceIndex, offset, length, callback) => {
// ... read block ...
callback(null, block) // respond back to the peer
})
wire.requests // list of requests we currently have pending {piece, offset, length}
wire.peerRequests // list of requests the peer currently have pending {piece, offset, length}
You can set a request timeout if you want to.
wire.setTimeout(5000) // head request should take a most 5s to finish
If the timeout is triggered the request callback is called with an error and a timeout
event is emitted.
dht and port
You can set the extensions flag dht in the handshake to true if you participate in
the torrent dht. Afterwards you can send your dht port.
// send your port to the peer
wire.port(dhtPort)
wire.on('port', dhtPort => {
// peer has sent a port to us
})
You can check to see if the peer supports extensions.
You can enable the keep-alive ping (triggered every 60s).
// starts the keep alive
wire.setKeepAlive(true)
wire.on('keep-alive', () => {
// peer sent a keep alive - just ignore it
})
protocol encryption (RC4)
Message stream encryption (RC4) is used automatically when both peers support it. The
cipher can use Node's built-in crypto.createCipheriv('rc4') when available (~2-3x faster),
or falls back to an inline JavaScript implementation.
Check at runtime which path is in use:
Wire.nativeRC4 // true if native RC4 is available, false if using JS fallback
This is useful for downstream consumers that want to decide whether to enable encryption
based on performance characteristics. For example, nativeRC4 is false by default on
Node 17+ (requires --openssl-legacy-provider).
fast extension (BEP 6)
This module has built-in support for the
BitTorrent Fast Extension (BEP 6).
The Fast Extension introduces several messages to make the protocol more efficient:
have-none, have-all, suggest, reject, and allowed-fast.
wire.handshake(infoHash, peerId, { fast: true })
wire.hasFast // true if Fast Extension is available, required to call the following methods
wire.haveNone() // instead of wire.bitfield(buffer) with an all-zero buffer
wire.on('have-none', () => {
// instead of bitfield with an all-zero buffer
})
wire.haveAll() // instead of wire.bitfield(buffer) with an all-one buffer
wire.on('have-all', () => {
// instead of bitfield with an all-one buffer
})
wire.suggest(pieceIndex) // suggest requesting a piece to the peer
wire.on('suggest', (pieceIndex) => {
// peer suggests requesting piece
})
wire.on('allowed-fast', (pieceIndex) => {
// piece may be obtained from peer while choked
})
wire.peerAllowedFastSet // list of allowed-fast pieces
// Note rejection is handled automatically on choke or request error
wire.reject(pieceIndex, offset, length) // reject a request
wire.on('reject', (pieceIndex, offset, length) => {
// peer rejected a request
})
extension protocol (BEP 10)
This module has built-in support for the
BitTorrent Extension Protocol (BEP 10).
The intention of BEP 10 is to provide a simple and thin transport for extensions to the
bittorrent protocol. Most extensions to the protocol use BEP 10 so they can add new
features to the protocol without interfering with the standard bittorrent protocol or
clients that don't support the new extension.
An example of a BitTorrent extension that uses BEP 10 is
ut_metadata (BEP 9), the extension that
allows magnet uris to work.
wire.extended(code, buffer)
This package, bittorrent-protocol, also provides an extension API to make it easy to
add extensions to this module using the "extension protocol" (BEP 10). For example, to
support ut_metadata (BEP 9), you need only install the
ut_metadata npm module and call wire.use().
See the Extension API section for more information.
transfer stats
Check how many bytes you have uploaded and download, and current speed
wire.uploaded // number of bytes uploaded
wire.downloaded // number of bytes downloaded
wire.uploadSpeed() // upload speed - bytes per second
wire.downloadSpeed() // download speed - bytes per second
wire.on('download', numberOfBytes => {
...
})
wire.on('upload', numberOfBytes => {
...
})
extension api
This package supports a simple extension API so you can extend the default protocol
functionality with common protocol extensions like ut_metadata (magnet uris).
Here are the bittorrent-protocol extensions that we know about:
ut_metadata - Extension for Peers to Send Metadata Files (BEP 9)
ut_pex - Extension for Peer Discovery (PEX)
Add yours here! Send a pull request!
In short, an extension can register itself with at a certain name, which will be added to
the extended protocol handshake sent to the remote peer. Extensions can also hook events
like 'handshake' and 'extended'. To use an extension, simply require it and call
wire.use().
Here is an example of the ut_metadata extension being used with
bittorrent-protocol:
import Protocol from 'bittorrent-protocol'
import net from 'net'
import ut_metadata from 'ut_metadata'
net.createServer(socket => {
const wire = new Protocol()
socket.pipe(wire).pipe(socket)
// initialize the extension
wire.use(ut_metadata())
// all `ut_metadata` functionality can now be accessed at wire.ut_metadata
// ask the peer to send us metadata
wire.ut_metadata.fetch()
// 'metadata' event will fire when the metadata arrives and is verified to be correct!
wire.ut_metadata.on('metadata', metadata => {
// got metadata!
// Note: the event will not fire if the peer does not support ut_metadata, if they
// don't have metadata yet either, if they repeatedly send invalid data, or if they
// simply don't respond.
})
// optionally, listen to the 'warning' event if you want to know that metadata is
// probably not going to arrive for one of the above reasons.
wire.ut_metadata.on('warning', err => {
console.log(err.message)
})
// handle handshake
wire.on('handshake', (infoHash, peerId) => {
// receive a handshake (infoHash and peerId are hex strings)
wire.handshake(new Buffer('my info hash'), new Buffer('my peer id'))
})
}).listen(6881)
If you want to write your own extension, take a look at the
ut_metadata index.js file
to see how it's done.
license
MIT. Copyright (c) Feross Aboukhadijeh, Mathias Buus, and WebTorrent, LLC.
How active is development on webtorrent/bittorrent-protocol?
The most recent commit recorded on webtorrent/bittorrent-protocol was 13 days ago, based on the GitHub push timestamp. The repository has 75 forks — one of the better signals of community interest.
How many stars does webtorrent/bittorrent-protocol have?
webtorrent/bittorrent-protocol has 357 GitHub stars — refresh the page for the live number, or check github.com/webtorrent/bittorrent-protocol. TopGit mirrors GitHub's count but does not claim minute-by-minute accuracy.
Is webtorrent/bittorrent-protocol open source?
Yes — webtorrent/bittorrent-protocol ships under the MIT license, which makes its source code freely readable (and, depending on license terms, forkable and reusable). Source: github.com/webtorrent/bittorrent-protocol.
What else is in the Frontend space?
webtorrent/bittorrent-protocol is tracked by TopGit under the Frontend category, alongside 8 GitHub-tagged topics. Trending and Topics pages list peer repositories of comparable stars and language.
What topics is webtorrent/bittorrent-protocol associated with?
GitHub's repository topics for webtorrent/bittorrent-protocol: "bittorrent", "browser", "javascript", "nodejs", "p2p", "protocol", "torrent", "webtorrent". TopGit's editorial category is Frontend.
Where can I see webtorrent/bittorrent-protocol in action?
The project maintains a homepage at https://webtorrent.io. The README tab on this page also usually contains screenshots and a quickstart.
Where do I read more about webtorrent/bittorrent-protocol?
This TopGit page is a snapshot — the READ ME tab shows the project's own README content (links stripped, images preserved). The GitHub repository at github.com/webtorrent/bittorrent-protocol is the definitive source.
Read full README in the tab above.
Is bittorrent-protocol worth your time?
ChatGPT, Claude and Perplexity can all read this page. Ask one of them what it makes of bittorrent-protocol.