{"id":13482075,"url":"https://github.com/webtorrent/bittorrent-protocol","last_synced_at":"2025-12-29T23:45:57.418Z","repository":{"id":11745105,"uuid":"14274070","full_name":"webtorrent/bittorrent-protocol","owner":"webtorrent","description":"Simple, robust, BitTorrent peer wire protocol implementation","archived":false,"fork":false,"pushed_at":"2024-10-26T21:24:52.000Z","size":331,"stargazers_count":346,"open_issues_count":9,"forks_count":71,"subscribers_count":19,"default_branch":"master","last_synced_at":"2024-10-30T01:47:58.451Z","etag":null,"topics":["bittorrent","browser","javascript","nodejs","p2p","protocol","torrent","webtorrent"],"latest_commit_sha":null,"homepage":"https://webtorrent.io","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/webtorrent.png","metadata":{"funding":{"github":["webtorrent","feross"]},"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2013-11-10T09:46:03.000Z","updated_at":"2024-10-09T21:45:47.000Z","dependencies_parsed_at":"2024-01-14T01:27:07.794Z","dependency_job_id":"73ba9ae0-cce2-4b55-af7e-6c71ee38db68","html_url":"https://github.com/webtorrent/bittorrent-protocol","commit_stats":{"total_commits":346,"total_committers":23,"mean_commits":"15.043478260869565","dds":"0.32947976878612717","last_synced_commit":"f17c7aaa925b9f34d351e4a844533d1967aaf354"},"previous_names":["feross/bittorrent-protocol"],"tags_count":97,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webtorrent%2Fbittorrent-protocol","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webtorrent%2Fbittorrent-protocol/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webtorrent%2Fbittorrent-protocol/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webtorrent%2Fbittorrent-protocol/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/webtorrent","download_url":"https://codeload.github.com/webtorrent/bittorrent-protocol/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":222252081,"owners_count":16955962,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bittorrent","browser","javascript","nodejs","p2p","protocol","torrent","webtorrent"],"created_at":"2024-07-31T17:00:58.768Z","updated_at":"2025-12-17T09:50:13.649Z","avatar_url":"https://github.com/webtorrent.png","language":"JavaScript","readme":"# bittorrent-protocol [![travis][travis-image]][travis-url] [![npm][npm-image]][npm-url] [![downloads][downloads-image]][downloads-url] [![javascript style guide][standard-image]][standard-url]\n\n[travis-image]: https://img.shields.io/travis/webtorrent/bittorrent-protocol/master.svg\n[travis-url]: https://travis-ci.org/webtorrent/bittorrent-protocol\n[npm-image]: https://img.shields.io/npm/v/bittorrent-protocol.svg\n[npm-url]: https://npmjs.org/package/bittorrent-protocol\n[downloads-image]: https://img.shields.io/npm/dm/bittorrent-protocol.svg\n[downloads-url]: https://npmjs.org/package/bittorrent-protocol\n[standard-image]: https://img.shields.io/badge/code_style-standard-brightgreen.svg\n[standard-url]: https://standardjs.com\n\n### Simple, robust, BitTorrent wire protocol implementation\n\nNode.js implementation of the [BitTorrent peer wire protocol](https://wiki.theory.org/BitTorrentSpecification#Peer_wire_protocol_.28TCP.29).\nThe protocol is the main communication layer for BitTorrent file transfer.\n\nAlso works in the browser with [browserify](http://browserify.org/)! This module is used\nby [WebTorrent](http://webtorrent.io).\n\n## install\n\n```\nnpm install bittorrent-protocol\n```\n\n## usage\n\nThe protocol is implemented as a **duplex stream**, so all you have to do is pipe to and\nfrom it.\n\nduplex streams | a.pipe(b).pipe(a)\n---- | ---\n![duplex streams](https://raw.github.com/substack/lxjs-stream-examples/master/images/duplex_streams.png) | ![a.pipe(b).pipe(a)](https://raw.github.com/substack/lxjs-stream-examples/master/images/a_pipe_b_pipe_a.png)\n\n(Images from the [\"harnessing streams\"](https://github.com/substack/lxjs-stream-examples/blob/master/slides.markdown) talk by substack.)\n\n```js\nimport Protocol from 'bittorrent-protocol'\nimport net from 'net'\n\nnet.createServer(socket =\u003e {\n\tconst wire = new Protocol()\n\n\t// pipe to and from the protocol\n\tsocket.pipe(wire).pipe(socket)\n\n\twire.on('handshake', (infoHash, peerId) =\u003e {\n    // receive a handshake (infoHash and peerId are hex strings)\n\n\t\t// lets emit a handshake of our own as well\n\t\twire.handshake('my info hash (hex)', 'my peer id (hex)')\n\t})\n\n\twire.on('unchoke', () =\u003e {\n\t\tconsole.log('peer is no longer choking us: ' + wire.peerChoking)\n\t})\n}).listen(6881)\n```\n\n## methods\n\n### handshaking\n\nSend and receive a handshake from the peer. This is the first message.\n\n```js\n// send a handshake to the peer\nwire.handshake(infoHash, peerId, { dht: true })\nwire.on('handshake', (infoHash, peerId, extensions) =\u003e {\n\t// receive a handshake (infoHash and peerId are hex strings)\n  console.log(extensions.dht) // supports DHT (BEP-0005)\n  console.log(extensions.extended) // supports extension protocol (BEP-0010)\n})\n```\n\nFor `wire.handshake()`, the `infoHash` and the `peerId` should be 20 bytes (hex-encoded `string` or `Buffer`).\n\n### choking\n\nCheck if you or the peer is choking.\n\n```js\nwire.peerChoking // is the peer choking us?\nwire.amChoking // are we choking the peer?\n\nwire.on('choke', () =\u003e {\n\t// the peer is now choking us\n})\nwire.on('unchoke', () =\u003e {\n\t// peer is no longer choking us\n})\n```\n\n### interested\n\nSee if you or the peer is interested.\n\n```js\nwire.peerInterested // is the peer interested in us?\nwire.amInterested // are we interested in the peer?\n\nwire.on('interested', () =\u003e {\n\t// peer is now interested\n})\nwire.on('uninterested', () =\u003e {\n\t// peer is no longer interested\n})\n```\n\n### bitfield\n\nExchange piece information with the peer.\n\n```js\n// send a bitfield to the peer\nwire.bitfield(buffer)\nwire.on('bitfield', bitfield =\u003e {\n\t// bitfield received from the peer\n})\n\n// send a have message indicating that you have a piece\nwire.have(pieceIndex)\nwire.on('have', pieceIndex =\u003e {\n\t// peer has sent you a have message\n})\n```\n\nYou can always see which pieces the peer has\n\n```js\nwire.peerPieces.get(i) // returns true if peer has piece i\n```\n\n`wire.peerPieces` is a `BitField`, see [docs](https://www.npmjs.org/package/bitfield).\n\n### requests\n\nSend and respond to requests for pieces.\n\n```js\n// request a block from a peer\nwire.request(pieceIndex, offset, length, (err, block) =\u003e {\n\tif (err) {\n\t\t// there was an error (peer has started choking us etc)\n\t\treturn\n\t}\n\t// got block\n})\n\n// cancel a request to a peer\nwire.cancel(pieceIndex, offset, length)\n\n// receive a request from a peer\nwire.on('request', (pieceIndex, offset, length, callback) =\u003e {\n\t// ... read block ...\n\tcallback(null, block) // respond back to the peer\n})\n\nwire.requests     // list of requests we currently have pending {piece, offset, length}\nwire.peerRequests // list of requests the peer currently have pending {piece, offset, length}\n```\n\nYou can set a request timeout if you want to.\n\n```js\nwire.setTimeout(5000) // head request should take a most 5s to finish\n```\n\nIf the timeout is triggered the request callback is called with an error and a `timeout`\nevent is emitted.\n\n### dht and port\n\nYou can set the extensions flag `dht` in the handshake to `true` if you participate in\nthe torrent dht. Afterwards you can send your dht port.\n\n```js\n// send your port to the peer\nwire.port(dhtPort)\nwire.on('port', dhtPort =\u003e {\n\t// peer has sent a port to us\n})\n```\n\nYou can check to see if the peer supports extensions.\n\n```js\nwire.peerExtensions.dht // supports DHT (bep_0005)\nwire.peerExtensions.extended // supports extended messages (bep_0005)\n```\n\n### keep-alive\n\nYou can enable the keep-alive ping (triggered every 60s).\n\n```js\n// starts the keep alive\nwire.setKeepAlive(true)\nwire.on('keep-alive', () =\u003e {\n\t// peer sent a keep alive - just ignore it\n})\n```\n### fast extension (BEP 6)\n\nThis module has built-in support for the\n[BitTorrent Fast Extension (BEP 6)](http://www.bittorrent.org/beps/bep_0006.html).\n\nThe Fast Extension introduces several messages to make the protocol more efficient:\nhave-none, have-all, suggest, reject, and allowed-fast.\n\n```js\nwire.handshake(infoHash, peerId, { fast: true })\n\nwire.hasFast // true if Fast Extension is available, required to call the following methods\n\nwire.haveNone() // instead of wire.bitfield(buffer) with an all-zero buffer\nwire.on('have-none', () =\u003e {\n  // instead of bitfield with an all-zero buffer\n})\n\nwire.haveAll() // instead of wire.bitfield(buffer) with an all-one buffer\nwire.on('have-all', () =\u003e {\n  // instead of bitfield with an all-one buffer\n})\n\nwire.suggest(pieceIndex) // suggest requesting a piece to the peer\nwire.on('suggest', (pieceIndex) =\u003e {\n  // peer suggests requesting piece\n})\n\nwire.on('allowed-fast', (pieceIndex) =\u003e {\n  // piece may be obtained from peer while choked\n})\n\nwire.peerAllowedFastSet // list of allowed-fast pieces\n\n// Note rejection is handled automatically on choke or request error\nwire.reject(pieceIndex, offset, length) // reject a request\nwire.on('reject', (pieceIndex, offset, length) =\u003e {\n  // peer rejected a request\n})\n```\n\n### extension protocol (BEP 10)\n\nThis module has built-in support for the\n[BitTorrent Extension Protocol (BEP 10)](http://www.bittorrent.org/beps/bep_0010.html).\n\nThe intention of BEP 10 is to provide a simple and thin transport for extensions to the\nbittorrent protocol. Most extensions to the protocol use BEP 10 so they can add new\nfeatures to the protocol without interfering with the standard bittorrent protocol or\nclients that don't support the new extension.\n\nAn example of a BitTorrent extension that uses BEP 10 is\n[ut_metadata](http://www.bittorrent.org/beps/bep_0009.html) (BEP 9), the extension that\nallows magnet uris to work.\n\n```js\nwire.extended(code, buffer)\n```\n\nThis package, **bittorrent-protocol**, also provides an extension API to make it easy to\nadd extensions to this module using the \"extension protocol\" (BEP 10). For example, to\nsupport ut_metadata (BEP 9), you need only install the\n[ut_metadata](https://www.npmjs.com/package/ut_metadata) npm module and call `wire.use()`.\nSee the [Extension API](#extension-api) section for more information.\n\n### transfer stats\n\nCheck how many bytes you have uploaded and download, and current speed\n\n```js\nwire.uploaded // number of bytes uploaded\nwire.downloaded // number of bytes downloaded\n\nwire.uploadSpeed() // upload speed - bytes per second\nwire.downloadSpeed() // download speed - bytes per second\n\nwire.on('download', numberOfBytes =\u003e {\n  ...\n})\nwire.on('upload', numberOfBytes =\u003e {\n  ...\n})\n```\n\n\n## extension api\n\nThis package supports a simple extension API so you can extend the default protocol\nfunctionality with common protocol extensions like ut_metadata (magnet uris).\n\nHere are the **bittorrent-protocol** extensions that we know about:\n\n- [ut_metadata](https://www.npmjs.com/package/ut_metadata) - Extension for Peers to Send Metadata Files (BEP 9)\n- [ut_pex](https://www.npmjs.com/package/ut_pex) - Extension for Peer Discovery (PEX)\n- *Add yours here! Send a pull request!*\n\nIn short, an extension can register itself with at a certain name, which will be added to\nthe extended protocol handshake sent to the remote peer. Extensions can also hook events\nlike 'handshake' and 'extended'. To use an extension, simply require it and call\n`wire.use()`.\n\nHere is an example of the **ut_metadata** extension being used with\n**bittorrent-protocol**:\n\n```js\nimport Protocol from 'bittorrent-protocol'\nimport net from 'net'\nimport ut_metadata from 'ut_metadata'\n\nnet.createServer(socket =\u003e {\n  const wire = new Protocol()\n  socket.pipe(wire).pipe(socket)\n\n  // initialize the extension\n  wire.use(ut_metadata())\n\n  // all `ut_metadata` functionality can now be accessed at wire.ut_metadata\n\n  // ask the peer to send us metadata\n  wire.ut_metadata.fetch()\n\n  // 'metadata' event will fire when the metadata arrives and is verified to be correct!\n  wire.ut_metadata.on('metadata', metadata =\u003e {\n    // got metadata!\n\n    // Note: the event will not fire if the peer does not support ut_metadata, if they\n    // don't have metadata yet either, if they repeatedly send invalid data, or if they\n    // simply don't respond.\n  })\n\n  // optionally, listen to the 'warning' event if you want to know that metadata is\n  // probably not going to arrive for one of the above reasons.\n  wire.ut_metadata.on('warning', err =\u003e {\n    console.log(err.message)\n  })\n\n  // handle handshake\n  wire.on('handshake', (infoHash, peerId) =\u003e {\n    // receive a handshake (infoHash and peerId are hex strings)\n    wire.handshake(new Buffer('my info hash'), new Buffer('my peer id'))\n  })\n\n}).listen(6881)\n```\n\nIf you want to write your own extension, take a look at the\n[ut_metadata index.js file](https://github.com/webtorrent/ut_metadata/blob/master/index.js)\nto see how it's done.\n\n## license\n\nMIT. Copyright (c) [Feross Aboukhadijeh](https://feross.org), Mathias Buus, and [WebTorrent, LLC](https://webtorrent.io).\n","funding_links":["https://github.com/sponsors/webtorrent","https://github.com/sponsors/feross"],"categories":["Modules","Protocols"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwebtorrent%2Fbittorrent-protocol","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwebtorrent%2Fbittorrent-protocol","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwebtorrent%2Fbittorrent-protocol/lists"}