{"id":13772381,"url":"https://github.com/thegecko/webbluetooth","last_synced_at":"2026-01-18T04:01:06.096Z","repository":{"id":27232671,"uuid":"111308426","full_name":"thegecko/webbluetooth","owner":"thegecko","description":"Node.js implementation of the Web Bluetooth Specification","archived":false,"fork":false,"pushed_at":"2026-01-17T13:47:06.000Z","size":3746,"stargazers_count":188,"open_issues_count":11,"forks_count":28,"subscribers_count":4,"default_branch":"main","last_synced_at":"2026-01-17T23:57:48.590Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://thegecko.github.io/webbluetooth/","language":"TypeScript","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/thegecko.png","metadata":{"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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2017-11-19T15:37:59.000Z","updated_at":"2026-01-17T13:19:32.000Z","dependencies_parsed_at":"2023-02-11T08:25:23.234Z","dependency_job_id":"3a061564-681e-4d8b-89cd-e735f10d4769","html_url":"https://github.com/thegecko/webbluetooth","commit_stats":{"total_commits":360,"total_committers":8,"mean_commits":45.0,"dds":0.475,"last_synced_commit":"37af8e7e66e9e43784200f5928bbe9c905bea1ef"},"previous_names":[],"tags_count":25,"template":false,"template_full_name":null,"purl":"pkg:github/thegecko/webbluetooth","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thegecko%2Fwebbluetooth","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thegecko%2Fwebbluetooth/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thegecko%2Fwebbluetooth/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thegecko%2Fwebbluetooth/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thegecko","download_url":"https://codeload.github.com/thegecko/webbluetooth/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thegecko%2Fwebbluetooth/sbom","scorecard":{"id":474273,"data":{"date":"2025-08-11","repo":{"name":"github.com/thegecko/webbluetooth","commit":"7fc0208342df81ecfaa4cff519a953b9de7cf74d"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.4,"checks":[{"name":"Code-Review","score":-1,"reason":"Found no human activity in the last 16 changesets","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":10,"reason":"30 commit(s) and 2 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/build.yml:1","Warn: no topLevel permission defined: .github/workflows/docs.yml:1","Warn: no topLevel permission defined: .github/workflows/prebuild.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/thegecko/webbluetooth/build.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/thegecko/webbluetooth/build.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/docs.yml:13: update your workflow using https://app.stepsecurity.io/secureworkflow/thegecko/webbluetooth/docs.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/docs.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/thegecko/webbluetooth/docs.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/docs.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/thegecko/webbluetooth/docs.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/prebuild.yml:43: update your workflow using https://app.stepsecurity.io/secureworkflow/thegecko/webbluetooth/prebuild.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/prebuild.yml:47: update your workflow using https://app.stepsecurity.io/secureworkflow/thegecko/webbluetooth/prebuild.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/prebuild.yml:55: update your workflow using https://app.stepsecurity.io/secureworkflow/thegecko/webbluetooth/prebuild.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/prebuild.yml:59: update your workflow using https://app.stepsecurity.io/secureworkflow/thegecko/webbluetooth/prebuild.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/prebuild.yml:63: update your workflow using https://app.stepsecurity.io/secureworkflow/thegecko/webbluetooth/prebuild.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/prebuild.yml:74: update your workflow using https://app.stepsecurity.io/secureworkflow/thegecko/webbluetooth/prebuild.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/prebuild.yml:75: update your workflow using https://app.stepsecurity.io/secureworkflow/thegecko/webbluetooth/prebuild.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/prebuild.yml:78: update your workflow using https://app.stepsecurity.io/secureworkflow/thegecko/webbluetooth/prebuild.yml/main?enable=pin","Info:   0 out of   9 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   4 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact v3.3.2 not signed: https://api.github.com/repos/thegecko/webbluetooth/releases/204563711","Warn: release artifact v3.2.1 not signed: https://api.github.com/repos/thegecko/webbluetooth/releases/141609498","Warn: release artifact v3.2.0 not signed: https://api.github.com/repos/thegecko/webbluetooth/releases/141607220","Warn: release artifact v3.3.2 does not have provenance: https://api.github.com/repos/thegecko/webbluetooth/releases/204563711","Warn: release artifact v3.2.1 does not have provenance: https://api.github.com/repos/thegecko/webbluetooth/releases/141609498","Warn: release artifact v3.2.0 does not have provenance: https://api.github.com/repos/thegecko/webbluetooth/releases/141607220"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 30 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":6,"reason":"4 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-fjxv-7rqg-78g4","Warn: Project is vulnerable to: GHSA-p8p7-x288-28g6","Warn: Project is vulnerable to: GHSA-72xf-g2v4-qvf3"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-19T14:50:51.376Z","repository_id":27232671,"created_at":"2025-08-19T14:50:51.376Z","updated_at":"2025-08-19T14:50:51.376Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28529455,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-18T00:39:45.795Z","status":"online","status_checked_at":"2026-01-18T02:00:07.578Z","response_time":98,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":[],"created_at":"2024-08-03T17:01:03.280Z","updated_at":"2026-01-18T04:01:05.872Z","avatar_url":"https://github.com/thegecko.png","language":"TypeScript","readme":"# Node Web Bluetooth\nNode.js implementation of the [Web Bluetooth Specification](https://webbluetoothcg.github.io/web-bluetooth/)\n\n[![Build Status](https://github.com/thegecko/webbluetooth/workflows/prebuild/badge.svg)](https://github.com/thegecko/webbluetooth/actions)\n[![npm](https://img.shields.io/npm/dm/webbluetooth.svg)](https://www.npmjs.com/package/webbluetooth)\n[![Licence MIT](https://img.shields.io/badge/licence-MIT-blue.svg)](http://opensource.org/licenses/MIT)\n\n## Prerequisites\n\n[Node.js \u003e v10.20.0](https://nodejs.org), which includes `npm`.\n\n## Installation\n\n```bash\n$ npm install webbluetooth\n```\n\n## Getting Started\n\nSee the [examples](https://github.com/thegecko/webbluetooth/tree/main/examples/) or view the API documentation at:\n\nhttps://thegecko.github.io/webbluetooth/\n\n## Supported Platforms\n\nBinaries are built to support the following platforms:\n\nOS | x86 | x64 | arm64\n--- | --- | --- | ---\nWindows         | X | X | -\nMacOS           | - | X | X \nLinux (glibc)   | - | X | X\n\n## Usage\n\nThe module exports a default `navigator.bluetooth` instance, the `Bluetooth` class to allow you to instantiate your own bluetooth instances and the Bluetooth helper methods:\n\n- [bluetooth](globals.html#bluetooth)\n- [Bluetooth()](classes/bluetooth.html)\n- [BluetoothUUID.getService()](globals.html)\n- [BluetoothUUID.getCharacteristic()](globals.html)\n- [BluetoothUUID.getDescriptor()](globals.html)\n- [BluetoothUUID.canonicalUUID()](globals.html)\n\n### Using the default bluetooth instance\n\nTo use existing Web Bluetooth scripts, you can simply use the default `bluetooth` instance in place of the `navigator.bluetooth` object:\n\n```JavaScript\nconst bluetooth = require('webbluetooth').bluetooth;\n\nconst device = await bluetooth.requestDevice({\n    filters:[{ services:[ 'heart_rate' ] }]\n});\n\nconst server = await device.gatt.connect();\n...\n```\n\nThe first device matching the filters will be returned.\n\n### Creating your own bluetooth instances\n\nYou may want to create your own instance of the `Bluetooth` class. For example, to inject a device chooser function or control the referring device:\n\n```JavaScript\nconst Bluetooth = require('webbluetooth').Bluetooth;\n\nconst deviceFound = (device, selectFn) =\u003e {\n    // If device can be automatically selected, do so by returning true\n    if (device.name === 'myName') return true;\n\n    // Otherwise store the selectFn somewhere and execute it later to select this device\n};\n\nconst bluetooth = new Bluetooth({ deviceFound });\n\nconst device = await bluetooth.requestDevice({\n    filters:[{ services:[ 'heart_rate' ] }]\n});\n\nconst server = await device.gatt.connect();\n...\n```\n\n## Specification\n\nThe Web Bluetooth specification can be found here:\n\nhttps://webbluetoothcg.github.io/web-bluetooth/\n\n## Implementation Status\n\n### Functions\n- [x] getAdapters() - list available bluetooth adapters\n\n### new Bluetooth options\n- [x] deviceFound - A `device found` callback function to allow the user to select a device\n- [x] scanTime - The amount of seconds to scan for the device (default is 10)\n- [x] allowAllDevices - Optional flag to automatically allow all devices\n- [x] referringDevice - An optional referring device\n- [x] adapterIndex - An optional index of bluetooth adapter to use (default is 0)\n\n### bluetooth\n\n- [x] getAvailability()\n- [x] referringDevice\n- [x] requestDevice()\n- [x] getDevices()\n- [x] RequestDeviceOptions.filter.name\n- [x] RequestDeviceOptions.filter.namePrefix\n- [x] RequestDeviceOptions.filter.services\n- [x] RequestDeviceOptions.filter.manufacturerData\n- [x] RequestDeviceOptions.filter.serviceData\n- [x] RequestDeviceOptions.acceptAllDevices\n- [x] RequestDeviceOptions.optionalServices\n- [ ] RequestDeviceOptions.exclusionFilters\n- [ ] RequestDeviceOptions.optionalManufacturerData - used in advertisements, unsupported in adapter\n\n### BluetoothDevice\n\n- [x] id\n- [x] name\n- [x] gatt\n- [x] forget()\n- [ ] watchAdvertisements() - unsupported in adapter\n- [ ] watchingAdvertisements - unsupported in adapter\n\n### BluetoothRemoteGATTServer\n\n- [x] device\n- [x] connected\n- [x] connect()\n- [x] disconnect()\n- [x] getPrimaryService()\n- [x] getPrimaryServices()\n\n### BluetoothRemoteGATTService\n\n- [x] uuid\n- [x] device\n- [x] isPrimary\n- [x] getCharacteristic()\n- [x] getCharacteristics()\n- [ ] getIncludedService() - unsupported in adapter\n- [ ] getIncludedServices() - unsupported in adapter\n\n### BluetoothRemoteGATTCharacteristic\n\n- [x] uuid\n- [x] service\n- [x] value\n- [ ] properties.broadcast - unsupported in adapter\n- [x] properties.read\n- [x] properties.writeWithoutResponse\n- [x] properties.write\n- [x] properties.notify\n- [x] properties.indicate\n- [ ] properties.authenticatedSignedWrites - unsupported in adapter\n- [ ] properties.reliableWrite - unsupported in adapter\n- [ ] properties.writableAuxiliaries - unsupported in adapter\n- [x] getDescriptor()\n- [x] getDescriptors()\n- [x] readValue()\n- [x] writeValue()\n- [x] writeValueWithResponse()\n- [x] writeValueWithoutResponse()\n- [x] startNotifications()\n- [x] stopNotifications()\n\n### BluetoothRemoteGATTDescriptor\n\n- [x] uuid\n- [x] characteristic\n- [x] value\n- [x] readValue()\n- [x] writeValue()\n\n### BluetoothUUID\n\n- [x] getService()\n- [x] getCharacteristic()\n- [x] getDescriptor()\n- [x] canonicalUUID()\n\n### Events\n\n#### Bluetooth\n\n- [ ] availabilitychanged - unsupported in adapter\n\n#### Bluetooth Device\n\n- [x] gattserverdisconnected\n- [ ] advertisementreceived - unsupported in adapter\n\n#### Bluetooth Service\n\n- [x] serviceadded\n- [ ] servicechanged - unsupported in adapter\n- [ ] serviceremoved - unsupported in adapter\n\n#### Bluetooth Characteristic\n\n- [x] characteristicvaluechanged\n\n### Other\n\n- [x] Device selector hook\n- [x] Examples\n- [x] API Documentation\n\n## Development\n\n### Cloning\n\nThis repository uses a submodule to reference the SimpleBLE library. Clone it as follows:\n\n```bash\ngit clone https://github.com/thegecko/webbluetooth\ncd webbluetooth\ngit submodule update --init\n```\n\n### Building\n\nTo build the SimpleBLE module, bindings and TypeScriptsource, run:\n\n``` bash\nyarn build:all\n```\n\n### Testing\n\nThe tests are set up to use a BBC micro:bit in range with the following services available:\n\n- Device Info Service (0000180a-0000-1000-8000-00805f9b34fb)\n- LED Service (e95dd91d-251d-470a-a062-fa1922dfa9a8)\n- Button Service (e95d9882-251d-470a-a062-fa1922dfa9a8)\n\nSample code and hex file for the v2 micro:bit can be found in the [firmware folder](https://github.com/thegecko/webbluetooth/tree/main/firmware).\n\nTo run the tests:\n\n```bash\nyarn test\n```\n","funding_links":[],"categories":["Browser Features"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthegecko%2Fwebbluetooth","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthegecko%2Fwebbluetooth","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthegecko%2Fwebbluetooth/lists"}