# flutter_blue_plus vs. WebBLE

`flutter_blue_plus` is the most widely used Flutter plugin for Bluetooth Low Energy, wrapping iOS CoreBluetooth and Android BluetoothGatt for Flutter apps. WebBLE takes a different path: it keeps your app a web page and teaches iOS Safari the standard W3C `navigator.bluetooth` API through a Safari Web Extension. This page compares the two so you can pick the right tool.

## TL;DR

- **flutter_blue_plus** is for teams shipping a **Flutter app** to the App Store or Play Store.
- **WebBLE** is for teams shipping a **web page** (Flutter Web included, or any other framework) and who want that web page to talk to BLE on iOS Safari with no App Store submission of their own.

If your product is already a Flutter native app, keep `flutter_blue_plus`. If you are using Flutter Web, or any other web stack, WebBLE gives you the W3C Web Bluetooth API everywhere — including iOS Safari.

## Comparison

| Axis | flutter_blue_plus | WebBLE |
|------|-------------------|--------|
| **Runtime** | Flutter engine → platform channels → native BLE | Safari Web Extension → CoreBluetooth |
| **API surface** | Plugin-specific Dart API | Standard W3C `navigator.bluetooth` (via JS interop on Flutter Web) |
| **Target platforms** | iOS + Android native apps | Any browser with Web Bluetooth or with WebBLE on iOS |
| **Language** | Dart | TypeScript / JavaScript (callable from Dart via `dart:js_interop`) |
| **Distribution** | App Store / Play Store per release | Web deploy; user installs WebBLE extension once |
| **Update cadence** | Blocked by App Review | Same-day deploy |
| **PWA** | Flutter Web can be a PWA, but native BLE plugin does not apply there | Works natively in any PWA |
| **Code reuse between native app and Flutter Web** | BLE code forks per platform | Same `navigator.bluetooth` path on Chrome and iOS Safari |
| **Background BLE** | Full iOS background modes in the native app | Premium `window.webbleIOS.backgroundSync` via companion app |
| **Peripheral role** | Limited, plugin-dependent | Premium `window.webbleIOS.peripheral` |
| **Licence** | Source-available plugin | Polyfill free; iOS premium via companion app |
| **Scan UI** | Custom widgets | iOS system chooser enforced by the extension |

## When flutter_blue_plus is the right answer

- You are already building a Flutter mobile app.
- You need background modes and a full native shell.
- Flutter Web is not part of your distribution.

## When WebBLE is the right answer

- You are using, or considering, **Flutter Web**, and you want BLE to work on iOS without shipping a sibling native app.
- You are using **any web framework** (React, Vue, Svelte, Angular, Next.js, or vanilla HTML) and you need BLE on iPhone.
- You want same-day releases without Apple review.
- You want a codebase that works unchanged on Chrome desktop and on iOS Safari.

## Using WebBLE from Flutter Web

On Flutter Web, call `navigator.bluetooth` via `dart:js_interop`:

```dart
import 'dart:js_interop';

@JS('navigator.bluetooth.requestDevice')
external JSPromise<JSObject> _requestDevice(JSObject options);

Future<void> pair() async {
  final options = <String, Object?>{
    'filters': [{'services': ['heart_rate']}],
  }.jsify() as JSObject;
  final device = await _requestDevice(options).toDart;
  // ... proceed with device.gatt.connect() etc.
}
```

On desktop Chrome this uses the browser's built-in Web Bluetooth. On iOS Safari it uses the WebBLE extension's polyfill with the exact same call shape.

See the [quickstart](../quickstart.md) and the [API reference](../api-reference.md).
