# Web Bluetooth Scanning

## Draft Community Group Report, 1 January 1970

This version:
  https://webbluetoothcg.github.io/web-bluetooth/scanning.html
Editor:
  See contributors on GitHub
Participate:
  Join the W3C Community Group
  Fix the text through GitHub
  public-web-bluetooth@w3.org (archives)
  IRC: #web-bluetooth on W3C’s IRC

Copyright © 1970 the Contributors to the Web Bluetooth Specification, published by the Web Bluetooth Community Group under the W3C Community Contributor License Agreement (CLA). A human-readable summary is available.

## Abstract

This document describes an API to scan for nearby Bluetooth Low Energy devices in real time.

## Status of this document

This specification was published by the Web Bluetooth Community Group. It is not a W3C Standard nor is it on the W3C Standards Track. Please note that under the W3C Community Contributor License Agreement (CLA) there is a limited opt-out and other conditions apply. Learn more about W3C Community and Business Groups.

Changes to this document may be tracked at https://github.com/WebBluetoothCG/web-bluetooth/commits/gh-pages.

If you wish to make comments regarding this document, please send them to public-web-bluetooth@w3.org (subscribe, archives).

## 1. Introduction

This section is non-normative.

Bluetooth Low Energy (BLE) allows devices to broadcast advertisements to nearby observers. These advertisements can contain small amounts of data of a variety of types defined in [BLUETOOTH-SUPPLEMENT6].

For example, a beacon might announce that it’s next to a particular museum exhibit and is advertising with 1mW of power, which would let nearby observers know their approximate distance to that exhibit.

This specification extends [web-bluetooth] to allow websites to receive these advertisements from nearby BLE devices, with the user’s permission.

### 1.1. Examples

To discover what iBeacons are nearby and measure their distance, a website could use code like the following:

    function recordNearbyBeacon(major, minor, pathLossVs1m) { ... }
    navigator.bluetooth.requestLEScan({
      filters: [{manufacturerData: {0x004C: {dataPrefix: new Uint8Array([
        0x02, 0x15, // iBeacon identifier.
        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15  // My beacon UUID.
      ])}}}],
      keepRepeatedDevices: true
    }).then(() => {
      navigator.bluetooth.addEventListener('advertisementreceived', event => {
        let appleData = event.manufacturerData.get(0x004C);
        if (appleData.byteLength != 23) {
          // Isn’t an iBeacon.
          return;
        }
        let major = appleData.getUint16(18, false);
        let minor = appleData.getUint16(20, false);
        let txPowerAt1m = -appleData.getInt8(22);
        let pathLossVs1m = txPowerAt1m - event.rssi;

        recordNearbyBeacon(major, minor, pathLossVs1m);
      });
    })

## 2. Privacy considerations

This section is non-normative.

Actively scanning for advertisements broadcasts a device address of the scanning device. If the UA’s Bluetooth system supports the privacy feature, this address rotates periodically, which prevents remote radios from tracking the user’s device. However, if the UA’s Bluetooth system does not support the privacy feature, this address is a stable unique identifier that’s difficult to change. To mitigate this, UAs should either use passive scanning, use the privacy feature in an observer, or warn the user that nearby devices will learn the identity of their device.

The ambient advertisements in a user’s area are unlikely to directly include GPS coordinates, but are likely to contain unique identifiers that could be manually correlated with particular physical locations or with particular other people. Given that, the user needs to give permission before a website gets access to nearby advertisements.

If a user has already given a site permission to know their location, it might be ok to implicitly grant access to BLE advertisements. However, BLE advertisements give away strictly less location information than full [geolocation-api] access, so UAs should allow users to grant that intermediate level of access.

BLE advertisements are usually fully public, since they’re broadcast unencrypted on 2.4GHz radio waves. However, it’s possible that a user would have a device broadcast private information in a radio-shielded room. This is probably an inappropriate use for BLE advertisements, but might argue for requiring explicit permission to scan, rather than inferring it from having permission to get a geolocation.

## 3. Security considerations

This section is non-normative.

Because this API doesn’t write anything, there are few if any security implications. A device in a shielded room might broadcast security-sensitive information, but we don’t have any actual attack scenarios for that.

## 4. Scanning for BLE advertisements

    dictionary BluetoothLEScanOptions {
      sequence<BluetoothLEScanFilterInit> filters;
      boolean keepRepeatedDevices = false;
      boolean acceptAllAdvertisements = false;
    };

    partial interface Bluetooth {
      [SecureContext]
      Promise<BluetoothLEScan> requestLEScan(optional BluetoothLEScanOptions options);
    };

NOTE: `requestLEScan()` summary

`navigator.bluetooth.`requestLEScan(options)`` starts scanning for BLE advertisements, asking the user for permission if they haven’t yet granted it.

Because this could show a prompt, it requires a secure context, and UAs are likely to require a user gesture.

Advertising events that match a `BluetoothLEScanFilter` in an active `BluetoothLEScan` cause `advertisementreceived` events to be dispatched to the sending `BluetoothDevice`. A filter matches if the advertisement includes data equal to each present member. Usually, you’ll only include one member in each filter.

Normally scans will discard the second and subsequent advertisements from a single device to save power. If you need to receive them, set `keepRepeatedDevices` to `true`. Note that setting `keepRepeatedDevices` to `false` doesn’t guarantee you won’t get redundant events; it just allows the UA to save power by omitting them.

In the rare case that you want to receive every advertisement without filtering them, use the `acceptAllAdvertisements` field.

The ``requestLEScan(options)`` method, when invoked, MUST return a new promise promise and run the following steps in parallel:

1. If `options.acceptAllAdvertisements` is `true`, and `options.filters` is present, reject promise with a `TypeError` and abort these steps.

   Note: There’s no need to include filters if all advertisements are being accepted.

2. If `options.acceptAllAdvertisements` is `false`, and `options.filters` is either absent or empty, reject promise with a `TypeError` and abort these steps.

   Note: An empty set of filters wouldn’t return any advertisements.

3. Let filters be `options.filters.map(filter=>new `BluetoothLEScanFilter`(filter))`. If this throws an exception, reject promise with that exception and abort these steps.
4. Request permission to use

       {
         name: "bluetooth-le-scan",
         filters: options.filters,
         keepRepeatedDevices: options.keepRepeatedDevices,
         acceptAllAdvertisements: options.acceptAllAdvertisements,
       }

   Note: This may require that this algorithm was triggered by user activation.

5. If the result is `"denied"`, reject promise with a `NotAllowedError` and abort these steps.
6. Let scan be a new `BluetoothLEScan` instance whose fields are initialized as in the following table:

   Field | Initial value
   --- | ---
   `filters` | filters
   `keepRepeatedDevices` | `options.keepRepeatedDevices`
   `acceptAllAdvertisements` | `options.acceptAllAdvertisements`
   `active` | `true`

7. Add scan to `navigator.bluetooth.`[[activeScans]]``.
8. Ensure the UA is scanning for BLE advertisements in a mode that will receive at least all advertisements matching any scan in any `[[activeScans]]` set in the whole UA.

   Find wording that allows the UA to limit its scan to only certain periods of time, to save power.

9. If the UA fails to start scanning, remove scan from `navigator.bluetooth.`[[activeScans]]``, reject promise with one of the following errors, and abort these steps:
   The UA doesn’t support scanning for advertisements
     `NotSupportedError`
   Bluetooth is turned off
     `InvalidStateError`
   Other reasons
     `UnknownError`
10. Resolve promise with scan.

### 4.1. Controlling a BLE scan

    [Constructor(optional BluetoothDataFilterInit init)]
    interface BluetoothDataFilter {
      readonly attribute ArrayBuffer dataPrefix;
      readonly attribute ArrayBuffer mask;
    };

    [Constructor(optional object init)]
    interface BluetoothManufacturerDataFilter {
      readonly maplike<unsigned short, BluetoothDataFilter>;
    };

    [Constructor(optional object init)]
    interface BluetoothServiceDataFilter {
      readonly maplike<UUID, BluetoothDataFilter>;
    };

    [Constructor(optional BluetoothLEScanFilterInit init)]
    interface BluetoothLEScanFilter {
      readonly attribute DOMString? name;
      readonly attribute DOMString? namePrefix;
      readonly attribute FrozenArray<UUID>? services;
      readonly attribute BluetoothManufacturerDataFilter manufacturerData;
      readonly attribute BluetoothServiceDataFilter serviceData;
    };

    interface BluetoothLEScan {
      readonly attribute FrozenArray<BluetoothLEScanFilter> filters;
      readonly attribute boolean keepRepeatedDevices;
      readonly attribute boolean acceptAllAdvertisements;

      readonly attribute boolean active;

      void stop();
    };

NOTE: `BluetoothLEScan` members

`BluetoothLEScan.stop()` stops a previously-requested scan. Sites should do this as soon as possible to avoid wasting power.

The `BluetoothLEScanFilter(init)` constructor, when invoked MUST perform the following steps:

1. Initialize all nullable fields to `null`.
2. If no member of init is present, throw a `TypeError`.

   Note: A filter can’t implicitly allow all advertisements. Use `acceptAllAdvertisements` to explicitly do it.

3. Initialize `manufacturerData` as `new BluetoothManufacturerDataFilter(init.`manufacturerData`)`.
4. Initialize `serviceData` as `new BluetoothManufacturerDataFilter(init.`serviceData`)`.
5. If `init.`services`` is present, initialize `this.`services`` as ``BluetoothUUID.getService`(init.`services``.
6. For each other present member in init, set `this`'s attribute with a matching identifier to the value of the member.
7. If any of the above calls threw an exception, propagate that exception from this constructor.

The `stop()` method, when invoked, MUST perform the following steps:

1. Set `this.`active`` to `false`.
2. Remove `this` from `navigator.bluetooth.`[[activeScans]]``.
3. The UA SHOULD reconfigure or stop its BLE scan to save power while still receiving any advertisements that match any scan in any `[[activeScans]]` set in the whole UA.

The `BluetoothManufacturerDataFilter(init)` constructor, when invoked, MUST perform the following steps:

1. If init is not present or `init.`[[OwnPropertyKeys]]`()` is empty, then `this` has no map entries. Abort these steps.
2. Let canonicalInit be the `manufacturerData` field of the result of canonicalizing `{manufacturerData: init}`. If this throws an exception, propagate that exception from this constructor and abort these steps.
3. `this`'s map entries map from each key in `canonicalInit.`[[OwnPropertyKeys]]`()`, parsed as a base-10 integer, to its value of `new `BluetoothDataFilter`(canonicalInit[key])`.

The `BluetoothServiceDataFilter(init)` constructor, when invoked, MUST perform the following steps:

1. If init is not present or `init.`[[OwnPropertyKeys]]`()` is empty, then `this` has no map entries. Abort these steps.
2. Let canonicalInit be the `serviceData` field of the result of canonicalizing `{serviceData: init}`. If this throws an exception, propagate that exception from this constructor and abort these steps.
3. `this`'s map entries map from each key in `canonicalInit.`[[OwnPropertyKeys]]`()`, to its value of `new `BluetoothDataFilter`(canonicalInit[key])`.

The `BluetoothDataFilter(init)` constructor, when invoked, MUST perform the following steps:

1. Let canonicalInit be the result of canonicalizing init. If this throws an exception, propagate that exception from this constructor and abort these steps.
2. Initialize `this.`dataPrefix`` as a read only ArrayBuffer whose contents are a copy of the bytes held by `canonicalInit.`dataPrefix``.
3. Initialize `this.`mask`` as a read only ArrayBuffer whose contents are a copy of the bytes held by `canonicalInit.`mask``.

### 4.2. Permission to scan

The `"bluetooth-le-scan"` powerful feature’s permission-related algorithms and types are defined as follows:

permission descriptor type

      dictionary BluetoothLEScanPermissionDescriptor : PermissionDescriptor {
        // These match BluetoothLEScanOptions.
        sequence<BluetoothLEScanFilterInit> filters;
        boolean keepRepeatedDevices = false;
        boolean acceptAllAdvertisements = false;
      };

permission result type

      interface BluetoothLEScanPermissionResult : PermissionStatus {
        attribute FrozenArray<BluetoothLEScan> scans;
      };

permission query algorithm

  Given a `BluetoothLEScanPermissionDescriptor` descriptor and a `BluetoothLEScanPermissionResult` result:

  1. Update `result.`state`` to descriptor’s permission state.
  2. If `result.`state`` is `"denied"`, set `result.scans` to an empty `FrozenArray` and abort these steps.
  3. Update `result.`scans`` to a new `FrozenArray` containing the elements of `navigator.bluetooth.`[[activeScans]]``.

     Consider filtering the result to active scans that match the fields of the descriptor.

permission request algorithm

  Given a `BluetoothLEScanPermissionDescriptor` descriptor and a `BluetoothLEScanPermissionResult` result:

  1. Let promise be the result of `navigator.bluetooth.`requestLEScan`(descriptor)`.
  2. Wait for promise to settle.
  3. If promise rejected, throw the reason it rejected with, and abort these steps.
  4. Update `result.status` to descriptor’s permission state.
  5. Update `result.scans` to a new `FrozenArray` whose single element is the value in promise.
permission revocation algorithm
  1. For each activeScan in `navigator.bluetooth.`[[activeScans]]``:
     1. If the permission state of

            {
              name: "bluetooth-le-scan",
              filters: activeScan.filters,
              keepRepeatedDevices: activeScan.keepRepeatedDevices
            }

        is not `"granted"`, call `activeScan.`stop()``.

## 5. Event handling

### 5.1. Responding to advertising events

When the UA receives an advertising event event (consisting of an advertising packet and an optional scan response), it MUST run the following steps:

1. Let device be the Bluetooth device that sent the advertising event.
2. For each `Bluetooth` instance bluetooth in the UA, queue a task on bluetooth’s relevant settings object’s responsible event loop to do the following sub-steps:
   1. Let scans be the set of `BluetoothLEScan`s in `bluetooth.`[[activeScans]]`` that match event.
   2. If scans is empty, abort these sub-steps.
   3. Note: the user’s permission to scan likely indicates that they intend newly-discovered devices to appear in `"bluetooth"`'s extra permission data, but possibly with `mayUseGATT` set to `false`.
   4. Get the `BluetoothDevice` representing device inside bluetooth, and let deviceObj be the result.
   5. Add each `BluetoothLEScan` in scans to `deviceObj.`[[returnedFromScans]]``.
   6. Fire an `advertisementreceived` event for event at deviceObj.

An advertising event event matches a `BluetoothLEScan` scan if the following steps return `match`:

1. `scan.acceptAllAdvertisements` is `false` and event doesn’t match any filter in `scan.`filters``, return `no match`.
2. If `scan.`keepRepeatedDevices`` is `false`, there is a `BluetoothDevice` device that represents the same Bluetooth device as the one that sent event, and `device.`[[returnedFromScans]]`` includes scan, the UA MAY return `no match`.
3. Return `match`.

An advertising event event matches a `BluetoothLEScanFilter` filter if all of the following conditions hold:

- If `filter.name` is non-`null`, event has a Local Name equal to `filter.name`.

  Note: A Shortened Local Name can match a `name` filter.

- If `filter.namePrefix` is non-`null`, event has a Local Name, and `filter.namePrefix` is a prefix of it.
- If `filter.serviceUUID` is non-`null`, it is equal to a Service UUID in event.
- For each (id, filter) in `filter.manufacturerData`’s map entries, some Manufacturer Specific Data in event has a Company Identifier Code of id, and whose array of bytes matches filter.
- For each (uuid, filter) in `filter.serviceData`’s map entries, some Service Data in event has a UUID whose 128-bit representation is uuid, and whose array of bytes matches filter.

## 6. Changes to existing interfaces

Instances of `Bluetooth` additionally have the following internal slots:

Internal Slot | Initial Value | Description (non-normative)
--- | --- | ---
`[[activeScans]]` | An empty set of `BluetoothLEScan` instances. | The contents of this set will have `active` equal to `true`.

Instances of `BluetoothDevice` additionally have the following internal slots:

Internal Slot | Initial Value | Description (non-normative)
--- | --- | ---
`[[returnedFromScans]]` | An empty set of `BluetoothLEScan` objects. | Used to implement `keepRepeatedDevices`.

## 7. Terminology and conventions

This specification uses a few conventions and several terms from other specifications. This section lists those and links to their primary definitions.

When an algorithm in this specification uses a name defined in this or another specification, the name MUST resolve to its initial value, ignoring any changes that have been made to the name in the current execution environment. For example, when the `requestLEScan()` algorithm says to call `options.filters.map(filter=>new `BluetoothLEScanFilter`(filter))`, this MUST apply the `Array.prototype.map` algorithm defined in [ECMAScript] with `options.services` as its `this` parameter and the algorithm defined at `BluetoothLEScanFilter()` as its `callbackfn` parameter, regardless of any modifications that have been made to `window`, `Array`, `Array.prototype`, `Array.prototype.map`, `Function`, `Function.prototype`, `BluetoothLEScanFilter`, or other objects.

[BLUETOOTH42]
  1. Architecture & Terminology Overview
     1. General Description
        1. Overview of Bluetooth Low Energy Operation (defines advertising events)
  2. Core System Package [Host volume]
     1. Generic Access Profile
        1. Profile Overview
           1. Profile Roles
              1. Roles when Operating over an LE Physical Transport
                 1. Observer Role
        2. Security Aspects — LE Physical Transport
           1. Privacy Feature
              1. Privacy Feature in an Observer
  3. Core System Package [Low Energy Controller volume]
     1. Link Layer Specification
        1. General Description
           1. Device Address
        2. Air Interface Packets
           1. Advertising Channel PDU
              1. Advertising PDUs
                 1. ADV_IND
                 2. ADV_DIRECT_IND
                 3. ADV_NONCONN_IND
                 4. ADV_SCAN_IND
        3. Air Interface Protocol
           1. Non-Connected States
              1. Scanning State
                 1. Passive Scanning
                 2. Active Scanning
[BLUETOOTH-SUPPLEMENT6]
  1. Data Types Specification
     1. Data Types Definitions and Formats
        1. Service UUID
        2. Local Name also defines Shortened Local Name and Complete Local Name
        3. Manufacturer Specific Data
        4. Service Data

## Conformance

Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification.

All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. [RFC2119]

Examples in this specification are introduced with the words “for example” or are set apart from the normative text with `class="example"`, like this:

This is an example of an informative example.

Informative notes begin with the word “Note” and are set apart from the normative text with `class="note"`, like this:

Note, this is an informative note.

## Index

### Terms defined by this specification

- acceptAllAdvertisements
  - attribute for BluetoothLEScan, in §4.1
  - dict-member for BluetoothLEScanOptions, in §4
  - dict-member for BluetoothLEScanPermissionDescriptor, in §4.2
- active, in §4.1
- Active Scanning, in §7
- [[activeScans]], in §6
- advertising event, in §7
- advertising events, in §7
- BluetoothDataFilter, in §4.1
- BluetoothDataFilter(init), in §4.1
- "bluetooth-le-scan", in §4.2
- BluetoothLEScan, in §4.1
- BluetoothLEScanFilter, in §4.1
- BluetoothLEScanFilter(init), in §4.1
- BluetoothLEScanOptions, in §4
- BluetoothLEScanPermissionDescriptor, in §4.2
- BluetoothLEScanPermissionResult, in §4.2
- BluetoothManufacturerDataFilter, in §4.1
- BluetoothManufacturerDataFilter(init), in §4.1
- BluetoothServiceDataFilter, in §4.1
- BluetoothServiceDataFilter(init), in §4.1
- dataPrefix, in §4.1
- Device Address, in §7
- filters
  - attribute for BluetoothLEScan, in §4.1
  - dict-member for BluetoothLEScanOptions, in §4
  - dict-member for BluetoothLEScanPermissionDescriptor, in §4.2
- keepRepeatedDevices
  - attribute for BluetoothLEScan, in §4.1
  - dict-member for BluetoothLEScanOptions, in §4
  - dict-member for BluetoothLEScanPermissionDescriptor, in §4.2
- Local Name, in §7
- manufacturerData, in §4.1
- Manufacturer Specific Data, in §7
- mask, in §4.1
- match
  - dfn for BluetoothLEScan, in §5.1
  - dfn for BluetoothLEScanFilter, in §5.1
- name, in §4.1
- namePrefix, in §4.1
- Observer, in §7
- Passive Scanning, in §7
- Privacy Feature, in §7
- Privacy Feature in an Observer, in §7
- requestLEScan(), in §4
- requestLEScan(options), in §4
- [[returnedFromScans]], in §6
- scans, in §4.2
- Service Data, in §7
- serviceData, in §4.1
- services, in §4.1
- Service UUID, in §7
- Shortened Local Name, in §7
- stop(), in §4.1

https://tc39.github.io/ecma262/#sec-array.prototype.map Referenced in:

- 7. Terminology and conventions

https://tc39.github.io/ecma262/#sec-native-error-types-used-in-this-standard-typeerror Referenced in:

- 4. Scanning for BLE advertisements (2)
- 4.1. Controlling a BLE scan

https://tc39.github.io/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys Referenced in:

- 4.1. Controlling a BLE scan (2) (3) (4)

https://html.spec.whatwg.org/multipage/infrastructure.html#in-parallel Referenced in:

- 4. Scanning for BLE advertisements

https://html.spec.whatwg.org/multipage/webappapis.html#queue-a-task Referenced in:

- 5.1. Responding to advertising events

https://html.spec.whatwg.org/multipage/webappapis.html#relevant-settings-object Referenced in:

- 5.1. Responding to advertising events

https://html.spec.whatwg.org/multipage/webappapis.html#responsible-event-loop Referenced in:

- 5.1. Responding to advertising events

https://html.spec.whatwg.org/multipage/interaction.html#triggered-by-user-activation Referenced in:

- 4. Scanning for BLE advertisements (2)

https://w3c.github.io/permissions/#dom-permissionstate-denied Referenced in:

- 4. Scanning for BLE advertisements
- 4.2. Permission to scan

https://w3c.github.io/permissions/#dom-permissionstate-granted Referenced in:

- 4.2. Permission to scan

https://w3c.github.io/permissions/#dictdef-permissiondescriptor Referenced in:

- 4.2. Permission to scan

https://w3c.github.io/permissions/#permissionstatus Referenced in:

- 4.2. Permission to scan

https://w3c.github.io/permissions/#extra-permission-data Referenced in:

- 5.1. Responding to advertising events

https://w3c.github.io/permissions/#permission-descriptor-type Referenced in:

- 4.2. Permission to scan

https://w3c.github.io/permissions/#permission-query-algorithm Referenced in:

- 4.2. Permission to scan

https://w3c.github.io/permissions/#permission-result-type Referenced in:

- 4.2. Permission to scan

https://w3c.github.io/permissions/#permission-revocation-algorithm Referenced in:

- 4.2. Permission to scan

https://w3c.github.io/permissions/#permission-state Referenced in:

- 4.2. Permission to scan (2) (3)

https://w3c.github.io/permissions/#powerful-feature Referenced in:

- 4.2. Permission to scan

https://w3c.github.io/permissions/#request-permission-to-use Referenced in:

- 4. Scanning for BLE advertisements

https://w3c.github.io/permissions/#dom-permissionstatus-state Referenced in:

- 4.2. Permission to scan (2)

https://wicg.github.io/permissions-request/#permission-request-algorithm Referenced in:

- 4.2. Permission to scan

https://www.w3.org/2001/tag/doc/promises-guide/#a-new-promise Referenced in:

- 4. Scanning for BLE advertisements

https://www.w3.org/2001/tag/doc/promises-guide/#reject-promise Referenced in:

- 4. Scanning for BLE advertisements (2) (3) (4)

https://w3c.github.io/webappsec-secure-contexts/#secure-contexts Referenced in:

- 4. Scanning for BLE advertisements

https://webbluetoothcg.github.io/web-bluetooth/#dom-permissionname-bluetooth Referenced in:

- 5.1. Responding to advertising events

https://webbluetoothcg.github.io/web-bluetooth/#bluetooth Referenced in:

- 4. Scanning for BLE advertisements
- 5.1. Responding to advertising events
- 6. Changes to existing interfaces

https://webbluetoothcg.github.io/web-bluetooth/#dictdef-bluetoothdatafilterinit Referenced in:

- 4.1. Controlling a BLE scan

index.html#bluetoothdevice Referenced in:

- 4. Scanning for BLE advertisements
- 5.1. Responding to advertising events
- 6. Changes to existing interfaces

https://webbluetoothcg.github.io/web-bluetooth/#dictdef-bluetoothlescanfilterinit Referenced in:

- 4. Scanning for BLE advertisements
- 4.1. Controlling a BLE scan
- 4.2. Permission to scan

https://webbluetoothcg.github.io/web-bluetooth/#typedefdef-uuid Referenced in:

- 4.1. Controlling a BLE scan (2)

https://webbluetoothcg.github.io/web-bluetooth/#eventdef-bluetoothdevice-advertisementreceived Referenced in:

- 1.1. Examples
- 4. Scanning for BLE advertisements

https://webbluetoothcg.github.io/web-bluetooth/#bluetooth-device Referenced in:

- 5.1. Responding to advertising events

https://webbluetoothcg.github.io/web-bluetooth/#bluetoothlescanfilterinit-canonicalizing Referenced in:

- 4.1. Controlling a BLE scan (2)

https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdatafilterinit-dataprefix Referenced in:

- 4.1. Controlling a BLE scan

https://webbluetoothcg.github.io/web-bluetooth/#fire-an-advertisementreceived-event Referenced in:

- 5.1. Responding to advertising events

https://webbluetoothcg.github.io/web-bluetooth/#get-the-bluetoothdevice-representing Referenced in:

- 5.1. Responding to advertising events

https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothuuid-getservice Referenced in:

- 4.1. Controlling a BLE scan

https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothlescanfilterinit-manufacturerdata Referenced in:

- 4.1. Controlling a BLE scan

https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdatafilterinit-mask Referenced in:

- 4.1. Controlling a BLE scan

https://webbluetoothcg.github.io/web-bluetooth/#bluetoothdatafilterinit-matches Referenced in:

- 5.1. Responding to advertising events (2)

https://webbluetoothcg.github.io/web-bluetooth/#dom-allowedbluetoothdevice-mayusegatt Referenced in:

- 5.1. Responding to advertising events

https://webbluetoothcg.github.io/web-bluetooth/#read-only-arraybuffer Referenced in:

- 4.1. Controlling a BLE scan (2)

https://webbluetoothcg.github.io/web-bluetooth/#same-bluetooth-device Referenced in:

- 5.1. Responding to advertising events

https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothlescanfilterinit-servicedata Referenced in:

- 4.1. Controlling a BLE scan

https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothlescanfilterinit-services Referenced in:

- 4.1. Controlling a BLE scan (2)

https://heycam.github.io/webidl/#idl-ArrayBuffer Referenced in:

- 4.1. Controlling a BLE scan (2)

https://heycam.github.io/webidl/#idl-DOMString Referenced in:

- 4.1. Controlling a BLE scan (2)

https://heycam.github.io/webidl/#idl-frozen-array Referenced in:

- 4.2. Permission to scan (2) (3)

https://heycam.github.io/webidl/#invalidstateerror Referenced in:

- 4. Scanning for BLE advertisements

https://heycam.github.io/webidl/#notallowederror Referenced in:

- 4. Scanning for BLE advertisements

https://heycam.github.io/webidl/#notsupportederror Referenced in:

- 4. Scanning for BLE advertisements

https://heycam.github.io/webidl/#SecureContext Referenced in:

- 4. Scanning for BLE advertisements

https://heycam.github.io/webidl/#unknownerror Referenced in:

- 4. Scanning for BLE advertisements

https://heycam.github.io/webidl/#dfn-get-buffer-source-copy Referenced in:

- 4.1. Controlling a BLE scan (2)

https://heycam.github.io/webidl/#idl-boolean Referenced in:

- 4. Scanning for BLE advertisements (2)
- 4.1. Controlling a BLE scan (2) (3)
- 4.2. Permission to scan (2)

https://heycam.github.io/webidl/#dfn-map-entries Referenced in:

- 4.1. Controlling a BLE scan (2) (3) (4)
- 5.1. Responding to advertising events (2)

https://heycam.github.io/webidl/#idl-object Referenced in:

- 4.1. Controlling a BLE scan (2)

https://heycam.github.io/webidl/#dfn-present Referenced in:

- 4. Scanning for BLE advertisements
- 4.1. Controlling a BLE scan

https://heycam.github.io/webidl/#idl-unsigned-short Referenced in:

- 4.1. Controlling a BLE scan

### Terms defined by reference

- [ECMAScript] defines the following terms:
  - Array.prototype.map
  - TypeError
  - [[OwnPropertyKeys]]
- [HTML] defines the following terms:
  - in parallel
  - queue a task
  - relevant settings object
  - responsible event loop
  - triggered by user activation
- [permissions] defines the following terms:
  - "denied"
  - "granted"
  - PermissionDescriptor
  - PermissionStatus
  - extra permission data
  - permission descriptor type
  - permission query algorithm
  - permission result type
  - permission revocation algorithm
  - permission state
  - powerful feature
  - request permission to use
  - state
- [PERMISSIONS-REQUEST] defines the following terms:
  - permission request algorithm
- [promises-guide] defines the following terms:
  - a new promise
  - reject
- [secure-contexts] defines the following terms:
  - secure contexts
- [web-bluetooth] defines the following terms:
  - "bluetooth"
  - Bluetooth
  - BluetoothDataFilterInit
  - BluetoothDevice
  - BluetoothLEScanFilterInit
  - UUID
  - advertisementreceived
  - bluetooth device
  - canonicalizing (for BluetoothLEScanFilterInit)
  - dataPrefix
  - fire an advertisementreceived event
  - get the bluetoothdevice representing
  - getService(name)
  - manufacturerData
  - mask
  - matches
  - mayUseGATT
  - read only arraybuffer
  - same bluetooth device
  - serviceData
  - services
- [WebIDL] defines the following terms:
  - ArrayBuffer
  - DOMString
  - FrozenArray
  - InvalidStateError
  - NotAllowedError
  - NotSupportedError
  - SecureContext
  - UnknownError
  - a copy of the bytes held
  - boolean
  - map entries
  - object
  - present
  - unsigned short

## References

### Normative References

[BLUETOOTH-SUPPLEMENT6]
  Supplement to the Bluetooth Core Specification Version 6. 14 July 2015. URL: https://www.bluetooth.org/DocMan/handlers/DownloadDoc.ashx?doc_id=302735
[BLUETOOTH42]
  BLUETOOTH SPECIFICATION Version 4.2. 2 December 2014. URL: https://www.bluetooth.org/DocMan/handlers/DownloadDoc.ashx?doc_id=286439
[ECMAScript]
  ECMAScript Language Specification. URL: https://tc39.github.io/ecma262/
[HTML]
  Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[PERMISSIONS]
  Mounir Lamouri; Marcos Caceres; Jeffrey Yasskin. Permissions. 25 September 2017. WD. URL: https://www.w3.org/TR/permissions/
[PERMISSIONS-REQUEST]
  Requesting Permissions. Living Standard. URL: https://wicg.github.io/permissions-request/
[PROMISES-GUIDE]
  Domenic Denicola. Writing Promise-Using Specifications. 9 November 2018. TAG Finding. URL: https://www.w3.org/2001/tag/doc/promises-guide
[RFC2119]
  S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://tools.ietf.org/html/rfc2119
[WEB-BLUETOOTH]
  Jeffrey Yasskin. Web Bluetooth. Draft Community Group Report. URL: https://webbluetoothcg.github.io/web-bluetooth/
[WebIDL]
  Boris Zbarsky. Web IDL. 15 December 2016. ED. URL: https://heycam.github.io/webidl/

### Informative References

[GEOLOCATION-API]
  Andrei Popescu. Geolocation API Specification 2nd Edition. 8 November 2016. REC. URL: https://www.w3.org/TR/geolocation-API/
[SECURE-CONTEXTS]
  Mike West. Secure Contexts. 15 September 2016. CR. URL: https://www.w3.org/TR/secure-contexts/

## IDL Index

    dictionary BluetoothLEScanOptions {
      sequence<BluetoothLEScanFilterInit> filters;
      boolean keepRepeatedDevices = false;
      boolean acceptAllAdvertisements = false;
    };

    partial interface Bluetooth {
      [SecureContext]
      Promise<BluetoothLEScan> requestLEScan(optional BluetoothLEScanOptions options);
    };

    [Constructor(optional BluetoothDataFilterInit init)]
    interface BluetoothDataFilter {
      readonly attribute ArrayBuffer dataPrefix;
      readonly attribute ArrayBuffer mask;
    };

    [Constructor(optional object init)]
    interface BluetoothManufacturerDataFilter {
      readonly maplike<unsigned short, BluetoothDataFilter>;
    };

    [Constructor(optional object init)]
    interface BluetoothServiceDataFilter {
      readonly maplike<UUID, BluetoothDataFilter>;
    };

    [Constructor(optional BluetoothLEScanFilterInit init)]
    interface BluetoothLEScanFilter {
      readonly attribute DOMString? name;
      readonly attribute DOMString? namePrefix;
      readonly attribute FrozenArray<UUID>? services;
      readonly attribute BluetoothManufacturerDataFilter manufacturerData;
      readonly attribute BluetoothServiceDataFilter serviceData;
    };

    interface BluetoothLEScan {
      readonly attribute FrozenArray<BluetoothLEScanFilter> filters;
      readonly attribute boolean keepRepeatedDevices;
      readonly attribute boolean acceptAllAdvertisements;

      readonly attribute boolean active;

      void stop();
    };

    dictionary BluetoothLEScanPermissionDescriptor : PermissionDescriptor {
      // These match BluetoothLEScanOptions.
      sequence<BluetoothLEScanFilterInit> filters;
      boolean keepRepeatedDevices = false;
      boolean acceptAllAdvertisements = false;
    };

    interface BluetoothLEScanPermissionResult : PermissionStatus {
      attribute FrozenArray<BluetoothLEScan> scans;
    };

## Issues Index

Find wording that allows the UA to limit its scan to only certain periods of time, to save power. ↵
Consider filtering the result to active scans that match the fields of the descriptor. ↵
#dictdef-bluetoothlescanoptions Referenced in:

- 4. Scanning for BLE advertisements

#dom-bluetoothlescanoptions-keeprepeateddevices Referenced in:

- 4. Scanning for BLE advertisements (2)
- 6. Changes to existing interfaces

#dom-bluetoothlescanoptions-acceptalladvertisements Referenced in:

- 4. Scanning for BLE advertisements
- 4.1. Controlling a BLE scan

#dom-bluetooth-requestlescan Referenced in:

- 1.1. Examples
- 4. Scanning for BLE advertisements (2) (3)
- 4.2. Permission to scan
- 7. Terminology and conventions

#bluetoothdatafilter Referenced in:

- 4.1. Controlling a BLE scan (2) (3) (4)

#dom-bluetoothdatafilter-dataprefix Referenced in:

- 4.1. Controlling a BLE scan

#dom-bluetoothdatafilter-mask Referenced in:

- 4.1. Controlling a BLE scan

#bluetoothmanufacturerdatafilter Referenced in:

- 4.1. Controlling a BLE scan

#bluetoothservicedatafilter Referenced in:

- 4.1. Controlling a BLE scan

#bluetoothlescanfilter Referenced in:

- 4. Scanning for BLE advertisements
- 4.1. Controlling a BLE scan
- 5.1. Responding to advertising events

#dom-bluetoothlescanfilter-name Referenced in:

- 5.1. Responding to advertising events

#dom-bluetoothlescanfilter-services Referenced in:

- 4.1. Controlling a BLE scan

#dom-bluetoothlescanfilter-manufacturerdata Referenced in:

- 4.1. Controlling a BLE scan

#dom-bluetoothlescanfilter-servicedata Referenced in:

- 4.1. Controlling a BLE scan

#bluetoothlescan Referenced in:

- 4. Scanning for BLE advertisements (2) (3)
- 4.1. Controlling a BLE scan
- 4.2. Permission to scan
- 5.1. Responding to advertising events (2) (3)
- 6. Changes to existing interfaces (2)

#dom-bluetoothlescan-filters Referenced in:

- 4. Scanning for BLE advertisements
- 5.1. Responding to advertising events

#dom-bluetoothlescan-keeprepeateddevices Referenced in:

- 4. Scanning for BLE advertisements
- 5.1. Responding to advertising events

#dom-bluetoothlescan-acceptalladvertisements Referenced in:

- 4. Scanning for BLE advertisements

#dom-bluetoothlescan-active Referenced in:

- 4. Scanning for BLE advertisements
- 4.1. Controlling a BLE scan
- 6. Changes to existing interfaces

#dom-bluetoothlescanfilter-bluetoothlescanfilter Referenced in:

- 4. Scanning for BLE advertisements
- 7. Terminology and conventions (2)

#dom-bluetoothlescan-stop Referenced in:

- 4.1. Controlling a BLE scan (2)
- 4.2. Permission to scan

#dom-permissionname-bluetooth-le-scan Referenced in:

- 4. Scanning for BLE advertisements

#dictdef-bluetoothlescanpermissiondescriptor Referenced in:

- 4.2. Permission to scan (2)

#bluetoothlescanpermissionresult Referenced in:

- 4.2. Permission to scan (2)

#dom-bluetoothlescanpermissionresult-scans Referenced in:

- 4.2. Permission to scan

#bluetoothlescan-match Referenced in:

- 4. Scanning for BLE advertisements
- 4.1. Controlling a BLE scan
- 5.1. Responding to advertising events

#bluetoothlescanfilter-match Referenced in:

- 4. Scanning for BLE advertisements
- 5.1. Responding to advertising events

#dom-bluetooth-activescans-slot Referenced in:

- 4. Scanning for BLE advertisements (2) (3)
- 4.1. Controlling a BLE scan (2)
- 4.2. Permission to scan (2)
- 5.1. Responding to advertising events

#dom-bluetoothdevice-returnedfromscans-slot Referenced in:

- 5.1. Responding to advertising events (2)

#advertising-event Referenced in:

- 5.1. Responding to advertising events

#observer Referenced in:

- 1. Introduction

#privacy-feature Referenced in:

- 2. Privacy considerations (2)

#privacy-feature-in-an-observer Referenced in:

- 2. Privacy considerations

#device-address Referenced in:

- 2. Privacy considerations

#passive-scanning Referenced in:

- 2. Privacy considerations

#active-scanning Referenced in:

- 2. Privacy considerations

#service-uuid Referenced in:

- 5.1. Responding to advertising events

#local-name Referenced in:

- 5.1. Responding to advertising events (2)

#shortened-local-name Referenced in:

- 5.1. Responding to advertising events

#manufacturer-specific-data Referenced in:

- 5.1. Responding to advertising events

#service-data Referenced in:

- 5.1. Responding to advertising events